Can someone please explain the set-user-ID mechanism in Unix ? What was the rationale behind this design decision? How is it different from effective user id mechanism ?
You might know the normal read, write and execute permissions for files in unix.
However, in many applications, this type of permission structure--e.g. giving a given user either full permission to read a given file, or no permission at all to read the file--is too coarse. For this reason, Unix includes another permission bit, the
set-user-ID bit. If this bit is set for an executable file, then whenever a user other than the owner executes the file, that user acquires all the file read/write/execute privileges of the owner in accessing any of the owner's other files!
To set the set-user-ID bit for a file, type
chmod u+s filename
Make sure that you have set group-other execute permission too; it would be nice to have group-other read permission as well. All of this can be done with the single statement
chmod 4755 filename
It is also referred to as Saved UID. A file that is launched that has a Set-UID bit on, the saved UID will be the UID of the owner of the file. Otherwise, saved UID will be the Real UID.
What is effective uid ?
This UID is used to evaluate privileges of the process to perform a particular action. EUID can be changed either to Real UID, or Superuser UID if EUID!=0. If EUID=0, it can be changed to anything.
An example of such program is
passwd. If you list it in full, you will see that it has Set-UID bit and the owner is "root". When a normal user, say "mtk", runs
passwd, it starts with:
Real-UID = mtk Effective-UID = mtk Saved-UID = root
Rather than calling "set UID" and "effective UID" a mechanism, the whole concept of UIDs should be called that. The rationale for existence of the various UIDs are various troubles with privilege separation. Even regular (unprivileged) users sometimes need to do things (access resources) that only privileged users can. To achieve this easily, programs can change their UIDs. There are 3 types of these:
real UID - the UID that owns a process
effective UID - the UID a process currently runs as - this determines the actual capabilities of the process at any particular moment. This is also what
psshows you in the USER field.
saved set UID - placeholder used for switching back and forth between real and effective UIDs
The need for the last one arises from the fact, that regular users can only switch between these three and nothing else and a setuid program usually needs to know somehow, who was the user who loaded it (plus the real UID should not be changed since that would create even bigger mess).
mtk's expalanation is a good one.
passwd example is one of privilege escalation -- passwd always runs as root since it must alter files that only root is allowed to alter. This makes it important that the passwd executable not be prone to buffer overflows, etc, such that a clever normal user might be able to put it to uses for which is was not intended.
Another rationale is to protect the user in the same manner as you might use
su if you are logged in as root -- in order to diminish or restrict your privileges for a specific tasks, not escalate them. For example, if I have permission to start a daemon service that does not require access to my stuff and has its own stuff, which is all it needs (eg, a logger), running it suid will mean it only has access to that stuff and not mine or anyone elses.
Note that it is possible to set uid programmatically even if the suid bit is not set on the executable, however, that will not work for escalation. Ie., if you are a normal user and write a program that sets uid at some point itself, that program cannot switch to root. Apache works this way, I believe. It is usually started by root and has one process that then forks children which switch uid to a non-privelleged user (eg, "httpd"). Those child processes are what do the actual web server work.