TechEarl

setuid, setgid, and the Sticky Bit Explained

What the s and t bits do, why /usr/bin/passwd is setuid and /tmp is sticky, how to set them, and how to audit a system for risky setuid binaries.

Ishan Karunaratne⏱️ 4 min readUpdated
Share thisCopied
What setuid, setgid, and the sticky bit do, why passwd is setuid and /tmp is sticky, and how to set and audit them.

Beyond the nine rwx bits there is a fourth octal digit holding three special bits: setuid, setgid, and the sticky bit. You have seen them in ls -l as an s or t where an x would be:

Terminal showing ls -l of /usr/bin/passwd with rws (setuid) and ls -ld of /tmp with a trailing t (sticky bit).
passwd shows rws: the setuid bit. /tmp ends in t: the sticky bit.

setuid (4): run as the file's owner

A setuid executable runs with the owner's identity, not the caller's. The canonical example is /usr/bin/passwd: it is owned by root and setuid, so an ordinary user running it can update /etc/shadow (which only root can write) for the duration of that command. You will see -rwsr-xr-x; the s replaces the owner's x.

bash
sudo chmod u+s /usr/local/bin/mytool     # or: chmod 4755

setuid on a program you do not fully trust is dangerous: any flaw in it becomes a root exploit. Set it sparingly, and never on a shell or interpreter.

setgid (2): run as the file's group, or inherit it on a directory

setgid does two different things:

  • On an executable, it runs with the file's group.
  • On a directory, new files created inside inherit the directory's group instead of the creator's primary group. This is the key to a shared project folder: everyone's new files stay group-owned by the team.
bash
sudo chmod g+s /srv/project       # or: chmod 2775   (directory: inherit group)

You will see drwxrwsr-x on such a directory; the s is in the group's slot.

Sticky bit (1): only the owner can delete, in a shared directory

On a world-writable directory, the sticky bit means a file can only be deleted or renamed by its owner (or root), even though anyone can create files there. That is why /tmp is drwxrwxrwt: everyone can write, but you cannot delete someone else's temp files.

bash
sudo chmod +t /shared/dropbox     # or: chmod 1777

The fourth digit, all together

In a four-digit octal mode, the leading digit is setuid (4) + setgid (2) + sticky (1):

ModeBitTypical use
4755setuida trusted root helper like passwd
2775setgida shared group directory
1777stickya world-writable scratch dir like /tmp

Audit setuid binaries (a real security task)

Attackers hunt for setuid binaries because each is a potential privilege-escalation path. List them:

bash
sudo find / -perm -4000 -type f 2>/dev/null      # all setuid files
sudo find / -perm -2000 -type f 2>/dev/null      # all setgid files

Compare against a known-good baseline; an unexpected setuid binary (especially one not from a package) is a red flag. The find -perm syntax is covered in find files by owner, group, or permission.

FAQ

See also

Sources

Authoritative references this article was fact-checked against.

TagsLinuxsetuidsetgidsticky bitPermissionsSecurity

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Software Systems Architect · Senior Software Engineer · Engineering Leadership

Software systems architect and senior software engineer with more than two decades designing, building, and running production software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Now a CTO, though what I write here is drawn from the full arc of that work, across architecture, engineering, and operations, not any single job.

Keep reading

Related posts

Understanding the Git staging area and what git add does to the index before a commit

The Git Staging Area Explained

The Git staging area (the index) is the in-between layer where you assemble exactly what goes into your next commit. Here is what git add really does, and why it exists.

Exclude a directory in find with -path './node_modules' -prune -o ... -print. Why the trailing -print is mandatory, the multi-directory form, the slower -not -path alternative, and BSD vs GNU notes.

How to Exclude a Directory in find (the -prune Pattern Explained)

find -path './node_modules' -prune -o -type f -print skips a directory subtree instead of walking into it. The pattern looks strange because -prune is an action, not a test, and the trailing -print is mandatory once you write an explicit action. The breakdown, the multi-directory form, the slower -not -path alternative, and when each one is the right call.