Beyond the familiar read/write/execute bits, Linux has three special permission bits: setuid, setgid and the sticky bit. You meet them in shared directories, in /tmp, and in programs like passwd and sudo. Knowing them helps with both team setups and security audits.

Overview

Bit Octal On files On directories
setuid 4000 Runs as the file’s owner (ignored on Linux)
setgid 2000 Runs with the file’s group New files inherit the directory’s group
sticky 1000 (ignored) Only a file’s owner can delete or rename it

The special bits form the first digit of a four-digit mode: chmod 2775 dir, chmod 1777 /tmp.

Reading them in ls

They replace the x in the permission string:

ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root … /usr/bin/passwd      # s in owner position = setuid

ls -ld /srv/shared
drwxrwsr-x 2 root webteam … /srv/shared       # s in group position = setgid

ls -ld /tmp
drwxrwxrwt 15 root root … /tmp                # t in others position = sticky

A lowercase s or t means the bit is set and the underlying execute bit is too. An uppercase S or T means the special bit is set without execute. That’s usually a mistake, for example chmod 2664 on a directory nobody can enter.

setuid: run as the owner

When a setuid file runs, the process gets the file owner’s privileges instead of the caller’s. That’s how a normal user can change their password: /usr/bin/passwd is owned by root and setuid, so it can write /etc/shadow.

Other examples: sudo, su, mount, ping (on older systems) and newgrp.

Security: a setuid-root program with a bug, or one that can be told to run arbitrary commands, gives an attacker root. That’s why:

  • Linux ignores setuid on shell scripts. Use sudo rules for scripts instead.
  • You should never set setuid on general tools like bash, find, vim or python. Each of those can spawn a root shell.
  • Filesystems for untrusted content should be mounted nosuid.
chmod u+s file      # set (or chmod 4755 file)
chmod u-s file      # remove

setgid on directories: shared group folders

This is the most useful special bit in day-to-day admin work. On a directory, setgid makes every new file and subdirectory inherit the directory’s group instead of the creator’s primary group:

sudo groupadd webteam
sudo chown root:webteam /srv/shared
sudo chmod 2775 /srv/shared        # or: chmod g+s /srv/shared

Now when alice creates /srv/shared/report.txt, it belongs to group webteam, so bob (also in webteam) can work with it. Subdirectories inherit the setgid bit too, so the whole tree stays consistent.

Combine it with a 002 umask, or default ACLs, so files are also group-writable. See umask and Linux groups.

On files, setgid makes the program run with the file’s group. It’s used by a few system tools, such as wall and write (group tty).

Sticky bit: protect files in shared directories

In a world-writable directory, anyone could normally delete anyone’s files. The sticky bit restricts deletion and renaming to the file’s owner, the directory owner and root:

ls -ld /tmp /var/tmp
drwxrwxrwt …

Use it on any directory where several users write but shouldn’t touch each other’s files:

sudo mkdir /srv/dropbox
sudo chmod 1777 /srv/dropbox       # or: chmod +t /srv/dropbox

Setting and removing with chmod

chmod 4755 file      # setuid + 755
chmod 2775 dir       # setgid + 775
chmod 1777 dir       # sticky + 777
chmod g+s dir        # symbolic
chmod o+t dir
chmod u-s,g-s file   # remove

Note: a plain numeric chmod 755 dir does not clear setgid on directories with GNU chmod. Clear it explicitly with chmod g-s dir, or use a five-digit mode like chmod 00755 dir.

Audit setuid and setgid files

Unexpected setuid binaries are a classic backdoor and privilege-escalation path. List them:

sudo find / -xdev -perm -4000 -type f -exec ls -l {} + 2>/dev/null   # setuid
sudo find / -xdev -perm -2000 -type f -exec ls -l {} + 2>/dev/null   # setgid

Compare the list against a known-good baseline, or against package ownership:

dpkg -S /usr/bin/passwd       # Debian/Ubuntu: which package owns it
rpm -qf /usr/bin/passwd       # RHEL family

A setuid file that no package owns, especially in /tmp, /home or /var/www, deserves immediate investigation. Tools like Lynis and AIDE automate these checks. See Linux server hardening checklist.

Capabilities: the modern alternative

Instead of full setuid root, Linux capabilities grant single privileges. For example, a non-root app can bind ports below 1024:

sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/myserver
getcap /usr/local/bin/myserver

For services, systemd’s AmbientCapabilities=CAP_NET_BIND_SERVICE does the same without touching the binary.

Quick reference

Goal Command
Shared group folder chmod 2775 dir
Shared drop folder chmod 1777 dir
Remove setgid chmod g-s dir
Find setuid files find / -xdev -perm -4000 -type f
Bind low port without root setcap cap_net_bind_service=+ep bin

Related: chmod and ACLs.

  • Linux
  • Permissions
  • Security