Survey of Unix Process Authority

Presotto & Ritchie’s Interprocess Communication in the Ninth Edition Unix System provides important background for the following material.

User IDs were originally invented to identify people and group IDs to identify disjoint sets of people. When a person is introduced to the system thru standard means he is assigned both a new user ID and an old or new group ID. His new user name, IDs and password are associated by the system.

For each Solaris process there are {real, saved, effective}×{user, group} IDs. On some machines there is also an “audit user ID”.

The process of logging in, (traditionally checking the password) creates a process whose ID’s are those associated by the system with the user name and password. Many system calls fail or succeed depending on these IDs and similar IDs attached to the thing operated on by the system call, such as a file.

The program obeyed by a process can query and change some of these IDs. This note explores the rules for doing this and explains some of the direct and indirect ramifications of changing these IDs. We will ignore super-user and root issues for now.
Field Name What Sets What Reads
Effective User ID login
setuid or seteuid - copied from real or saved
exec - copied from file owner
setreuid - copied from real
geteuid; Police
Real User ID login
setreuid - copied from effective
setuid
setuid, getuid
Saved User ID login
exec - copied from effective
setuid
setuid
Audit User ID login write log
Group IDs behave like User IDs. They usually have their own system calls.

I learn from man getgroups that there is a “supplemental group access list” associated with a process. I can find no mention of how this list effects what a program can do. There is some discussion in this description of the “set groups” command in the context of cgi.

System calls to examine: intro(2), getgroups

Drawbacks to setuid

Whenever there are three of some kind of thing (user ID’s per process here) more are probably needed. The several kinds of user ID referred to above suggest that Solaris is evolving these one at a time where a capability architecture would provide them all at once.

There is no command that a shell script can use that is analogous to setuid. Perhaps a general program could be made that could be invoked by a shell script that would perform a setuid and then finish by “exec”ing a named sub-shell script.

Shell scripts (command files) are frequently nested. Such a script cannot endow another script that it invokes with the invoker’s authority. Indeed a shell script cannot even perform a setuid function.

Here is some C code (gcc, but not ANSI) that describes how I think that Unix works:

#include <sys/types.h>
typedef struct{uid_t effective; uid_t real; uid_t saved;} Whos;
Whos whos; // current user IDs
uid_t super_user = 0;
void setuid(uid_t j){
  if(whos.effective == super_user) whos = (Whos){j, j, j};
  else if(j == whos.real || j == whos.saved) whos.effective = j;
}
void seteuid(uid_t j){
  if(whos.effective == super_user || j == whos.real || j == whos.saved)
      whos.effective = j;
}
void exec(int set_uID, uid_t file_uid){
  if(set_uID) whos = (Whos){file_uid, whos.real, file_uid};
}

See Proposed Patch for Linux