Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!columbia!rutgers!ames!ptsfa!ihnp4!occrsh!uokmax!rmtodd From: rmtodd@uokmax.UUCP (Richard Michael Todd) Newsgroups: comp.os.minix Subject: Re: SETUID on mkdir and rmdir Message-ID: <616@uokmax.UUCP> Date: Sat, 4-Jul-87 01:46:26 EDT Article-I.D.: uokmax.616 Posted: Sat Jul 4 01:46:26 1987 Date-Received: Sat, 4-Jul-87 20:20:35 EDT References: <8707030732.a029212@Louie.UDEL.EDU> Reply-To: rmtodd@uokmax.UUCP (Richard Michael Todd) Distribution: world Organization: University of Oklahoma, Norman Lines: 49 Summary: Seems to be a bug in forbidden() In article <8707030732.a029212@Louie.UDEL.EDU> ESC1332@ESOC (K.Keyte) writes: > >Does everyone have SETUID on their mkdir and rmdir? Standard UNIX does >not, as the mkdir and rmdir are just normal file operations. In MINIX, if >SETUID is on it means that any user has the permission to create and delete >directories anywhere is the file system. I've tried, however, taking the >SETUID bit off, but I can't seem to create ANY directories from normal user >accounts in this state. Standard UNIX? Whose UNIX do you mean by "Standard"? On the only UNIX system besides MINIX which I have access to (BSD4.2), mkdir and rmdir are, as you say, not set-uid. BUT, this is because BSD4.2 has mkdir() and rmdir() system calls which can be executed by any user. MINIX is based on Version 7 UNIX, and it is my understanding that V7 didn't have mkdir() or rmdir(). On MINIX, one has to use the system call mknod() to create a dir., and unlink() to remove one. Only root can use unlink() to unlink directories, and since mknod() can also create device special files, its use is also restricted to root. The mkdir and rmdir programs do contain code to check, using the access(2) system call, whether the real user has permission to write in the parent directory. Alas, the access call doesn't work as it should. For the reason behind this, look in the book's listing, starting at line 11757 (file fs/protect.c), for the access call handler code. Access calls forbidden(), the next subroutine in the listing, to see if the user has permission to do the specified function. Access passes a 1 in the third argument, to tell forbidden to do its tests with the real uid. (All the other calls to forbidden() are to check against euid.) Forbidden() starts out (line 11797) by setting test_uid and test_gid to whichever uid and gids are to be checked, according to the third parameter. However, at the next line (line 11800) is: if (super_user) { perm_bits = 07; } else { ... selecting which set of mode bits to test (user, group,other... Super_user is a global variable set whenever the EFFECTIVE uid is root, which is always when called from a set-uid root utility. Thus, whenever a set-uid root program makes an access(2) call, it never refuses permission. I haven't yet had a chance to try fixing it (having just only learned that the bug exists), but it should be fixable by changing the above test from if (super_user) { to if (test_uid == SU_UID) { thus testing whichever uid (real or effective) is requested by forbidden's caller. -------------------------------------------------------------------------- Richard Todd USSnail:820 Annie Court,Norman OK 73069 UUCP: {allegra!cbosgd|ihnp4}!okstate!uokmax!rmtodd