Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!bellcore!att!occrsh!uokmax!servalan!rmtodd From: rmtodd@servalan.uucp (Richard Todd) Newsgroups: comp.unix.wizards Subject: Re: How does 'mv' rename directories? Summary: More than you ever wanted to know about moving directories. Message-ID: <1989Sep16.213600.260@servalan.uucp> Date: 16 Sep 89 21:36:00 GMT References: <544@isi.UUCP> <4158@buengc.BU.EDU> <1160@virtech.UUCP> <4195@buengc.BU.EDU> Reply-To: rmtodd@servalan.UUCP (Richard Todd) Organization: Ministry of Silly Walks Lines: 76 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!