Bug 42036 - mv does not respect file permissions when attempting to overwrite an existing file
Summary: mv does not respect file permissions when attempting to overwrite an existing...
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: fileutils
Version: 7.1
Hardware: i686
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Bernhard Rosenkraenzer
QA Contact: Aaron Brown
URL: http://cst-www.nrl.navy.mil/~mehl/mvb...
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2001-05-23 21:52 UTC by mehl+redhat
Modified: 2007-04-18 16:33 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2002-07-09 17:29:03 UTC
Embargoed:


Attachments (Terms of Use)

Description mehl+redhat 2001-05-23 21:52:43 UTC
From Bugzilla Helper:
User-Agent: Mozilla/4.76 [en] (X11; U; Linux 2.4.2-2 i686)

Description of problem:
If filea exists with permissions 444,  the command
$ mv fileb filea
renames fiileb to filea without warning.  Previous versions of RH (6.2)
ask:

mv: overwrite `filea', overriding mode 0444? 

which is the expected response in any version of Unix with which I am
familiar.

How reproducible:
Always

Steps to Reproduce:
1.  Create "file1" with text "This is file 1."
2.  Create "file2" with text "This is file 2."
3.  chmod 444 file1 file2
4.  mv file1 file2
	

Actual Results:  $ cat file2
This is file 1.

Expected Results:  $ mv file1 file2
mv: overwrite 'file2', overriding mode 0444? n
$ cat file2
This is file 2.

Additional info:

Comment 1 Dave Gotwisner 2002-07-09 17:26:45 UTC
I have tracked this down a little more, and sent a request to the bug-fileutils
also, but it looks to me like it may be a GLIBC issue.  I did something similar,
performing the following (as non-root):

touch foo1 foo2
chmod 400 foo1 foo2
mv foo1 foo2

On RH6.2, it generates the abovementioned warning.  on RH7.3, it does the move
blindly.  Cp and Rm perform correctly (on both systems). Doing straces on both
systems, yields the only apparent difference being a stat() call prior to the
move (which is done using rename(2)).

Looking at the sources for both versions, and building them, they both call a
function called euidaccess (or something very similar, don't have the code in
front of me right now), which is conditionally compiled based upon whether libc
has it or not.  In both versions, libc has it, so the local version is not
used.  Euidaccess is similar to the access(2) system call, except that it does
things based upon the effective user id (because of suid programs), and the
behavior apparently changed between versions of libc in RH.  The code
differences in MV and the fileutils code which calls it wouldn't account for the
extra stat (or lack thereof), or the behavioral difference.

Straces follow:

##################################
##################################
##################################
##################################
Fileutils 4.0p strace:

execve("/bin/mv", ["mv", "foo1", "foo2"], [/* 26 vars */]) = 0
brk(0)                                  = 0x80531f0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0) = 0x40014000
open("/etc/ld.so.preload", O_RDONLY)    = -1 ENOENT (No such file or
directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=34685, ...}) = 0
old_mmap(NULL, 34685, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40015000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=4101324, ...}) = 0
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\210\212"...,
4096) = 4096
old_mmap(NULL, 1001564, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) =
0x4001e000
mprotect(0x4010b000, 30812, PROT_NONE)  = 0
old_mmap(0x4010b000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED,
3, 0xec000) = 0x4010b000
old_mmap(0x4010f000, 14428, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x4010f000
close(3)                                = 0
mprotect(0x4001e000, 970752, PROT_READ|PROT_WRITE) = 0
mprotect(0x4001e000, 970752, PROT_READ|PROT_EXEC) = 0
munmap(0x40015000, 34685)               = 0
personality(PER_LINUX)                  = 0
getpid()                                = 17107
brk(0)                                  = 0x80531f0
brk(0x8053228)                          = 0x8053228
brk(0x8054000)                          = 0x8054000
open("/usr/share/locale/locale.alias", O_RDONLY) = 3
fstat64(0x3, 0xbfffb6ac)                = -1 ENOSYS (Function not
implemented)
fstat(3, {st_mode=S_IFREG|0644, st_size=2265, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0) = 0x40015000
read(3, "# Locale name alias data base.\n#"..., 4096) = 2265
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x40015000, 4096)                = 0
open("/usr/share/i18n/locale.alias", O_RDONLY) = -1 ENOENT (No such file
or directory)
open("/usr/share/locale/en_US/LC_MESSAGES", O_RDONLY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
close(3)                                = 0
open("/usr/share/locale/en_US/LC_MESSAGES/SYS_LC_MESSAGES", O_RDONLY) =
3
fstat(3, {st_mode=S_IFREG|0644, st_size=44, ...}) = 0
old_mmap(NULL, 44, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40015000
close(3)                                = 0
open("/usr/share/locale/en_US/LC_MONETARY", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=93, ...}) = 0
old_mmap(NULL, 93, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40016000
close(3)                                = 0
open("/usr/share/locale/en_US/LC_COLLATE", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=29970, ...}) = 0
old_mmap(NULL, 29970, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40113000
close(3)                                = 0
brk(0x8055000)                          = 0x8055000
open("/usr/share/locale/en_US/LC_TIME", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=508, ...}) = 0
old_mmap(NULL, 508, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40017000
close(3)                                = 0
open("/usr/share/locale/en_US/LC_NUMERIC", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=27, ...}) = 0
old_mmap(NULL, 27, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40018000
close(3)                                = 0
open("/usr/share/locale/en_US/LC_CTYPE", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=87756, ...}) = 0
old_mmap(NULL, 87756, PROT_READ, MAP_PRIVATE, 3, 0) = 0x4011b000
close(3)                                = 0
geteuid()                               = 500
umask(0)                                = 02
stat("foo2", {st_mode=S_IFREG|0400, st_size=0, ...}) = 0
lstat("foo1", {st_mode=S_IFREG|0400, st_size=0, ...}) = 0
lstat("foo2", {st_mode=S_IFREG|0400, st_size=0, ...}) = 0
access("foo2", W_OK)                    = -1 EACCES (Permission denied)
open("/usr/share/locale/en_US/LC_MESSAGES/fileutils.mo", O_RDONLY) = -1
ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/fileutils.mo", O_RDONLY) = -1
ENOENT (No such file or directory)

write(2, "mv: overwrite `foo2\', overriding"..., 44mv: overwrite `foo2',
overriding mode 0400? ) = 44
fstat(0, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0) = 0x40019000
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
read(0,
"\n", 1024)                     = 1
brk(0x8056000)                          = 0x8056000
_exit(1)                                = ?


##################################
##################################
##################################
##################################
The strace for the 4.1 fileutils is the following:


execve("/bin/mv", ["mv", "foo1", "foo2"], [/* 30 vars */]) = 0
uname({sys="Linux", node="dellunix.gotwisner.net", ...}) = 0
brk(0)                                  = 0x8053a04
open("/etc/ld.so.preload", O_RDONLY)    = -1 ENOENT (No such file or
directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=118112, ...}) = 0
old_mmap(NULL, 118112, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40014000
close(3)                                = 0
open("/lib/i686/libc.so.6", O_RDONLY)   = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0`u\1B4\0"...,
1024) = 1024
fstat64(3, {st_mode=S_IFREG|0755, st_size=1401027, ...}) = 0
old_mmap(0x42000000, 1264928, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) =
0x42000000
mprotect(0x4212c000, 36128, PROT_NONE)  = 0
old_mmap(0x4212c000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED,
3, 0x12c000) = 0x4212c000
old_mmap(0x42131000, 15648, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x42131000
close(3)                                = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0) = 0x40031000
munmap(0x40014000, 118112)              = 0
brk(0)                                  = 0x8053a04
brk(0x8053a34)                          = 0x8053a34
brk(0x8054000)                          = 0x8054000
geteuid32()                             = 500
umask(0)                                = 02
stat64("foo2", {st_mode=S_IFREG|0400, st_size=0, ...}) = 0
brk(0x8055000)                          = 0x8055000
lstat64("foo1", {st_mode=S_IFREG|0400, st_size=0, ...}) = 0
lstat64("foo2", {st_mode=S_IFREG|0400, st_size=0, ...}) = 0
rename("foo1", "foo2")                  = 0
_exit(0)                                = ?



Comment 2 Dave Gotwisner 2002-07-09 17:28:59 UTC
The severity of this bug should be HI because it causes data to be lost (it
removes the files that are marked as read-only)

Comment 3 Bernhard Rosenkraenzer 2002-08-29 22:36:04 UTC
Fixed in 4.1.9-10

Comment 4 Dave Gotwisner 2002-08-30 05:37:48 UTC
Thanks for the fix.  Where do I get it?  I checked your updates site for both
RH7.1 (which the original poster uses) and RH7.3 (which I use).  I prefer source
to binary.  The Rawhide tree indicates fileutils-4.1.9-9.src.rpm, not 4.1.9-10. 
Ditto for the x386 tree.


Note You need to log in before you can comment on or make changes to this bug.