stanonik (01/01/83)
Why shouldn't root change uid like any user when exec'ing a
setuid program? In the procedure getxfile in sys1.c (4.1bsd)
the following code appears:
/*
* set SUID/SGID protections, if no tracing
*/
if ((u.u_procp->p_flag&STRC)==0) {
#ifndef MELB
if(u.u_uid != 0)
#endif
{
u.u_uid = uid;
u.u_procp->p_uid = uid;
}
So, root processes are exempt from changing uid. Why? This
can cause problems when a daemon which runs as root interacts
with uucp. In particular, the arpanet daemons in bbn's tcp
software.
Thanks,
Ron Stanonik
ucbvax!sdcsvax!stanonik
or
stanonik@nprdc
lepreau (01/02/83)
Having root not honor setuid is a a complete botch; it's left over from when people thought the only use for setuid was to give more prviliges, not less or different ones. Just stick an option "MELB" in your config file-- it's right there waiting to be defined. We did that long ago to our benefit in v7, 2.8, and 4.1. 4.1a has fixed this and I presume 4.2 will too. -Jay
bentson (01/04/83)
/*
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.
*/
#include <stdio.h>
main(){
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
chris.umcp-cs@UDel-Relay (03/10/83)
From: Chris Torek <chris.umcp-cs@UDel-Relay>
From: hplabs!hao!csu-cs!bentson@UCB-C70
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 U*nx idiom is to create a file with "0" permission so
that a second attempt to create a file will fail....
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....
There is a better idiomatic expression:
unlink (tempfile);
creat (tempfile, mode);
if (link (tempfile, lockfile) < 0) {
/* someone else is doing the work */
exit (0);
}
The link system call will not let ANYONE link one file to another if
the second file exists.
guy (03/28/83)
1) If "root" executes a set-UID program under USG UNIX 5.0, I believe that the set-UID still takes effect. 2) Under USG UNIX 3.0 and later, you can have a creat-lock mechanism that works even for the super-user. Just don't use "creat"; use "open" instead. USG 3.0 (and, I believe, 4.2BSD) have made "open" a superset of "creat", which makes a lot of sense; why have two system calls when one will do? Furthermore, "open" can set various file-descriptor flags AND can leave the file descriptor open for reading AND writing after a create! You use the call: open(pathname, (open_mode)|O_CREAT|O_EXCL, creatmode); where "open_mode" is either O_WRONLY for a write-only file descriptor (O_WRONLY is a #define of 1, of course) or O_RDWR for a read/write file descriptor (O_RDWR is, of course, a #define of 2). This means: If the file does *not* exist, create it with mode "creatmode" and leave the resulting file descriptor open in the desired mode. If the file *does* exist, return an error. A clean and simple solution to a problem that has been in UNIX for a long while. I think 4.2BSD has a USG-style "open", too... Guy Harris RLG Corporation seismo!rlgvax!guy
dan@BBN-UNIX (03/28/83)
From: Dan Franklin <dan@BBN-UNIX> Perhaps the reason so many programs use the creat "solution" is because it's recommended by the manual! (See creat(2).) It's one of the few programming hints in Vol. 1--perhaps we should be grateful there aren't more. Dan