Subject: Re: setreuid() and setregid()
To: der Mouse <mouse@Collatz.McRCIM.McGill.EDU>
From: Greg Hudson <ghudson@mit.edu>
List: tech-kern
Date: 05/25/1996 12:17:35
(Apologies if I'm one of N people to respond.)
> So, I can almost hear you saying, why bother with having multiple
> UIDs at all? The first need is for the ruid, so that a setuid
> program can tell who invoked it. The suid one arguably does not
> actually need; I don't quite understand why POSIX added it, but like
> the other POSIX braindamages, we appear to be stuck with it for now,
> because it's not quite braindamaged enough to make core dump it.
The saved uid is not present in NetBSD because of POSIX. In fact,
NetBSD does not define _POSIX_SAVED_IDS, because of a disagreement
over what should happen to setuid executables owned by someone other
than root (POSIX makes it impossible to permanently revoke the
privileges of the non-root user you're setuid to without doing an
exec()). We have the saved uid for the sake of allowing a process to
temporarily revoke privileges without corrupting the purpose of the
ruid.
POSIX model (with "process having appropriate privileges"
interpreted as "process euid is 0"):
- For a setuid root executable, setuid(getuid())
permanently revokes root privileges, setting
suid=euid=ruid.
- For a setuid joe executable, setuid(getuid())
temporarily revokes joe privileges, setting
euid=ruid. (exec() sets suid=euid, but short of
that, you can't avoid having an suid of joe.)
It's becoming increasingly clear to me that the POSIX
model is dictated by a particular interpretation of
the C2 security guidelines; revoking joe privileges is
not "lowering your clearance," so you can do it
temporarily, but revoking root privileges is, so you
can only do it permanently.
NetBSD model:
- For all setuid executables, setuid(getuid())
permanently revokes privileges, setting
suid=euid=ruid.
- For all setuid executables, seteuid(getuid())
temporarily revokes privileges, setting euid=ruid.
Fortunately, the NetBSD model is consistent with the POSIX model
(albeit without defining _POSIX_SAVED_IDS, so you have to explicitly
test for NetBSD) for the case of setuid root executables.
> The reasons for allowing a setuid process to switch its uid back to
> that of the invoker while still retaining the potential to return to
> what it had are (a) convenience of programming - it limits, to some
> extent, the damage bugs can do, and (b) the closing of some race
> windows.
(a) is not a terribly useful guideline, since any stack-smash bug can
be exploited to do a setuid() back to root. (b) is the important
issue; there are cases where you really want to do operations as a
non-root user (making sure you don't do anything to the filesystem
that said user can't do) before you're ready to revoke root
privileges. Doing a fork() and setuid() for such operations doesn't
always work when there are library interfaces in the way.