Setuid in Linux: chmod u+s, 4755 and Practical Examples

Tested on RHEL 10.2
Package coreutils (chmod, ls, find)
Applies to RHEL, Rocky Linux, AlmaLinux, CentOS Stream, Fedora, Ubuntu, Debian, and other Linux systems with POSIX permissions
Privilege Normal user to inspect setuid binaries; sudo to change modes on system paths
Scope Setuid on executable files: chmod u+s, octal 4 prefix, s vs S, passwd example, find, and nosuid mounts. Does not cover capabilities, SELinux, or writing custom setuid programs.
Related guides Linux file permissions
Setgid in Linux
Sticky bit in Linux
chmod recursive
find command

Setuid on an executable means the program runs with the file owner's UID, not the UID of the person who launched it. You see it on /usr/bin/passwd as the s in -rwsr-xr-x. That is how a normal user can update their own password without having direct permission to read or modify /etc/shadow.


Quick Reference: Setuid Commands

Task Command
Set setuid (symbolic) chmod u+s file
Set setuid with mode 755 chmod 4755 file
Remove setuid chmod u-s file or drop the 4 digit in octal
List setuid files find /path -type f -perm -4000
Inspect mode ls -l file (look for s or S in user execute)

1. What Is Setuid in Linux?

Regular executables run as you. The kernel sets the process effective UID from your login session. Setuid flips that rule for one file: whoever runs it temporarily inherits the owner's UID for that process.

That matters when a trusted program must touch root-only resources on behalf of an unprivileged user. passwd must update /etc/shadow, which normal users cannot modify directly. Without setuid, every user would need direct shadow access or a setuid helper could not exist.

Setuid applies to executable files, not directories. On Linux, setuid on a directory is not a supported access-control pattern the way setgid on a directory is.

Root and the "others" permission class

Setuid changes the process effective UID when someone who is not the file owner runs the executable. If you are already root, setuid on a root-owned binary does not grant anything new—you already pass DAC checks.

For normal users, setuid is the elevation path: passwd runs with UID 0 long enough to update shadow, even though the shell session is still your account.

The s is stored in the user (owner) execute slot (chmod u+s), not in the others column. To run the program at all, your user still needs execute through owner, group, or others permissions. passwd is 755, so the others triplet is r-x and any user may invoke it. Without x for your access class, the kernel refuses to start the binary regardless of setuid.


2. The borrowed badge: why setuid exists

Picture a secure office building. Most employees have a blue badge that opens the lobby and their own desk. The server room needs a red badge. You do not hand every employee a permanent red badge just so they can change their voicemail PIN.

Instead, the building runs one approved kiosk program owned by facilities (red badge baked in). You walk up as yourself (blue badge), the kiosk checks your identity, performs the one task you are allowed to request, and logs the change. You never keep the red badge when you leave.

Setuid is that kiosk. The file is owned by root (red badge). You run it as your normal user. For the lifetime of that process, the kernel treats the effective UID as root so the program can reach protected files, but only along the code path the binary implements.

When setuid helps

  • Small, audited system utilities (passwd, mount, su) that must cross a privilege boundary safely
  • Vendor packages that ship a fixed helper instead of handing users root shells

When you should not add your own

  • Random shell scripts with chmod u+s (any local user who can edit the script owns your escalation path)
  • Daemons that should run as a dedicated service account with sudo or systemd User= instead
  • Files on nosuid mounts, where the kernel ignores setuid bits entirely

If you need persistent root access for an app, use sudo rules, a service unit, or Polkit. Do not sprinkle u+s on homemade binaries.


3. Why /usr/bin/passwd Uses Setuid

passwd is the textbook setuid binary. It is owned by root, executable by everyone, and marked setuid so the process can update shadow entries:

bash
ls -l /usr/bin/passwd
output
-rwsr-xr-x. 1 root root 91424 Feb 23 05:30 /usr/bin/passwd

The s in the user execute column means setuid is on and execute is set. Octal mode 4755 breaks down as 4 (setuid) plus 755 (owner read/write/exec, group/other read/exec).

As a normal user you still cannot read /etc/shadow directly:

bash
cat /etc/shadow
output
cat: /etc/shadow: Permission denied

Running /usr/bin/passwd is different. The binary runs with root's effective UID long enough to validate your old password and rewrite your shadow line. You never get a root shell; you get one controlled operation.


4. Set Setuid with chmod u+s

For a safe permissions-only demonstration, create a regular script and inspect the mode bit. Linux ignores setuid and setgid bits when executing scripts, so this example demonstrates chmod and ls output only — it does not demonstrate privilege elevation:

bash
printf '#!/bin/sh\necho setuid demo\n' > /tmp/suid-demo.sh

Give the file execute permission first:

bash
chmod u+x /tmp/suid-demo.sh

Then layer setuid on top:

bash
chmod u+s /tmp/suid-demo.sh

Check the user execute slot for s:

bash
ls -l /tmp/suid-demo.sh
output
-rwsr--r--. 1 user user 27 Aug 15 19:48 /tmp/suid-demo.sh

Remove the demo file when you are done. Do not leave setuid bits on scripts you can edit; even compiled setuid binaries belong only in audited packages.


5. Set Setuid with Octal Mode 4755

Octal mode uses a fourth leading digit for special bits. 4 is setuid, 2 is setgid, and 1 is sticky (see sticky bit).

Apply setuid together with mode 755:

bash
chmod 4755 /tmp/suid-demo.sh

Octal 4755 sets the full mode: 4 (setuid) plus 755 (rwxr-xr-x). Confirm the listing:

bash
ls -l /tmp/suid-demo.sh
output
-rwsr-xr-x. 1 user user 17 Aug 15 20:22 /tmp/suid-demo.sh

Use octal when you set the full mode in one command. If the file already has the right rwx bits, chmod u+s is safer because it cannot accidentally widen group or other permissions.


6. Lowercase s vs Uppercase S

ls encodes setuid in the user execute position:

  • lowercase s — setuid and user execute are both on
  • uppercase S — setuid is on but user execute is off (unusual and not runnable)

Create setuid without execute to see uppercase S:

bash
chmod 4644 /tmp/suid-demo.sh

ls should show S where user execute would be:

bash
ls -l /tmp/suid-demo.sh
output
-rwSr--r--. 1 user user 27 Aug 15 19:48 /tmp/suid-demo.sh

Add execute back and the letter drops to lowercase s:

bash
chmod u+x /tmp/suid-demo.sh

The mode line should read -rws again:

bash
ls -l /tmp/suid-demo.sh
output
-rwsr--r--. 1 user user 27 Aug 15 19:48 /tmp/suid-demo.sh

7. Remove Setuid

Drop the bit with symbolic mode:

bash
chmod u-s /tmp/suid-demo.sh

Or set the full mode without the setuid digit. chmod 755 replaces the entire permission field:

bash
chmod 755 /tmp/suid-demo.sh

Confirm the s is gone:

bash
ls -l /tmp/suid-demo.sh
output
-rwxr-xr-x. 1 user user 17 Aug 15 20:22 /tmp/suid-demo.sh

8. Find Files with Setuid

Setuid is bit 4000 in octal. find -perm -4000 matches files where all bits specified by 4000 are set — here, that simply means setuid is present:

bash
find /usr/bin -maxdepth 1 -type f -perm -4000
output
/usr/bin/umount
/usr/bin/mount
/usr/bin/chage
/usr/bin/gpasswd
/usr/bin/newgrp

Expect a short list on a minimal install and a longer one on a desktop system. Audit unexpected setuid binaries after package installs or compromise drills.

Mounts with nosuid ignore setuid bits on that filesystem. That is common on /home NFS exports and removable media.


Setuid vs Setgid and Sticky Bit

Bit Where it applies What changes
setuid (u+s, octal 4) executable file process effective UID becomes file owner
setgid (g+s, octal 2) executable or directory process GID or new file group — see setgid
sticky (+t, octal 1) directory delete/rename restricted to owner — see sticky bit

Only one special bit belongs on a given task. passwd needs setuid, not sticky. /tmp needs sticky, not setuid.


Summary

Setuid lets a trusted executable run with its owner's UID instead of the caller's. That is how passwd updates /etc/shadow while normal users cannot read or modify that file directly.

Set it with chmod u+s or a leading 4 in octal (4755). Lowercase s means execute is present; uppercase S means setuid without execute. Remove it with chmod u-s or by dropping the 4 digit. Use find … -perm -4000 to audit setuid files.

Treat setuid as a vendor-curated mechanism, not a shortcut for your own scripts. For shared folders and group ownership, use setgid. For world-writable directories, use sticky bit.


References

Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)