From: utzoo!decvax!harpo!seismo!hao!csu-cs!bentson Newsgroups: net.unix-wizards Title: root executing setuid programs Article-I.D.: csu-cs.1957 Posted: Tue Jan 4 10:31:23 1983 Received: Wed Jan 5 02:55:50 1983 /* For those of you who haven't followed the discussion regarding the superuser and the setuid bit in files, here's an example of what can go wrong. The line printer daemon and other utilities have a need for mutual exclusion because they can be simultaneously invoked by many users. Since there is no such intrinsic in U*nx, there is an idiomatic expression that provides the same effect. The "creat" call will: (1) if the file doesn't exist, create a new file with the given permissions; (2) if it does exist, and the permissions allow access, the file pointer will be positioned at the start of the file; (3) if the existing file's permissions are too restrictive of access, the call returns an error condition. The U*nx idiom is to create a file with "0" permission so that a second attempt to create a file will fail. Below is a short program that demonstrates this feature. HOWEVER, if either the program is owned by superuser and is setuid or the program is run by superuser the example will not work as predicted. This is because the superuser always has permission to do anything to any file. In the example program you'll find that the second "creat" will fail if you're an ordinary user, but it will succeed if you run the program as superuser or if the program is owned by the superuser and is setuid. I have been trying to figure out why a second invocation of the line printer daemon will occasionally fail to be inhibited (die). One possible cause now seems to be that if the daemon is started by a superuser at the same time that another copy is started, the superuser copy may succeed in the "creat" call when it "shouldn't have been able." Furthermore, some time ago I changed the ownership of the daemon to superuser and set the setuid bit so that the daemon could access spool files that were owned by the users and had limited read access. Thus every copy of the daemon was running superuser. I have since changed the spooler to call "umask(0)" when it starts and changed the daemon's ownership to "daemon" with setuid. Because of the "setuid" botch for files I have also had to add code to the daemon to "setuid(1)." Preliminary testing shows both problems have been solved properly. */ #includemain(){ int f; if((f = creat("/tmp/dummy")) < 0) printf("first create failed\n"); else printf("first create worked\n"); if((f = creat("/tmp/dummy")) < 0) printf("second create failed\n"); else printf("second create worked\n"); unlink("/tmp/dummy"); } I hope that this will shed light on the general topic of why one would want "setuid" to affect the superuser as well as other users. Randy Bentson Colo State U - Comp Sci Ft. Collins, CO