[net.unix-wizards] root executing setuid programs

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