mike@isi.UUCP (Mike Maloney) (09/13/89)
Dear wizards, I was recently trying to figure out why the 'mv' command on a Microport System V box would refused to rename directories. The commands cd mkdir junk mv junk junk2 would elicit the response: mv: cannot link 'junk' and 'junk2'. (No, 'junk2' did not already exist.) The same commands would work fine on another system RUNNING THE SAME OPERATING SYSTEM! I suspect that it is something subtle to do with permissions. But anyway, this led me to wonder how the 'mv' command can rename directories at all. The Rochkind book shows an implementation of 'mv' using link() and unlink(). If the target path is a directory it first checks to see if it already exists, and if it does, fails. If I understand him correctly, his version of 'mv' must have the Set-UID bit set and be owned be root because only processes with an effective UID of root can link directories. But on Microport, Xenix, and Sun Unix 4.0, /bin/mv is -rwxr-xr-x and is owned by 'bin'. How is 'mv' able to rename directories on a properly working system? -- Mike Maloney Integral Systems, Inc (301) 731-4233 5000 Philadelpha Way, Suite A, Lanham, MD 20706
cpcahil@virtech.UUCP (Conor P. Cahill) (09/14/89)
In article <544@isi.UUCP>, mike@isi.UUCP (Mike Maloney) writes: > But on Microport, Xenix, and Sun Unix 4.0, /bin/mv is -rwxr-xr-x and is > owned by 'bin'. How is 'mv' able to rename directories on a properly > working system? On system V 3.2 mv determines that a directory is to be moved and calls the program /usr/lib/mv_dir which is setuid to root. -- +-----------------------------------------------------------------------+ | Conor P. Cahill uunet!virtech!cpcahil 703-430-9247 ! | Virtual Technologies Inc., P. O. Box 876, Sterling, VA 22170 | +-----------------------------------------------------------------------+
guy@auspex.auspex.com (Guy Harris) (09/15/89)
>But on Microport, Xenix, and Sun Unix 4.0, /bin/mv is -rwxr-xr-x and is >owned by 'bin'. How is 'mv' able to rename directories on a properly >working system? In SunOS 4.0 - and in other systems that have the "rename()" system call from 4.[23]BSD, including all other SunOS releases, 4.[23]BSD themselves, Ultrix, etc. - it uses the "rename" call, which lets you move directories when it's safe, and doesn't require super-user privileges. I expect S5R4 to have this as well, and thus to render obsolete the program that S5R3, at least (and possibly Microport and Xenix, and maybe some older S5 releases, as well) uses to move directories.
bill@twwells.com (T. William Wells) (09/15/89)
In article <544@isi.UUCP> mike@isi.UUCP (Mike Maloney) writes:
: But on Microport, Xenix, and Sun Unix 4.0, /bin/mv is -rwxr-xr-x and is
: owned by 'bin'. How is 'mv' able to rename directories on a properly
: working system?
On my Microport, it calls /usr/lib/mv_dir to do the dirty work.
---
Bill { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com
bph@buengc.BU.EDU (Blair P. Houghton) (09/15/89)
In article <544@isi.UUCP> mike@isi.UUCP (Mike Maloney) writes: >Dear wizards, > >I was recently trying to figure out why the 'mv' command on a Microport >System V box would refused to rename directories. The commands > cd > mkdir junk > mv junk junk2 >would elicit the response: mv: cannot link 'junk' and 'junk2'. >(No, 'junk2' did not already exist.) The same commands would work >fine on another system RUNNING THE SAME OPERATING SYSTEM! Was it really 'junk1' and 'junk2' and not two files with long pathnames on different filesystems? >I suspect that it is something subtle to do with permissions. But anyway, >this led me to wonder how the 'mv' command can rename directories at all. Setuid root, and you can move the cpu. (That's not the case, here, it's just a funny thing to say. I do that, sometimes...) Oh, but it isn't a "setuid program"... >The Rochkind book shows an implementation of 'mv' using link() and unlink(). >If the target path is a directory it first checks to see if it already exists, >and if it does, fails. If I understand him correctly, his version of 'mv' >must have the Set-UID bit set and be owned be root because only processes >with an effective UID of root can link directories. Yep. One other case: if the source and destination are on different filesystems, it should effectively do mkdir() and then copy the directory recursively and then remove the source, again recursively. I've seen this done, and I'm wondering how much more effective it is, in software-installation routines by using tar(1) instead of a recursive copy. Any comments? >But on Microport, Xenix, and Sun Unix 4.0, /bin/mv is -rwxr-xr-x and is >owned by 'bin'. How is 'mv' able to rename directories on a properly >working system? Does mv not do setuid()? The setuid bit tells the OS to make the effective uid (that which is used to derive ownership) the owner of the program, but doesn't alter the possibility that there's a uid change in the program itself. (Sounds of digging Bach out of a back pack -- a Bachpach? :-S -- and rummaging around the indexed ref to setuid for verification, then the smell of paraphrasing fills the air) Since the owner of the files has placed his uid in the kernel's process table, the setuid() system call is free to change the effective uid to that one. The process is now permitted to change your files. Faux Plagiarism: p. 197, Bach, The Design of the UNIX O. S. "The real user ID identifies the user who is responsible for the running process. the effective user ID is used to assign ownership of newly created files, to check file access permissions, and to check permission to send signals to processes via the kill(2) system call." --Blair "Now comes the pain wherein kill(1) fails to setuid(2) to you because you are su-personating yourself from elsewhom..."
cpcahil@virtech.UUCP (Conor P. Cahill) (09/15/89)
In article <4158@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) writes: > Does mv not do setuid()? The setuid bit tells the OS to make the > effective uid (that which is used to derive ownership) the owner of the > program, but doesn't alter the possibility that there's a uid change in > the program itself. The only ids a program can setuid() to are as follows: 1. the effective user id of the process 2. the real user id of the process 3. (for system V) the "saved" user id of the process. The exception is if either the real user id or effective user id of the process is root, these limitations are rescinded (Sounds of digging Bach out of a back pack -- a > Bachpach? :-S -- and rummaging around the indexed ref to setuid for > verification, then the smell of paraphrasing fills the air) Since the > owner of the files has placed his uid in the kernel's process table, > the setuid() system call is free to change the effective uid to that > one. The process is now permitted to change your files. I'm not sure what you are talking about, but it sounds like you are talking about the method the kernel uses to interpret/execute the setuid-bits on the file. This automatically sets the effective user id and allows the program to change it's "real" user id to match the effective user id (or to change the effective user id back to the real user id) by using the setuid() syscall. If you aint root, the only way to get root uid privileges is to run a setuid-root program. -- +-----------------------------------------------------------------------+ | Conor P. Cahill uunet!virtech!cpcahil 703-430-9247 ! | Virtual Technologies Inc., P. O. Box 876, Sterling, VA 22170 | +-----------------------------------------------------------------------+
blm@6sigma.UUCP (Brian Matthews) (09/16/89)
In article <544@isi.UUCP> mike@isi.UUCP (Mike Maloney) writes: |I was recently trying to figure out why the 'mv' command on a Microport |System V box would refused to rename directories. I don't have Microport, but I do have a System V box, and directory moving is implemented by /usr/lib/mv_dir, which has permissions -r-sr-xr-x and is owned by root. mv uses mv_dir when renaming directories. -- Brian L. Matthews blm@6sigma.UUCP Six Sigma CASE, Inc. +1 206 854 6578 PO Box 40316, Bellevue, WA 98004
bph@buengc.BU.EDU (Blair P. Houghton) (09/16/89)
In article <1160@virtech.UUCP> cpcahil@virtech.UUCP (Conor P. Cahill) writes: >In article <4158@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) writes: >> Does mv not do setuid()? The setuid bit tells the OS to make the >> effective uid (that which is used to derive ownership) the owner of the >> program, but doesn't alter the possibility that there's a uid change in >> the program itself. > >The only ids a program can setuid() to are as follows: > > 1. the effective user id of the process > 2. the real user id of the process > 3. (for system V) the "saved" user id of the process. Okay. Nothing odd there. > The exception is if either the real user id or effective user id > of the process is root, these limitations are rescinded > > (Sounds of digging Bach out of a back pack -- a >> Bachpach? :-S -- and rummaging around the indexed ref to setuid for >> verification, then the smell of paraphrasing fills the air) Since the >> owner of the files has placed his uid in the kernel's process table, >> the setuid() system call is free to change the effective uid to that >> one. The process is now permitted to change your files. The real uid is the caller's uid. >I'm not sure what you are talking about, but it sounds like you are talking >about the method the kernel uses to interpret/execute the setuid-bits on >the file. No, That's what I was talking about up there where it says "setuid bit tells the OS..." Now, I'm talking about seteuid(getuid()), which makes the process-owner the owner of any files created by the process, and allows the process to access any files owned by the process owner. >This automatically sets the effective user id and allows the program >to change it's "real" user id to match the effective user id (or to change >the effective user id back to the real user id) by using the setuid() syscall. Like I said I said. (Hey. Now _I_ am starting to get lost... :-) >If you aint root, the only way to get root uid privileges is to run a >setuid-root program. True, but not in the paragdigm for mv(1). You only want mv(1) to be able to seteuid(2) to you, so you can move your own files. If mv(1) was setuid-root, you could move files all over the place, without a care. Hence, mv(1) is most definitely not setuid-root. I've been told that mv(1) may call mv_dir(?) (which doesn't exist on this machine... Encore's Umax is a vanilla BSD...) which is setuid-root (it is claimed). If this is how it's done, then the reason for the setuid-root could be to allow the moving of a directory across partition boundaries when the directory may contain files with an owner different from the directory-owner. Moving from one partition to the next requires a copy-then-unlink, whereas moving within a partition only requires a link-then-unlink. Linking to a file is a thing done on the directory containing that file, and so requires only the permission of the directory. Copying the file, however, requires permission to read from that file. The destination-writing can be accomplished by chown'ing once the file is written, but the source-reading absolutely requires the permission. But, basically, there's no need to become uid 0 when you're just moving files around in a partition. --Blair "Maybe. It's too much blither and not enough snarl. Is it clear?"
cpcahil@virtech.UUCP (Conor P. Cahill) (09/16/89)
In article <4195@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) writes: > In article <1160@virtech.UUCP> cpcahil@virtech.UUCP (Conor P. Cahill) writes: > >In article <4158@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) writes: [ much deleted junk... ] > > You only want mv(1) to be able to seteuid(2) to you, so you can move > your own files. If mv(1) was setuid-root, you could move files all > over the place, without a care. Hence, mv(1) is most definitely > not setuid-root. mv doesn't need to seteuid() since it is not a setuid program. The reason for the discussion about setuid was due to the fact that the original poster wanted to know how a directory could be moved. For BSD, this is simple because the rename(2) syscall allows this, but for SYSV, there is no rename syscall and the old link/unlink pair won't work for directories unless the effective user is root. The solution under sysV is to have a second program mv_dir (in /usr/lib) that is setuid root and is called by mv whenever a directory is to be moved. However the mv_dir program will only allow mv's within the same direcory. > I've been told that mv(1) may call mv_dir(?) (which doesn't exist > on this machine... Encore's Umax is a vanilla BSD...) which is > setuid-root (it is claimed). If this is how it's done, then the > reason for the setuid-root could be to allow the moving of a > directory across partition boundaries when the directory may > contain files with an owner different from the directory-owner. Nope. See above. > Linking to a file is a thing done on the directory containing that > file, and so requires only the permission of the directory. Copying It requires search permission to the source file directory and write permission to the target file direcory. > the file, however, requires permission to read from that file. > > But, basically, there's no need to become uid 0 when you're just moving > files around in a partition. The discussion was not about moving files, it was about moving directories and on a SYSV system you need to be euid root to accomplish it. -- +-----------------------------------------------------------------------+ | Conor P. Cahill uunet!virtech!cpcahil 703-430-9247 ! | Virtual Technologies Inc., P. O. Box 876, Sterling, VA 22170 | +-----------------------------------------------------------------------+
rmtodd@servalan.uucp (Richard Todd) (09/17/89)
In article <4195@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes: >You only want mv(1) to be able to seteuid(2) to you, so you can move >your own files. If mv(1) was setuid-root, you could move files all >over the place, without a care. Hence, mv(1) is most definitely >not setuid-root. mv(1) can only move files about without a care if mv(1) wasn't written to check the destination mode and ownership to see if you're allowed to move it. On some systems, mv(1) is setuid-root, and it does check permissions itself. On some systems, mv isn't setuid. >I've been told that mv(1) may call mv_dir(?) (which doesn't exist >on this machine... Encore's Umax is a vanilla BSD...) which is >setuid-root (it is claimed). If this is how it's done, then the >reason for the setuid-root could be to allow the moving of a >directory across partition boundaries when the directory may >contain files with an owner different from the directory-owner. Uh, not quite. First of all, I don't know of *any* version of the mv command that allows moving directories across partition boundaries. Secondly, there are at least three different ways mv(1) can be implemented on Unix systems, and different systems use different ones. 1. The mv command may be setuid root, and check to see if the real user has appropriate permissions on the target directory. The reason root privileges are needed is not, as you say, to do directory moves from one partition to another, since mv doesn't do that sort of move. The real reason is this: Suppose we want to move directory foo from /usr/bin to /usr/lib. Not only must a link be made to foo in /usr/lib and the existing link to foo in /usr/bin be removed, but the entry for ".." in the foo directory must be unlinked and a new link for ".." must be made pointing to the new parent. Ordinary (non-root) users aren't allowed to unlink "..", for the simple reason that one could accidentally make a tremendous mess of the filesystem. Thus the power to unlink ".." (or, for that matter, any directory) is restricted to root. On such systems, mkdir and rmdir have to be setuid-root, too, for the same reasons. I believe V7 used the above scheme; perhaps System III did as well. Minix, the V7 clone for PCs, definitely uses this scheme. 2. Same as above, except that mv is non-setuid, and whenever mv needs to move a directory, it calls mv_dir, a setuid program which does the actual directory move. mv itself doesn't call mv_dir when ordinary files are moved. System V systems without NFS apparently use this scheme. 3. The operation of moving a file/directory from one place to another (making the new link and unlinking the old one) can be done inside a system call, rename(2), which does all the grotty work of checking permissions, linking and unlinking, and making sure that ".." in the moved directory is set correctly. BSD systems and systems that have client-mode NFS have this system call, and mv on such systems uses this call; basically, mv just calls rename(2) directly for intra-partition moves, and does the copy of files for moves between partitions. mv is not setuid, and needs no setuid program to assist it. The reason you didn't find mv_dir on your Encore system is that it isn't needed there. Putting the functionality of "move" in the kernel has two advantages: 1, it removes the need for programs that move directories to mess with the ".." business and be setuid-root, and 2. the whole operation of moving the file/directory can be made atomic inside the kernel, thus avoiding certain race conditions. Also, it's useful on NFS systems, where the server you're mounting your filesystem from may not be a Unix system and may require some other (server-specific) technique to move files/directories; with rename(2), moves on remote-mounted filesystems are simply translated to appropriate calls to the NFS server. Mkdir and rmdir are also system calls on BSD or NFS systems, for much the same reasons. >But, basically, there's no need to become uid 0 when you're just moving >files around in a partition. Agreed. It's the business of moving directories around that sometimes causes problems. -- Richard Todd rmtodd@uokmax.ecn.uoknor.edu rmtodd@chinet.chi.il.us rmtodd@servalan.uucp Motorola Skates On Intel's Head!
gwyn@smoke.BRL.MIL (Doug Gwyn) (09/17/89)
In article <4195@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
-I've been told that mv(1) may call mv_dir(?) (which doesn't exist
-on this machine... Encore's Umax is a vanilla BSD...) which is
-setuid-root (it is claimed). If this is how it's done, then the
-reason for the setuid-root could be to allow the moving of a
-directory across partition boundaries when the directory may
-contain files with an owner different from the directory-owner.
No, the setUID-0 is because linking to directories requires privilege.
guy@auspex.auspex.com (Guy Harris) (09/19/89)
>Also, [the rename system call is] useful on NFS systems, where the server >you're mounting your filesystem from may not be a Unix system and may >require some other (server-specific) technique to move files/directories; with >rename(2), moves on remote-mounted filesystems are simply translated >to appropriate calls to the NFS server. Mkdir and rmdir are also >system calls on BSD or NFS systems, for much the same reasons. And also because: 1) the remote server may not give clients the ability to get root privileges (true both of NFS and RFS), so that even set-UID "root" programs on the client may not have the root privileges necessary to create, remove, or rename directories in the "traditional" fashion; and 2) the file system in question may, even if it's not a remote file system, not look enough like a "traditional" UNIX file system (either V7/S5 *or* BSD) for the "traditional" ways of creating, removing, or renaming directories to work, since systems with VFS or the File System Switch can have all sorts of different file system types plugged into them. S5R3, having both RFS and the File System Switch, also has "mkdir" and "rmdir" system calls; unfortunately, they forgot "rename", but that'll be fixed in S5R4.