GNU bug report logs -
#45371
race condition in rm --preserve-root=all
Previous Next
To reply to this bug, email your comments to 45371 AT debbugs.gnu.org.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-coreutils <at> gnu.org
:
bug#45371
; Package
coreutils
.
(Tue, 22 Dec 2020 16:11:02 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Stephane Chazelas <stephane <at> chazelas.org>
:
New bug report received and forwarded. Copy sent to
bug-coreutils <at> gnu.org
.
(Tue, 22 Dec 2020 16:11:02 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
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
This bug report was last modified 3 years and 318 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.