[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#45371: race condition in rm --preserve-root=all
From: |
Stephane Chazelas |
Subject: |
bug#45371: race condition in rm --preserve-root=all |
Date: |
Tue, 22 Dec 2020 16:10:18 +0000 |
Hello,
[reproduced with rm 8.30 and current git head on ubuntu 20.04 amd64]
Whilst trying to answer
https://unix.stackexchange.com/questions/505317/using-rm-one-file-system-to-only-delete-files-on-the-local-filesystem
I noticed that "rm -rf --preserve-root=all some-dir" was not race-free.
"some-dir", as the root of a filesystem could still be removed recursively if
the filesystem is mounted after "rm" has checked that "some-dir" was not a
mountpoint but before "rm" opens that directory.
That can be reproduced with gdb:
$ mkdir -p 1 2/dir
$ gdb --quiet --args rm -rf --preserve-root=all --one-file-system 1
Reading symbols from rm...
(gdb) break __fxstatat
Breakpoint 1 at 0x25e0
(gdb) break __lxstat
Breakpoint 2 at 0x2570
(gdb) break unlinkat
Breakpoint 3 at 0x24d0
(gdb) r
Starting program: /home/chazelas/install/cvs/coreutils/INSTALL.d/bin/rm -rf
--preserve-root=all --one-file-system 1
Breakpoint 2, __GI___lxstat (vers=1, name=0x55555556350c "/",
buf=0x7fffffffd820) at ../sysdeps/unix/sysv/linux/wordsize-64/lxstat.c:33
33 ../sysdeps/unix/sysv/linux/wordsize-64/lxstat.c: No such file or
directory.
(gdb) c
Continuing.
Breakpoint 1, __GI___fxstatat (vers=1, fd=-100, file=0x5555555705b0 "1",
st=0x555555570520, flag=256) at
../sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c:36
36 ../sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c: No such file or
directory.
(gdb) c
Continuing.
Breakpoint 2, __GI___lxstat (vers=1, name=0x555555570700 "1/..",
buf=0x7fffffffd7b0) at ../sysdeps/unix/sysv/linux/wordsize-64/lxstat.c:33
33 ../sysdeps/unix/sysv/linux/wordsize-64/lxstat.c: No such file or
directory.
(gdb) fin
Run till exit from #0 __GI___lxstat (vers=1, name=0x555555570700 "1/..",
buf=0x7fffffffd7b0) at ../sysdeps/unix/sysv/linux/wordsize-64/lxstat.c:33
0x000055555555839e in rm_fts (fts=0x55555556f200, ent=0x5555555704b0,
x=0x7fffffffd900) at src/remove.c:473
473 if (!parent || lstat (parent, &statbuf))
Value returned is $1 = 0
(gdb) !bindfs --no-allow-other 2 1
(gdb) !ls 1
dir
(gdb) c
Continuing.
Breakpoint 1, __GI___fxstatat (vers=1, fd=4, file=0x5555555706c0 "dir",
st=0x555555570630, flag=256) at
../sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c:36
36 ../sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c: No such file or
directory.
(gdb) c
Continuing.
Breakpoint 3, unlinkat () at ../sysdeps/unix/syscall-template.S:78
78 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) bt
#0 unlinkat () at ../sysdeps/unix/syscall-template.S:78
#1 0x0000555555557ddc in excise (fts=0x55555556f200, ent=0x5555555705c0,
x=0x7fffffffd900, is_dir=true) at src/remove.c:370
#2 0x0000555555558547 in rm_fts (fts=0x55555556f200, ent=0x5555555705c0,
x=0x7fffffffd900) at src/remove.c:508
#3 0x000055555555892d in rm (file=0x7fffffffda58, x=0x7fffffffd900) at
src/remove.c:608
#4 0x000055555555749d in main (argc=5, argv=0x7fffffffda38) at src/rm.c:370
(gdb)
bindfs is a fuse-based file system to mount one directory over
another. 2 is mounted over 1 after rm has compared the result of
stat("1") and stat("1/.."), and we see unlink("1/dir") being
done.
It seems to me that race window could be closed if "." and ".."
were compared after the directory is opened.
--
Stephane
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- bug#45371: race condition in rm --preserve-root=all,
Stephane Chazelas <=