Skip to content

Special Permissions

Three extra bits sit above rwx: SUID runs a program with its owner's identity, SGID runs it with its group or makes a directory pass its group to new files, and the sticky bit stops users from deleting each other's files in shared directories. They power passwd, sudo and /tmp, and they are a standard target of security audits.

Track: Core · Interview weight: High


Must-Know Facts

Fact Value Verify with
SUID (4000) Executable runs with the file owner's effective UID ls -l /usr/bin/passwd
SGID on a file (2000) Executable runs with the file group's effective GID ls -l /usr/bin/write
SGID on a directory New files and subdirectories inherit the directory's group; subdirectories also get SGID ls -ld /srv/team
Sticky bit (1000) In a writable directory, only the file owner, directory owner or root may delete or rename a file ls -ld /tmp
Display s in the user or group execute position, t in the other position ls -l
Capital S or T The special bit is set but the execute bit under it is not chmod 4644 f
Octal Fourth digit in front: 4755, 2770, 1777 stat -c %a f
Real vs effective UID Real is who started the process; effective is used for permission checks /proc/<pid>/status
Scripts Linux ignores SUID and SGID on interpreted scripts ls -l script
chown Clears SUID and SGID on the file ls -l
nosuid mount option Disables SUID and SGID for the whole filesystem findmnt -no OPTIONS <mount>
Audit find / -perm -4000 and -perm -2000 sudo find / -xdev -perm /6000

Where the Bits Appear

ls -l /usr/bin/passwd /usr/bin/su /usr/bin/sudo /usr/bin/write
ls -ld /tmp /var/tmp
stat -c '%a %A %n' /usr/bin/passwd /usr/bin/sudo /tmp

Output:

-rwsr-xr-x 1 root root  91424 Feb 23  2026 /usr/bin/passwd
-rwsr-xr-x 1 root root  57344 Jan 15  2026 /usr/bin/su
---s--x--x 1 root root 297744 Apr 10 00:00 /usr/bin/sudo
-rwxr-sr-x 1 root tty   24152 Jan 15  2026 /usr/bin/write
drwxrwxrwt 11 root root 4096 Sep 16 14:36 /tmp
drwxrwxrwt  6 root root 4096 Sep 16 14:36 /var/tmp
4755 -rwsr-xr-x /usr/bin/passwd
4111 ---s--x--x /usr/bin/sudo
1777 drwxrwxrwt /tmp

passwd must update /etc/shadow, which only root can write, so it runs as root for every caller. write is SGID tty so it can write to other users' terminals.

Setting Octal Symbolic
SUID chmod 4755 f chmod u+s f
SGID chmod 2755 f chmod g+s f
Sticky chmod 1777 d chmod +t d
Remove all three chmod 0755 f (GNU chmod keeps directory SGID unless given five digits or g-s) chmod ug-s,-t f

SUID: Real and Effective UID

A small C program prints both user IDs. Compiled on Rocky and installed as root with the SUID bit:

#include <stdio.h>
#include <unistd.h>

int main(void) {
    printf("real uid=%d effective uid=%d\n", getuid(), geteuid());
    return 0;
}
gcc -o showid showid.c
sudo install -o root -m 4755 showid /usr/local/bin/showid
ls -l /usr/local/bin/showid
sudo -u amor /usr/local/bin/showid
sudo chmod u-s /usr/local/bin/showid
sudo -u amor /usr/local/bin/showid

Output:

-rwsr-xr-x 1 root root 16816 Sep 16 14:37 /usr/local/bin/showid
real uid=1002 effective uid=0
real uid=1002 effective uid=1002

The real UID still identifies amor, which is how passwd knows whose password to change; the effective UID 0 passes the permission check on /etc/shadow.

A writable SUID-root binary is a root shell

If any user can write to a SUID-root program, or the program can be told to run other commands (find -exec, vim :!sh, less !), it hands out root. Keep SUID binaries owned by root, mode 4755 or stricter, and audit them regularly.

Two kernel rules limit the damage:

sudo chmod 4755 /usr/local/bin/showid
sudo chown amor /usr/local/bin/showid
ls -l /usr/local/bin/showid
printf '#!/bin/bash\nid -un\n' | sudo tee /usr/local/bin/suid-script >/dev/null
sudo chmod 4755 /usr/local/bin/suid-script
ls -l /usr/local/bin/suid-script
sudo -u amor /usr/local/bin/suid-script

Output:

-rwxr-xr-x 1 amor root 16816 Sep 16 14:37 /usr/local/bin/showid
-rwsr-xr-x 1 root root 19 Sep 16 14:36 /usr/local/bin/suid-script
amor

chown cleared the SUID bit, and the SUID script still ran as amor: Linux ignores the bit on files started through an interpreter line.

A filesystem mounted nosuid disables the bits entirely:

sudo mkdir -p /mnt/ns
sudo mount -t tmpfs -o nosuid tmpfs /mnt/ns
sudo install -o root -m 4755 /tmp/showid /mnt/ns/showid
ls -l /mnt/ns/showid
sudo -u amor /mnt/ns/showid
findmnt -no OPTIONS /mnt/ns

Output:

-rwsr-xr-x 1 root root 16816 Sep 16 14:37 /mnt/ns/showid
real uid=1002 effective uid=1002
rw,nosuid,relatime

Capital S and T

sudo touch s-file
sudo chmod 4644 s-file; ls -l s-file
sudo chmod 4755 s-file; ls -l s-file
sudo chmod 2644 s-file; ls -l s-file
sudo chmod 1644 s-file; ls -l s-file

Output:

-rwSr--r-- 1 root root 0 Sep 16 14:36 s-file
-rwsr-xr-x 1 root root 0 Sep 16 14:36 s-file
-rw-r-Sr-- 1 root root 0 Sep 16 14:36 s-file
-rw-r--r-T 1 root root 0 Sep 16 14:36 s-file

A capital letter means the special bit has no effect, because nothing can execute the file (or, for T, others cannot enter the directory). It usually points to a mistake.


SGID Directories for Team Collaboration

sudo mkdir -p /srv/team
sudo chgrp devs /srv/team
sudo chmod 2770 /srv/team
ls -ld /srv/team
sudo -u amor touch /srv/team/by-amor.txt
sudo -u amor mkdir /srv/team/sub
sudo -u amor touch /tmp/by-amor-tmp.txt
sudo ls -l /srv/team
ls -l /tmp/by-amor-tmp.txt

Output:

drwxrws--- 2 root devs 4096 Sep 16 14:36 /srv/team
total 4
-rw-r--r-- 1 amor devs    0 Sep 16 14:37 by-amor.txt
drwxr-sr-x 2 amor devs 4096 Sep 16 14:36 sub
-rw-r--r-- 1 amor amor 0 Sep 16 14:37 /tmp/by-amor-tmp.txt

Files in /srv/team got group devs, and the subdirectory inherited the SGID bit; the same user's file in /tmp got their primary group amor. The file is still 644, so teammates can read it but not edit it: combine the SGID directory with umask 002 or a default ACL.


The Sticky Bit

With mode 3770, members of devs can create files but only delete their own:

sudo usermod -aG devs ibtisam
sudo chmod 3770 /srv/team
ls -ld /srv/team
sudo -u ibtisam rm /srv/team/by-amor.txt; echo "rc=$?"
sudo -u amor rm /srv/team/by-amor.txt; echo "rc=$?"

Output:

drwxrws--T 3 root devs 4096 Sep 16 14:36 /srv/team
rm: cannot remove '/srv/team/by-amor.txt': Operation not permitted
rc=1
rc=0

T is capital because others have no x on the directory; the bit still works for group members.

The standard shared-directory recipe

chgrp team dir; chmod 3770 dir gives group ownership of new files (SGID), protection against deleting others' files (sticky) and no access for anyone else. Add setfacl -d -m g:team:rwX dir if teammates must edit each other's files.


Auditing Special Bits

sudo find / -xdev -perm -4000 -type f 2>/dev/null | sort | head -12
sudo find / -xdev -perm -2000 -type f 2>/dev/null | sort

Output:

/usr/bin/chage
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/crontab
/usr/bin/fusermount3
/usr/bin/gpasswd
/usr/bin/mount
/usr/bin/newgrp
/usr/bin/passwd
/usr/bin/pkexec
/usr/bin/su
/usr/bin/sudo
/usr/bin/plocate
/usr/bin/write
/usr/libexec/utempter/utempter

The list should only contain files from packages (rpm -Vf or dpkg -S confirms the owner). ping is not in it: on Rocky 10.2 it is an ordinary binary, and unprivileged ICMP is allowed by net.ipv4.ping_group_range = 0 2147483647.


Common Errors

rm: cannot remove '/srv/team/by-amor.txt': Operation not permitted

Cause: the directory has the sticky bit, and the caller owns neither the file nor the directory.

Fix: the file's owner or root removes it; this is the intended behavior. When a SUID program instead runs as the caller, check for a script, a nosuid mount (findmnt -no OPTIONS -T <file>) or a chown that cleared the bit.


Interview Checkpoints

L1: What do SUID, SGID and the sticky bit do?

Say first: SUID runs a program as its owner, SGID runs it as its group or makes a directory pass on its group, and the sticky bit limits deletion in shared directories to each file's owner.

Proof: ls -l /usr/bin/passwd /usr/bin/write; ls -ld /tmp

Follow-up: Why does passwd need SUID?

L1: What is the difference between s and S in ls output?

Say first: lowercase means the special bit and the execute bit are both set; uppercase means the special bit is set without execute, so it has no effect.

Proof: chmod 4644 f shows -rwSr--r--.

Follow-up: What does T mean on a directory?

L1: What is the difference between the real and the effective UID?

Say first: the real UID is the user who started the process; the effective UID is the one the kernel uses for permission checks, and SUID changes only the effective one.

Proof: the SUID showid program prints real uid=1002 effective uid=0.

Follow-up: Where can you see both for a running process? (Uid: line in /proc/<pid>/status.)

L2: Create a directory where the team shares files and nobody deletes others' work.

Say first: group ownership, SGID and sticky, no access for others.

Proof:

sudo mkdir /srv/team && sudo chgrp devs /srv/team && sudo chmod 3770 /srv/team

Follow-up: How do teammates get write access to each other's files? (Default ACL or umask 002.)

L2: List every SUID and SGID file on the root filesystem.

Say first: permission test with the any-bit form.

Proof: sudo find / -xdev -type f -perm /6000 -ls 2>/dev/null

Follow-up: How do you check that each one came from a package?

L3: A security scan flags a SUID binary in /usr/local/bin.

Say first: find out what it is, who owns it, and whether it can run other commands.

Proof: ls -l, rpm -qf or dpkg -S (no package), strings or --help for exec options; GTFOBins lists common escapes.

Follow-up: How do you prevent SUID binaries on data filesystems? (nosuid in /etc/fstab.)

L3: New files in a shared project directory keep getting the wrong group.

Say first: check for the SGID bit on the directory and on its subdirectories.

Proof: ls -ld shows drwxrwx--- without s; chmod g+s fixes new files, and find dir -type d -exec chmod g+s {} + fixes existing subdirectories.

Follow-up: Does SGID change the group of files moved in with mv? (No; mv keeps the original group.)

L4: How does passwd update /etc/shadow when a normal user runs it?

Say first: execve sees the SUID bit and sets the process's effective UID to the file owner (root) while keeping the real UID; passwd then checks the real UID to decide which account the user may change.

Proof: ls -l /usr/bin/passwd shows rws; during a change, /proc/<pid>/status shows Uid: 1002 0 0 0.

Don't say: "passwd asks sudo for permission."


Captured on Rocky Linux 10.2 and Ubuntu 24.04.4 LTS (iximiuz Labs microVMs, kernel 6.1.167), 2026-09.