In Part 1, we covered the basics: rwx, octal notation, the kernel's decision order, and why chown is better than 777. Two questions remained: what does the s in -rwsr-xr-x do, and what do you do when a single owner and group aren’t enough?

> The Essentials in 30 Seconds > > - A fourth digit, on the left, contains three special bits: setuid (4), setgid (2), sticky (1). > - setuid: the program runs with the owner’s permissions. Powerful, so use with caution. > - setgid on a directory: files created inside it inherit its group. This is the key to shared directories. > - sticky on a directory: Users can only delete their own files. This is what protects /tmp. > - ACL: Permissions for other users or groups, with one caveat: the permission mask.

The 4th digit

Bit Value Displayed On a program On a directory
setuid 4 s for the owner runs with the owner’s UID ignored on Linux
setgid 2 s for the group runs with the group’s GID new files inherit the group
sticky 1 t for others has no effect on Linux deletion restricted to the file’s owner

An uppercase S or T means that the bit is set but the x below it is missing. On a program, this is almost always an error.

setuid: root privileges, in controlled doses

/usr/bin/passwd belongs to root and has the setuid bit set (4755). When you change your password, the program runs as root just long enough to write to /etc/shadow, and does nothing else.

The danger begins when the program is capable of doing more than that. The GTFOBins project lists common binaries (find, vim, less, python, etc.) that open a root shell as soon as they are setuid. A chmod u+s /usr/bin/find “to troubleshoot” grants root access to all local accounts.

Two simple best practices:

# Create an inventory, save it, and compare it from time to time
find / -xdev -type f -perm -4000 -exec ls -l {} + 2>/dev/null

# Do not honor setuid on data partitions (/etc/fstab)
/dev/mapper/vg-data  /srv  ext4  defaults,nosuid,nodev  0 2

A new setuid binary appearing without a package update is a red flag.

Setuid does not work on a script

“I ran chmod u+s on my Bash script, but it doesn’t run as root. ” This is normal and intentional: Linux ignores the setuid bit on #! scripts. Between the kernel reading the #! line and the interpreter reopening the file, an attacker could replace the script.

For a user to run a specific action as root, the correct solution is a sudo rule limited to that command.

setgid: The Clean Shared Folder

The problem: Alice and Bob are working in the same folder, but each creates files in their own group, and the other cannot modify them. The solution:

groupadd project
usermod -aG project alice
usermod -aG project bob
mkdir /srv/project
chown root:project /srv/project
chmod 2770 /srv/project

The leading 2 causes everything created in the directory to inherit the project group. For Alice and Bob to be able to edit each other’s files, their umask must allow writing to the group (002 or 007).

Sticky bit: what makes /tmp livable

/tmp is set to 1777: anyone can write to it, but the t prevents users from deleting other people’s files. So this beast does indeed exist on your system, kept on a leash by a t.

When added to the shared folder, it results in 3770: everyone can write, but can only delete their own files.

To verify that no publicly accessible folders have been overlooked:

find / -xdev -type d -perm -0002 ! -perm -1000 2>/dev/null

ACLs: When a Single Group Isn’t Enough

The compta folder must be writable by the compta group and readable by the auditeur user. With only one group per file, rwx can’t handle this. ACLs can:

setfacl -m u:auditor:rX /srv/accounting        # one more user
setfacl -d -m g:accounting:rwX /srv/accounting      # rule inherited by new files
getfacl /srv/accounting                          # read the result

A + at the end of the permissions (drwxrwx---+) indicates an ACL. ls -l therefore doesn’t show everything: remember to use getfacl.

The mask trap

As soon as you add a named user or group, a permission mask appears. It caps the permissions for everyone except the owner and others.

group::rwx          #effective:r-x
mask::r-x

The group has rwx on paper, but the mask limits it to r-x. And on a file with an ACL, chmod changes the mask, not the group. A routine chmod 750 can therefore remove write access from all named users at once. For these files, you use setfacl.

Further Reading

Two mechanisms round out the picture, each of which deserves its own article:

  • Capabilities carve out root privileges. To listen on port 80 without being root: AmbientCapabilities=CAP_NET_BIND_SERVICE in the systemd unit, rather than a setuid.
  • SELinux and AppArmor add an additional layer of control on top of Unix permissions. If you encounter a Permission denied error despite having the correct permissions, check their logs before making any changes.

Common Mistakes

Error What to do instead
chmod u+s on a script set a targeted sudo rule
setuid on a binary “as a workaround” sudo or a specific capability
Shared directory set to 777 dedicated group + 2770 or 3770
chmod on a directory under ACL setfacl
Relying only on ls -l use getfacl when a + is present

> Key Takeaways > > - Setuid binaries are few and far between and should be monitored. On a script, the bit is ignored—and that’s a good thing. > - Setgid on a folder for sharing; sticky bit so everyone keeps their files. > - ACLs handle what rwx can’t, but once they’re in place, you can forget about chmod. > - In any case, the question remains the same as in Part 1: who needs what, and nothing more.

Sources and References