chmod 4755 sets the mode to rwsr-xr-x: the permissions of 755 plus the setuid bit, the leading 4. Whoever runs the program, it runs with the effective user ID of the file’s owner. The s in the owner’s execute slot shows both setuid and execute; a capital S, as in 4644 (rwSr--r--), means setuid without execute, which does nothing useful.
How it’s used
passwd is the classic case:
$ stat -c '%A %a %U:%G %n' /usr/bin/passwd
-rwsr-xr-x 4755 root:root /usr/bin/passwd
Any user can run it, and it runs as root, so it can write the password database that only root may change; the program itself limits what each user can do. su, sudo and mount are setuid root for the same reason. Setting it on your own program:
sudo chown root:root /usr/local/bin/tool # chown first: it clears setuid
sudo chmod 4755 /usr/local/bin/tool # or: chmod u+s
stat -c '%a %U %n' /usr/local/bin/tool # 4755 root /usr/local/bin/tool
On Linux, chown clears the setuid and setgid bits of an executable, even when root runs it, so the order matters. install -m 4755 -o root -g root tool /usr/local/bin/ does both in one step.
Where it does nothing
- Scripts. Linux ignores setuid and setgid on
#!scripts; only compiled programs change identity. Give a script elevated rights through asudorule instead. nosuidmounts. The kernel ignores setuid and setgid on any filesystem mountednosuid. Hardening guides apply it to/tmp,/var/tmp,/dev/shmand removable media.no_new_privs. Docker’s--security-opt no-new-privileges, systemd’sNoNewPrivileges=yesand Kubernetes’allowPrivilegeEscalation: falseset it, and after that a setuid program runs with the caller’s own IDs.- Directories. Linux ignores setuid on a directory.
The security cost
Every setuid-root program is code that any local user can run as root, so a bug in it is a privilege escalation. Keep the list short and audit it:
find / -xdev -perm -4000 -type f 2>/dev/null
Often a capability is enough. A server that only needs to bind port 443 can get setcap cap_net_bind_service=+ep /usr/local/bin/server instead of running as root.
Git and containers
Git can’t carry the bit: it stores only 100755, so a packaging or install step has to set it. Images inherit setuid binaries from their base packages, and hardened Dockerfiles often strip them all with RUN find / -xdev -perm /6000 -type f -exec chmod a-s {} +.