chmod 4755

rwsr-xr-x

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 a sudo rule instead.
  • nosuid mounts. The kernel ignores setuid and setgid on any filesystem mounted nosuid. Hardening guides apply it to /tmp, /var/tmp, /dev/shm and removable media.
  • no_new_privs. Docker’s --security-opt no-new-privileges, systemd’s NoNewPrivileges=yes and Kubernetes’ allowPrivilegeEscalation: false set 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 {} +.

Try it in the chmod Calculator

4755 rwsr-xr-x

WhoReadWriteExecute
Owner
Group
Others
Special bits
Command
chmod 4755 file

Runs in your browser. Nothing you enter is sent anywhere.