SUID, SGID, the sticky bit, and reading a mode cold
◈ 13 cardsThe three special bits explained from the contradictions they resolve, and how to read any twelve-bit mode — including the s/S and t/T cases — off a listing.
A contradiction the nine bits cannot resolve
Start with the problem, not the mechanism. Two requirements, both non-negotiable:
- Every user must be able to change their own password.
- No user may be able to write the password file, because writing it means editing everyone else’s entry as well as their own.
Nine permission bits cannot express that. Whatever you grant to run passwd is granted to everything else the user runs, and the file is either writable by them or it is not.
Set-user-ID (SUID) is the resolution. A program is normally executed with the effective user ID of whoever invoked it. With the SUID bit set, it is executed with the effective UID of the file’s owner instead. /usr/bin/passwd is owned by root and is SUID, so while it runs — and only while it runs — it holds root’s identity and can edit the password file. The privilege is attached to a single, carefully written program rather than to a user. The book names lp, mail, mkdir, mv and ps as other commands that have historically needed it; a non-system example is a game that must update a shared high-score table that players must not be able to edit by hand.
Set-group-ID (SGID) is the same mechanism at the group position: the process takes the group identity of the file’s group owner. Octal 2, or chmod g+s.
The sticky bit, and the /tmp contradiction
Another pair of requirements that the nine bits cannot express together:
/tmpmust be writable by everyone, so any program can create scratch files.- No user may delete another user’s scratch files.
But deletion is governed by the directory, and a directory anyone can write is a directory in which anyone can delete anything. The sticky bit (octal 1, or chmod +t) changes that rule for one directory: with it set, a user may only remove or rename entries they own. That is why /tmp is drwxrwxrwt.
The sticky bit also has a historical meaning on an executable: a hint to keep the program’s text segment resident in memory or in swap after it exits, so the next run starts faster. That use is obsolete from 4.4BSD onward, because paging algorithms already keep hot pages resident — and the platforms now disagree about it. PC-BSD refuses chmod +t on a non-directory (Inappropriate file type or format), Solaris still permits it, and Linux stores the bit but the kernel ignores it on a regular file. Name the platform when you answer this one.
Twelve bits, not nine
The full mode is twelve bits, and a four-digit octal mode is <special><owner><group><other>. The leading digit is built the same way the others are — from the weights 4 = SUID, 2 = SGID, 1 = sticky — so chmod 6754 f sets SUID and SGID with mode 754, and chmod 7755 f sets all three at once.
Where the special bits appear, and what the case means
There is no fourth triple in ls -l. Each special bit is displayed in the execute column of the triple it belongs to, which means that column has to encode two bits at once. It does that with case:
- lowercase — the special bit is set and the underlying execute bit is set;
- UPPERCASE — the special bit is set and the underlying execute bit is clear.
So s at the owner position is SUID with owner-execute on; S is SUID with owner-execute off. Same for s/S at the group position, and t/T at the other position for sticky.
Worked example — set, observe, clear the x bit, observe again
$ chmod 4755 pwtool
$ ls -l pwtool
-rwsr-xr-x 1 ada dev 8192 Sep 1 14:02 pwtool
$ chmod u-x pwtool
$ ls -l pwtool
-rwSr-xr-x 1 ada dev 8192 Sep 1 14:02 pwtool
One bit changed between those two listings, and it was not the SUID bit — that stayed set the whole time. The case flipped because owner-execute went away. (A SUID program with its execute bit cleared is a useless object, which is exactly why the capital letter is worth flagging: it usually means a mistake.)
Now read one cold. -rwSr-sr-t, character by character: - is a regular file; owner rw then S, so SUID is set and owner-execute is clear; group r- then s, so SGID is set and group-execute is set; other r- then t, so sticky is set and other-execute is set. Special digit = 4 + 2 + 1 = 7, owner = 6, group = 5, other = 5. The mode is 7655.