Bug#1015273: coreutils: rm -d doesn't try to remove unreadable directories, lies in error message, with *fails to prompt* with -i

2023-02-20 Thread Jim Meyering
On Mon, Jul 18, 2022 at 12:21 PM наб  wrote:
> Package: coreutils
> Version: 8.32-4.1
> Severity: normal
>
> Dear Maintainer,
>
> Fun one for ya: the baseline:
> -- >8 --
> $ mkdir -p /tmp/psko
> $ rm -vid /tmp/psko
> rm: remove directory '/tmp/psko'? y
> removed directory '/tmp/psko'
> -- >8 --
>
> Bug a:
> -- >8 --
> $ mkdir -p /tmp/psko
> $ chmod -r /tmp/psko
> $ rm -vid /tmp/psko; echo $?
> rm: cannot remove '/tmp/psko': Directory not empty
> 1
> -- >8 --
>
> Absolutely 0 prompt, despite -i!
> That's very fun (and a POSIX violation)!
>
> Bug b:
> -- >8 --
> $ strace rm -vid /tmp/psko 2>&1 | grep -v locale
> execve("/bin/rm", ["rm", "-vid", "/tmp/psko"], 0xff8fbc48 /* 24 vars */) = 0
> /* ... */
> arch_prctl(ARCH_SET_FS, 0xf7f9e240) = 0
> mprotect(0xf7f8b000, 8192, PROT_READ)   = 0
> mprotect(0x40f000, 4096, PROT_READ) = 0
> mprotect(0xf7fcd000, 8192, PROT_READ)   = 0
> munmap(0xf7f96000, 26859)   = 0
> brk(NULL)   = 0xaa6000
> brk(0xac7000)   = 0xac7000
> brk(0xac8000)   = 0xac8000
> newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=3041504, ...}, 
> AT_EMPTY_PATH) = 0
> mmap(NULL, 2097152, PROT_READ, MAP_PRIVATE, 3, 0) = 0xf7a0
> mmap(NULL, 2596864, PROT_READ, MAP_PRIVATE, 3, 0x6d000) = 0xf7786000
> close(3)= 0
> ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
> newfstatat(AT_FDCWD, "/tmp/psko", {st_mode=S_IFDIR|0311, st_size=40, ...}, 
> AT_SYMLINK_NOFOLLOW) = 0
> openat(AT_FDCWD, "/tmp/psko", 
> O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_DIRECTORY) = -1 EACCES (Permission 
> denied)
> newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=2996, ...}, AT_EMPTY_PATH) = > 0
> read(3, "# Locale name alias data base.\n#"..., 4096) = 2996
> read(3, "", 4096)   = 0
> close(3)= 0
> write(2, "rm: ", 4rm: ) = 4
> write(2, "cannot remove '/tmp/psko'", 25cannot remove '/tmp/psko') = 25
> newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=1433, ...}, AT_EMPTY_PATH) = > 0
> mmap(NULL, 1433, PROT_READ, MAP_PRIVATE, 3, 0) = 0xf7f9c000
> close(3)= 0
> write(2, ": Directory not empty", 21: Directory not empty)   = 21
> write(2, "\n", 1
> )   = 1
> lseek(0, 0, SEEK_CUR)   = -1 ESPIPE (Illegal seek)
> close(0)= 0
> close(1)= 0
> close(2)= 0
> exit_group(1)   = ?
> +++ exited with 1 +++
> -- >8 --
>
> Can you spot a rmdir(2) equivalent? I can't! So why does it lie and say
> that it tried to remove it?
>
> Also, the directory /isn't nonempty/! Bug c:
> -- >8 --
> $ rmdir -v /tmp/psko/; echo $?
> rmdir: removing directory, '/tmp/psko/'
> 0
> -- >8 --
> And it's not there! Because, shockingly, there's nothing stopping you
> from removing it! So why on /earth/ is rm failing to prompt, failing to
> try to remove it, then lying that it had and failed with an obviously
> false errno?
>
> The same applies to just plain rm -d /tmp/psko (no -i)
> (except for bug a).

Thank you for the bug report.
I've attached a patch that fixes those bugs.


rm--dir.diff
Description: Binary data


Bug#1015273: coreutils: rm -d doesn't try to remove unreadable directories, lies in error message, with *fails to prompt* with -i

2022-07-18 Thread наб
Package: coreutils
Version: 8.32-4.1
Severity: normal

Dear Maintainer,

Fun one for ya: the baseline:
-- >8 --
$ mkdir -p /tmp/psko
$ rm -vid /tmp/psko
rm: remove directory '/tmp/psko'? y
removed directory '/tmp/psko'
-- >8 --

Bug a:
-- >8 --
$ mkdir -p /tmp/psko
$ chmod -r /tmp/psko
$ rm -vid /tmp/psko; echo $?
rm: cannot remove '/tmp/psko': Directory not empty
1
-- >8 --

Absolutely 0 prompt, despite -i!
That's very fun (and a POSIX violation)!

Bug b:
-- >8 --
$ strace rm -vid /tmp/psko 2>&1 | grep -v locale
execve("/bin/rm", ["rm", "-vid", "/tmp/psko"], 0xff8fbc48 /* 24 vars */) = 0
/* ... */
arch_prctl(ARCH_SET_FS, 0xf7f9e240) = 0
mprotect(0xf7f8b000, 8192, PROT_READ)   = 0
mprotect(0x40f000, 4096, PROT_READ) = 0
mprotect(0xf7fcd000, 8192, PROT_READ)   = 0
munmap(0xf7f96000, 26859)   = 0
brk(NULL)   = 0xaa6000
brk(0xac7000)   = 0xac7000
brk(0xac8000)   = 0xac8000
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=3041504, ...}, AT_EMPTY_PATH) 
= 0
mmap(NULL, 2097152, PROT_READ, MAP_PRIVATE, 3, 0) = 0xf7a0
mmap(NULL, 2596864, PROT_READ, MAP_PRIVATE, 3, 0x6d000) = 0xf7786000
close(3)= 0
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
newfstatat(AT_FDCWD, "/tmp/psko", {st_mode=S_IFDIR|0311, st_size=40, ...}, 
AT_SYMLINK_NOFOLLOW) = 0
openat(AT_FDCWD, "/tmp/psko", 
O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_DIRECTORY) = -1 EACCES (Permission 
denied)
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=2996, ...}, AT_EMPTY_PATH) = 0
read(3, "# Locale name alias data base.\n#"..., 4096) = 2996
read(3, "", 4096)   = 0
close(3)= 0
write(2, "rm: ", 4rm: ) = 4
write(2, "cannot remove '/tmp/psko'", 25cannot remove '/tmp/psko') = 25
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=1433, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 1433, PROT_READ, MAP_PRIVATE, 3, 0) = 0xf7f9c000
close(3)= 0
write(2, ": Directory not empty", 21: Directory not empty)   = 21
write(2, "\n", 1
)   = 1
lseek(0, 0, SEEK_CUR)   = -1 ESPIPE (Illegal seek)
close(0)= 0
close(1)= 0
close(2)= 0
exit_group(1)   = ?
+++ exited with 1 +++
-- >8 --

Can you spot a rmdir(2) equivalent? I can't! So why does it lie and say
that it tried to remove it?

Also, the directory /isn't nonempty/! Bug c:
-- >8 --
$ rmdir -v /tmp/psko/; echo $?
rmdir: removing directory, '/tmp/psko/'
0
-- >8 --
And it's not there! Because, shockingly, there's nothing stopping you
from removing it! So why on /earth/ is rm failing to prompt, failing to
try to remove it, then lying that it had and failed with an obviously
false errno?

The same applies to just plain rm -d /tmp/psko (no -i)
(except for bug a).

All three bugs are POSIX violations
(a   : 202x/D2.1  : XCU, rm, DESCRIPTION, 3.,
 b, c: 202x/D2.1, 2008: XCU, rm, DESCRIPTION, 4.),
but more importantly render coreutils rm not fit for purpose.

Best,
наб

-- System Information:
Debian Release: 11.4
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 
'stable-debug'), (500, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 5.10.0-16-amd64 (SMP w/24 CPU threads)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_FIRMWARE_WORKAROUND, 
TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_GB:en
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages coreutils depends on:
ii  libacl1  2.2.53-10
ii  libattr1 1:2.4.48-6
ii  libc62.31-13+deb11u3
ii  libgmp10 2:6.2.1+dfsg-1+deb11u1
ii  libselinux1  3.1-3

coreutils recommends no packages.

coreutils suggests no packages.

-- no debconf information


signature.asc
Description: PGP signature