|Summary:||rm fails in fileutils 4.0x-3.1 when it can't lstat the current directory|
|Product:||Red Hat Enterprise Linux 2.1||Reporter:||Terry Griffin <griffint>|
|Component:||fileutils||Assignee:||Tim Waugh <twaugh>|
|Status:||CLOSED ERRATA||QA Contact:||Mike McLean <mikem>|
|Version:||2.1||CC:||greg.marsden, kin.au, robinson, tao|
|Fixed In Version:||Doc Type:||Bug Fix|
|Doc Text:||Story Points:||---|
|Last Closed:||2004-08-18 15:52:33 UTC||Type:||---|
|oVirt Team:||---||RHEL 7.3 requirements from Atomic Host:|
|Cloudforms Team:||---||Target Upstream Version:|
Description Terry Griffin 2003-02-18 18:52:18 UTC
Description of problem: If the 'rm' command is executed while the current working directory is not searchable (+x permission) by the effective user, then rm will fail on a call to lstat() of the current directroy and the files specified on the command line will not be removed, even if the current user has the right to delete those files. Version-Release number of selected component (if applicable): 4.0x-3.1 How reproducible: Repeatable. Steps to Reproduce: 1. Create a directory. 2. CD in to that directory. 3. After CD'ing, remove search permissions from that directory (chmod -x). 4. Then while in that directory try to 'rm' a file. You'll get this error: rm: cannot lstat `.': Permission denied and the file will not be removed. Actual results: Files not removed. Expected results: Files removed. Additional info:
Comment 1 Tim Waugh 2003-02-18 19:09:35 UTC
Nothing fileutils can do about it; that's just how permissions work on directories I think. $ strace -feunlink perl -e 'unlink ("file")' unlink("file") = -1 EACCES (Permission denied)
Comment 2 Terry Griffin 2003-02-18 19:31:48 UTC
Well the previous version of fileutils didn't have this problem. So me thinks that it is not unavoidable.
Comment 3 Tim Waugh 2003-02-18 20:41:56 UTC
Which version, specifically?
Comment 4 Terry Griffin 2003-02-18 21:42:24 UTC
As there appears to be no older fileutils RPMs on my Red Hat update mirror, the previous version must have been the one from the Red Hat 7.0 CD-ROM which is fileutils-4.0x-3. The reason I know the previous version worked is that I had a /etc/procmailrc invoked spam-checking script that broke when fileutils was upgraded last Thursday. The script was doing an "rm -f" on a lock file created by procmail's 'lockfile' utility. In some instances the script's PWD happened to be one that was not searchable. But since the script never actually does anything in PWD this never mattered before the upgrade. I could imagine lots of system scripts breaking in this fashion, where before now they never cared about the current PWD because they didn't use it for anything. Now "rm" creates an unnecessary dependency on PWD's permissions.
Comment 5 Tim Waugh 2003-02-18 21:52:47 UTC
Do you mean that the file that you're trying to remove isn't in the directory in question? Please supply a real test case that I can try.
Comment 6 Terry Griffin 2003-02-18 22:28:44 UTC
Yes, the file I'm trying to delete is *not* in the current directory. It's elsewhere on the file system. The procedure is described in the original bug report. But I now see that step #4 is not clear. It should be: ------------- 4. Then while in that directory, 'rm' a file that resides elsewhere on the file system. You'll get this error: rm: cannot lstat `.': Permission denied and the file will not be removed. ------------- Sorry about that. The things a little lack of clarity will lead to.
Comment 7 Mike McLean 2003-02-19 00:38:56 UTC
I am unable to replicate this with the version mentioned: fileutils-4.0x-3.1 I used the following script: #!/bin/bash file=$(mktemp /tmp/file.XXXXXX) dir=$(mktemp -d /tmp/dir.XXXXXX) relpath="../$(basename $file)" echo "Using file $file and directory $dir" ls -ld $dir ls -l $file cd $dir touch $(seq 10) echo Changing permissions on $dir chmod a-rwx $dir ls -ld $dir echo "Removing $relpath (cwd is $PWD)" rm $relpath && ! [ -e $file ] || echo rm failed echo "Cleaning up" chmod u+rwx $dir rm -rf $dir
Comment 8 Terry Griffin 2003-02-19 01:19:25 UTC
Running your script on my system gives this output: Using file /tmp/file.qPHPcS and directory /tmp/dir.Jt050R drwx------ 2 terryg terryg 4096 Feb 18 17:13 /tmp/dir.Jt050R -rw------- 1 terryg terryg 0 Feb 18 17:13 /tmp/file.qPHPcS Changing permissions on /tmp/dir.Jt050R d--------- 2 terryg terryg 4096 Feb 18 17:13 /tmp/dir.Jt050R Removing ../file.qPHPcS (cwd is /tmp/dir.Jt050R) rm: cannot lstat `.': Permission denied rm failed Cleaning up
Comment 9 Tim Waugh 2003-03-03 16:11:28 UTC
I get the same result as Mike.
Comment 10 Terry Griffin 2003-03-04 03:25:50 UTC
Did you run the script as root or as a regular user? For me the script works fine as root but fails as a regular user.
Comment 11 Tim Waugh 2003-03-04 10:45:26 UTC
Okay, I see it now.
Comment 12 Tim Waugh 2004-05-12 08:28:23 UTC
*** Bug 123071 has been marked as a duplicate of this bug. ***
Comment 13 Greg Marsden 2004-05-13 16:00:20 UTC
If the current directory does not exist, rm fails immediately. This is a result of a bad security fix for fileutils 4.1 and is fixed in 4.5 and later. The problem is only on AS2.1 A trivial testcase to reproduce this problem is:  gmarsden@ca-build1:/tmp$ mkdir rmtest  gmarsden@ca-build1:/tmp$ cd rmtest/  gmarsden@ca-build1:/tmp/rmtest$ touch /tmp/file1  gmarsden@ca-build1:/tmp/rmtest$ chmod 0 .  gmarsden@ca-build1:/tmp/rmtest$ rm -f /tmp/file1 rm: cannot lstat `.': Permission denied  gmarsden@ca-build1:/tmp/rmtest$ ls -l /tmp/file1 -rw-rw-r-- 1 gmarsden gmarsden 0 May 7 18:52 /tmp/file1 The offending code is actually flagged with a FIXME in the AS2.1 fileutils package and results from attempting to do an lstat on the current directory to prevent a security exploit. However, this check should not happen when not removing recursive directories.
Comment 14 Greg Marsden 2004-05-17 19:23:10 UTC
Created attachment 100278 [details] patch to fix rm behavior. Patch to fix rm for file-delete
Comment 16 Tim Waugh 2004-05-19 16:04:49 UTC
The rm.c part looks like it is reversed to me. Before: ==> if (lstat (...)) error; carry on; <== After: ==> if (lstat (...)) carry on; else error; <== Shouldn't the if/else clauses be the other way around? In the first hunk from remove.c, 'sb' is initialised from a checked lstat() called after a successful chdir(), so there's no reason I can see that sb->st_dev or sb->st_ino would be NULL. Did you mean (*fs)->st_dev/ino? Similarly for hunk #2 from remove.c: why would sb have NULL st_dev/st_ino here?
Comment 17 Greg Marsden 2004-05-19 17:06:28 UTC
Created attachment 100350 [details] rmfix patch, take 2 Ok, that was silly, thanks for noticing the reversed call path. Here's a new, cleaner, patch. The only parameter which must be checked for null is cwd_dev_ino,which is passed from the initial lstat into the remove_dir function, and could be set to null by the new code in rm.c. As you noticed, only one null check is required in remove.c There's no need to check *fs, as that lstat is being done from the present directory.
Comment 18 Tim Waugh 2004-05-20 11:00:16 UTC
Yes, this patch looks good -- thanks.
Comment 23 John Flanagan 2004-08-18 15:52:33 UTC
An errata has been issued which should help the problem described in this bug report. This report is therefore being closed with a resolution of ERRATA. For more information on the solution and/or where to find the updated files, please follow the link below. You may reopen this bug report if the solution does not work for you. http://rhn.redhat.com/errata/RHBA-2004-230.html