A question came up on the Stack Exchange site Unix & Linux in which I wrote up a pretty good answer, that describes some of the mechanics of how a process deals with its user credentials, so I’m adding my writeup to the blog.
It really comes down to what makes up a process in Unix. A process can come into existence in one of 2 ways. Either via the
fork() function or through one of the
exec() functions in C.
fork() basically just makes a copy of the current process, but assigns it a new process ID (PID). It’s a child of the original process. You can see this relationship in the output of @[email protected]:
1 2 3 4 5 6 7
$ ps axjf PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 1 5255 1964 1964 ? -1 Sl 500 0:39 gnome-terminal 5255 5259 1964 1964 ? -1 S 500 0:00 \_ gnome-pty-helper 5255 18422 18422 18422 pts/1 18422 Ss+ 500 0:01 \_ bash 5255 30473 30473 30473 pts/4 30473 Ss+ 500 0:00 \_ bash 30473 782 782 30473 pts/4 30473 Sl 500 1:14 | \_ evince s.pdf
Here you can see that
gnome-terminal is the parent process (PID = 5255) and that
bash is it’s child (PID = 18422, PPID = 5255).
When a process forks from its parent, it “inherits” certain things, such as copies of all the file descriptors that the parent currently has for open files and the parent’s user and group IDs.
NOTE1: PPID = Parent Process ID.
NOTE2: The last 2 are what identify what file and group permissions this process will have when accessing the file system.
So if a process just inherits its user and group ID from its parent, then why isn’t everything just owned by root or a single user? This is where
exec() comes in.
exec() Part #1
exec() family of functions, specifically
execve(), “replace” a current process image with a new process image. The terminology “process image” is really just a file, i.e. an executable on disk. So this is how a bash script can execute a program such as
So what about the user ID and group ID? Well to understand that let’s first discuss the concept of “Persona”.
At any time, each process has an effective user ID, an effective group ID, and a set of supplementary group IDs. These IDs determine the privileges of the process. They are collectively called the [persona of the process]1, because they determine “who it is” for purposes of access control.
exec() Part #2
So in addition to being able to swap out the “process image”,
exec() can also change the user & group IDs from the original “real” ones to “effective” ones.
For this demonstration I’m going to show you what happens when we start out in a shell as our default UID/GID, and then spawn a child shell using one of my supplementary GIDs, making it the child shell’s effective GID.
To perform this I’m going to make use of the unix command
newgrp allows you to spawn a new shell passing it the supplementary group that I’d like to make my effective GID.
$ id -a uid=500(saml) gid=501(saml) groups=501(saml),502(vboxusers),503(jupiter)
We can see that this shell is currently configured with my default UID/GID of
saml. Touching some files shows that this is the case as well:
1 2 3 4 5 6
$ touch afile1 $ touch afile2 $ ls -l total 0 -rw-rw-r-- 1 saml saml 0 May 21 23:47 afile1 -rw-rw-r-- 1 saml saml 0 May 21 23:47 afile2
Now we make our supplementary group
jupiter the effective GID:
1 2 3
$ newgrp jupiter $ id -a uid=500(saml) gid=503(jupiter) groups=501(saml),502(vboxusers),503(jupiter)
Now if we touch some files:
1 2 3 4 5 6 7 8
$ touch afile3 $ touch afile4 $ ls -l total 0 -rw-rw-r-- 1 saml saml 0 May 21 23:47 afile1 -rw-rw-r-- 1 saml saml 0 May 21 23:47 afile2 -rw-r--r-- 1 saml jupiter 0 May 21 23:49 afile3 -rw-r--r-- 1 saml jupiter 0 May 21 23:49 afile4
We see that the shell’s effective GID is
jupiter, so any interactions with the disk result in files being created with
jupiter rather than my normal default group of