Linux · lesson 2 of 7
Beginner
2Intermediate
5- 2 Permission Bits, Ownership, and Why passwd Needs setuid
- 3 A Zombie Process That Never Gets Reaped — and the PID 1 That Fixes It
- 4 systemd Service Supervision: Restart Limits and Why They Trip
- 5 Linux Networking: Routes, Interfaces, and Bind Addresses
- 7 Inodes: The Filesystem Is Full, but df -h Says 1% Used
Also part of Linux
7- + Bash Text Processing from Bash
- + Bash Process Management from Bash
- + Bash System Information from Bash
- + Cron and Scheduling in Bash from Bash
- + Bash File Operations from Bash
- + Reading Linux SSH Auth Logs: Failed Logins You Generate Yourself from Defensive Security
- + Host Firewalls with nftables: DROP Times Out, REJECT Refuses from Networking
Also part of: Bash Security Fundamentals Ethical Hacking (methodology, lab-only)
Permission Bits, Ownership, and Why passwd Needs setuid
A real permission-denied error from a locked-down file, then stripping the setuid bit from /usr/bin/passwd to see exactly why an ordinary user can't change their own password without it.
By SkillByExample · Updated
Two related mechanisms, both enforced by the kernel on every file access: ordinary permission bits, and the special setuid bit that lets exactly one kind of privilege escalation happen safely.
A real permission-denied error
docker exec linux-lesson bash -c "useradd -m -s /bin/bash alice && mkdir /data && echo 'secret content' > /data/report.txt && chmod 600 /data/report.txt && ls -la /data"
total 12
drwxr-xr-x 2 root root 4096 Sep 14 06:01 .
drwxr-xr-x 1 root root 4096 Sep 14 06:01 ..
-rw------- 1 root root 15 Sep 14 06:01 report.txt
chmod 600 sets owner to read+write (4+2), and both group and everyone-else to nothing —
exactly the -rw------- shown. alice is neither the file’s owner (root) nor in its
owning group:
docker exec --user alice linux-lesson cat /data/report.txt
cat: /data/report.txt: Permission denied
Not a missing-file error — alice can see report.txt exists (the directory itself is
world-readable), but opening its contents is a completely separate check, and her three
permission bits on this file are all zero.
docker exec linux-lesson chmod 644 /data/report.txt
docker exec --user alice linux-lesson cat /data/report.txt
secret content
644 adds read access for group and others — now alice’s “others” bit grants her cat.
setuid: a program that runs as someone else
docker exec linux-lesson ls -la /usr/bin/passwd
-rwsr-xr-x 1 root root 59976 Feb 6 2024 /usr/bin/passwd
That lowercase s where owner-execute would normally be an x is the setuid bit —
passwd runs with root’s privileges for the duration of the process, no matter which user
launched it. This has to exist: changing your own password means writing to /etc/shadow, a
file only root can write, and an ordinary user needs some sanctioned way to trigger that
write without being handed root access generally.
The bug: stripping setuid breaks passwd for everyone but root
docker exec linux-lesson chmod u-s /usr/bin/passwd
docker exec linux-lesson ls -la /usr/bin/passwd
-rwxr-xr-x 1 root root 59976 Feb 6 2024 /usr/bin/passwd
Plain x now, no s. alice tries to change her own password:
docker exec --user alice linux-lesson bash -c "printf 'oldpass123\nnewpass456\nnewpass456\n' | passwd"
Changing password for alice.
Current password: New password: Retype new password: passwd: Authentication token manipulation error
passwd: password unchanged
Without setuid, passwd runs with alice’s own ordinary privileges the entire time —
including the moment it tries to write her new password hash into /etc/shadow. That write is
refused by the kernel, exactly as it would be for any other program alice ran, because
/etc/shadow grants write access to nobody but root. Correct current password, correct new
password twice — none of that matters, because the actual failure is a permission check on a
file alice was never trying to open directly.
The fix: restore setuid
docker exec linux-lesson chmod u+s /usr/bin/passwd
docker exec --user alice linux-lesson bash -c "printf 'oldpass123\nnewpass456\nnewpass456\n' | passwd"
Changing password for alice.
Current password: New password: Retype new password: passwd: password updated successfully
Same command, same user, same password values — the only thing that changed is whether the
kernel elevates passwd’s privileges while it runs.
Practice
1. Find every setuid binary currently on the system.
docker exec linux-lesson find /usr/bin /usr/sbin -perm -4000 2>/dev/null
/usr/bin/newgrp
/usr/bin/mount
/usr/bin/su
/usr/bin/chfn
/usr/bin/umount
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/chsh
/usr/bin/sudo
-perm -4000 matches the setuid bit specifically — this is the real command a security audit
runs to find every binary capable of privilege escalation, worth periodically reviewing on any
system for binaries that don’t actually need it.
2. Give a group, rather than "others", access to the restricted file.
docker exec linux-lesson bash -c "chmod 600 /data/report.txt && chgrp alice /data/report.txt && chmod 640 /data/report.txt"
docker exec --user alice linux-lesson cat /data/report.txt
secret content
chmod 640 grants read to owner and group, nothing to others — chgrp alice first makes
alice’s own group the file’s group, so this is a narrower grant than 644’s “everyone can
read” from earlier.
3. Confirm that only the setuid bit changed, not the binary's other permissions, when it was stripped and restored.
docker exec linux-lesson stat -c '%A %U:%G' /usr/bin/passwd
-rwsr-xr-x root:root
Owner, group, and the r-x for group/others are unchanged from before either chmod call —
only the single setuid bit toggled, confirming the fix didn’t accidentally alter anything else
about the binary.
Next: processes at the OS level — zombies, orphans, and what /proc actually shows about a running process.