Re: 2.0.29 sysctl.c if(grp == current->euid)

Theodore Y. Ts'o (tytso@MIT.EDU)
Tue, 11 Feb 1997 17:04:28 -0500


Date: Tue, 11 Feb 1997 07:12:01 +0000
From: David A Rusling <rusling@linux.reo.dec.com>

I'm not sure either, I'm confused by Linux's use of uids and gids, for
every process it keeps 4 variants of each (plus an array of group ids):

uid, suid, euid, fsuid
gid, sgid, egid, fsgid

So far as I can tell from reading the code, the fsuid and fsgid are
used when checking access to files and they are there because some
executables may change the uid and gid of the executing process (for
the purposes of privilege protection). euid and egid are the
effective ids (based on {uid, suid} and {gid, sgid}?). If someone
could clarify this it would be helpful.

OK, here's the quick summary. The four types of uid (gids are
analogous) that are associated with each process are:

* real (uid)
* effective (euid)
* saved (suid)
* filesystem (fsuid)

The real uid identifies who the process "really" belongs to. So if I
run a particular program, the real uid will have my uid attached to it.
All permissions check (except for filesystem access) are checked based
on the effective uid. If you execute a setuid program, the effective
uid is set to the uid of the program, while the real uid is still
yours. So, the setuid program can execute with privileges because its
effective uid is set appropriately, but it can figure out on whose
behalf it is running by checking the real uid.

The fsuid is normally the same as the euid (system calls which change
the euid also change the fsuid). However, the setfsuid() only sets
fsuid, without changing the effective uid. The fsuid is only needed for
the user-mode nfs server, which needs to access files as if it were some
particular user. It used to do this by changing its effective uid;
however, POSIX specifies some rules about when a program is allowed to
send a signal to a process, and it turns out that by changing the
effective uid to some user process, it meant that a user process running
on the NFS server could kill the nfs user proceoss if the attacker timed
things just right. By only changing the fsuid, and keeping the
effective uid the same, it prevents the attacker from making this
attack.

The saved userid is mandated by POSIX, and it's how POSIX handles
switching back and forth between two user ids in a setuid program --- as
long as both user-ids are not root. The typical BSD way of handling
this is to simply use setreuid(x, y) to swap the real and effective user
id's. However, POSIX didn't want to support setreuid(). Instead, POSIX
supports only one system call --- setuid(uid), and setuid() when run as
a non-root account sets the effective user id to either the real user-id
or the saved-user id, where the saved-user id is the "saved" effective
user-id when the setuid program was first started. If setuid(x) is run
as root, then the real, effective, and saved user-id is set to X.
The bottom line is that suid is only needed by setuid(), and you
shouldn't really need to worry about it. If you want more information,
see the POSIX.1 spec, preferably not just after you've had lunch. (IMO,
the POSIX people really botched the definition of setuid() in the
standard.)

- Ted