Skip to content
Go back

Sticky Bit, Setuid, Setgid: Linux Special Permissions Explained

· Updated:
By KingPin 8 min read
Sticky Bit, Setuid, Setgid: Linux Special Permissions Explained
Contents

You see a file with permissions 4755 or a directory with permissions 1777. Those extra digits are special permissions. They’re powerful and dangerous if you don’t understand them.

Let’s demystify sticky bit, setuid, and setgid.

The Permission Basics (Quick Review)

Normal permissions are three digits: rwx for owner, group, and others.

-rw-r--r-- 1 alice users 1024 Apr 16 10:00 file.txt

Read the permissions as:

Special permissions are a fourth digit prepended to these three.

Setuid (Set User ID)

What it does: When you execute a setuid binary, it runs as the owner, not you.

Symbol: s in the owner execute position (or S if owner can’t execute)

Example: The sudo binary

Terminal window
$ ls -l /usr/bin/sudo
-rwsr-xr-x 1 root root 236K Apr 16 10:00 /usr/bin/sudo

The s in position 1 means “setuid”. When you run sudo, it runs as root, even though you executed it.

How to set it:

Terminal window
chmod u+s /path/to/binary
# Or numerically
chmod 4755 /path/to/binary

The first digit is 4 for setuid.

Why it’s dangerous:

If you setuid a binary with a vulnerability, anyone can exploit it to become the owner. That’s why /bin/passwd (which changes your password) is setuid root, you need root privileges to modify /etc/shadow, but regular users need to be able to run it.

Real-world examples:

Terminal window
ls -l /usr/bin/passwd /usr/bin/sudo /usr/bin/fusermount
# All have setuid bit set

These tools need elevated privileges but regular users need to run them.

Not every root tool needs the bit, though: run0 gets root without setuid by asking systemd to start the command for you.

Security rule: Never setuid a script (#! shell or Python). Only setuid compiled binaries, and only if you’ve audited the code.

It’s also pointless on Linux. The kernel ignores the setuid and setgid bits on scripts entirely. Set the bit on a #! script and chmod will happily show you the s, but execve() runs the interpreter as your own uid anyway. That bit on a script is just a lie waiting to confuse the next admin who reads ls -l.

Setgid (Set Group ID)

What it does: When you execute a setgid binary, it runs as the group owner, not your group. On directories, newly created files inherit the directory’s group.

Symbol: s in the group execute position (or S if group can’t execute)

Example: A shared project directory

Terminal window
$ mkdir /project
$ chown :project /project
$ chmod g+s /project
$ ls -ld /project
drwxr-sr-x 2 alice project 4096 Apr 16 10:00 /project

The s in the group execute position means “setgid”. Now any file created in /project automatically belongs to the project group, regardless of who creates it.

How to set it on a directory:

Terminal window
chmod g+s /path/to/directory
# Or numerically
chmod 2755 /path/to/directory

The first digit is 2 for setgid.

Real-world use case: Shared team directories

Terminal window
mkdir -p /shared/docs
chown alice:team /shared/docs
chmod 2775 /shared/docs
# Now anyone in the 'team' group can create files here,
# and those files automatically belong to 'team'

Check it:

Terminal window
$ touch /shared/docs/test.txt
$ ls -l /shared/docs/test.txt
-rw-r--r-- 1 alice team 0 Apr 16 10:00 test.txt
# File is owned by alice:team, even though alice created it

On binaries: Setgid binaries are rare and work similarly to setuid, the binary runs with the group’s permissions.

Sticky Bit

What it does: On directories, it restricts deletion. You can only delete files you own, even if you have write permission to the directory.

Symbol: t in the others execute position (or T if others can’t execute)

Example: /tmp

Terminal window
$ ls -ld /tmp
drwxrwxrwt 10 root root 4096 Apr 16 16:15 /tmp

The t at the end means sticky bit. Anyone can create files in /tmp, but you can only delete your own.

Without sticky bit, anyone could delete anyone else’s files:

Terminal window
rm /tmp/someone_elses_file.txt # This would work without sticky bit

With sticky bit, you get “Operation not permitted”.

How to set it:

Terminal window
chmod o+t /path/to/directory
# Or numerically
chmod 1777 /path/to/directory

The first digit is 1 for sticky bit.

Real-world use case: Shared upload directories

Terminal window
mkdir /uploads
chmod 1777 /uploads
# Everyone can write files, but only the owner can delete them

Prevents users from deleting each other’s uploads.

Reading Special Permissions

When you see permissions, decode them from left to right:

-rwsr-xr-x
^ ^
| +-- setuid (runs as owner)
+------ regular file (not special file type)

Or with all three special bits:

-rwsr-sr-t
^ ^ ^
| | +-- sticky bit (only owner can delete)
| +---- setgid (inherited group)
+------- setuid (runs as owner)

Numerically:

4755
^
+-- setuid bit (4)
2755
^
+-- setgid bit (2)
1777
^
+-- sticky bit (1)

You can combine them:

7755 = setuid (4) + setgid (2) + sticky bit (1) + 755 permissions

Viewing Special Bits in Detail

Use stat:

Terminal window
stat /usr/bin/sudo
# Shows: Access: (4755/-rwsr-xr-x) Uid: (0/root) Gid: (0/root)
stat /tmp
# Shows: Access: (1777/drwxrwxrwt)

Or use find:

Terminal window
# Find all setuid binaries on the system
find / -perm -4000 -type f 2>/dev/null
# Find all setgid binaries
find / -perm -2000 -type f 2>/dev/null
# Find directories with sticky bit
find / -perm -1000 -type d 2>/dev/null

Security Audit

Audit setuid binaries on your system:

Terminal window
find / -perm -4000 -type f -exec ls -l {} \; 2>/dev/null
# Sample output:
# -rwsr-xr-x 1 root root /usr/bin/sudo
# -rwsr-xr-x 1 root root /usr/bin/passwd
# -rwsr-xr-x 1 root root /usr/bin/chfn

Each of these is a potential security entry point. Any vulnerability here is a privilege escalation.

Common Real-World Examples

setuid:

Terminal window
ls -l /usr/bin/sudo /usr/bin/passwd /usr/bin/chsh /usr/bin/fusermount
# All setuid for security/functionality reasons

setgid on directories:

Terminal window
mkdir /project
chown alice:project /project
chmod 2770 /project # rwxrwx--- with setgid
# All files created in /project belong to 'project' group

sticky bit:

Terminal window
ls -ld /tmp /var/tmp
# Both have sticky bit to prevent accidental deletion

The Security Rule of Thumb

You’ll rarely need to set these yourself. But when you do, understand the implications. A wrong setuid bit is a privilege escalation waiting to happen.

Your system already has examples on binaries like sudo and passwd. That’s by design, they need elevated privileges to work. But any setuid binary you create is a security risk unless thoroughly audited.

Common Questions

What is the difference between setuid, setgid, and the sticky bit?

Setuid makes a binary run as its file owner. Setgid makes a binary run as its group owner, and makes new files in a directory inherit that directory’s group. The sticky bit limits deletion in a directory to the file’s owner. Their numeric digits are 4, 2, and 1.

Does setuid work on shell scripts in Linux?

No. The Linux kernel ignores the setuid and setgid bits on scripts. The chmod command still shows the s, but execve() runs the interpreter as your own uid. The safe rule is to setuid only compiled binaries, and only after you audit the code.

How do I find all setuid files on Linux?

Run find / -perm -4000 -type f 2>/dev/null to list every setuid file on the system. Use -perm -2000 for setgid files instead. Review each result, because every setuid binary is a potential privilege escalation entry point if it has a vulnerability.

What does a four-digit mode like 2775 mean in chmod?

The first digit holds the special bits: 4 for setuid, 2 for setgid, and 1 for the sticky bit. The last three digits are the normal owner, group, and others permissions. A mode of 2775 on a directory sets setgid, so new files there belong to the directory’s group.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Previous Post
The Firewall Rule Order That's Breaking Your Setup
Next Post
Is fail2ban Actually Working? Here's How to Check

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts