Skip to content

Owners and Permissions

Scope: testing entries by whose they are (-user, -group, and the numeric forms) and by their permission bits (-perm in its three shapes) — the tests that turn find from a search tool into an audit tool.

Whose: -user

-user name tests the entry's owner. It needs files with more than one owner to be interesting, and the lab tree — built by one user — doesn't have any: its specimen not-mine.txt was meant to belong to user nobody, but the build machine's home filesystem refuses ownership changes outright, even to root:

$ chown 65534 tree/perms/not-mine.txt
chown: changing ownership of 'tree/perms/not-mine.txt': Operation not permitted
[exit 1]

That refusal is recorded here rather than smoothed over, because it decides where this chapter's captures happen: a two-file detour in /tmp, whose filesystem permits the change. The commands are the point; they travel to any directory you can name.

$ ls -l /tmp/owners
total 8
-rw-rw---- 1 root   root    15 Oct 20 22:27 mine.txt
-rw-rw---- 1 nobody nogroup 17 Oct 20 22:27 theirs.txt

$ find /tmp/owners -user root
/tmp/owners
/tmp/owners/mine.txt

$ find /tmp/owners -user nobody
/tmp/owners/theirs.txt

$ find /tmp/owners -not -user root
/tmp/owners/theirs.txt

(-not is the spelled-out form of !, met in chapter 6.) The directory itself belongs to root, so it answers the first search; the second and third are the same fact read from opposite ends.

Three relatives, named rather than captured: -group is -user for the group; -uid and -gid take numbers instead of names, which is how you search for an owner whose account has been deleted — or use -nouser and -nogroup, which match exactly those orphans, entries whose owner or group no longer resolves to a name. Files belonging to departed accounts are a real audit finding: nothing maintains them, and nobody may be watching them.

In practice, mortals meet -user less often as builders of mixed-owner trees than as auditors of shared ones: everything in this shared directory that isn't the project's, everything a departed colleague left behind, everything a service account has been quietly writing. The test is the same whatever the errand.

The bits: -perm

-perm tests the permission bits, and it has three shapes, which differ in one word: how much of the pattern must match. The specimens live in tree/perms/:

$ ls -l tree/perms
total 20
-rw-r--r-- 1 root nogroup 17 Oct 20 22:26 normal.txt
-rw-rw---- 1 root nogroup 30 Oct 20 22:26 not-mine.txt
-rw------- 1 root nogroup 11 Oct 20 22:26 secret.txt
-rwsr-xr-x 1 root nogroup 37 Oct 20 22:26 setuid.sh
-rw-rw-rw- 1 root nogroup 35 Oct 20 22:26 world-writable.txt

Four of the five were set deliberately by the build script; not-mine.txt wears the build machine's defaults. Now the three shapes.

Exact — -perm 600: every bit, special bits included, must equal the pattern:

$ find tree -type f -perm 600
tree/perms/secret.txt

$ find tree -type f -perm 644
tree/perms/normal.txt

All of these bits — -perm -0002: every bit in the pattern must be set; other bits are the entry's own business. This is the audit shape — "writable by others, whatever else is true":

$ find tree -type f -perm -0002
tree/perms/world-writable.txt

Any of these bits — -perm /6000: at least one pattern bit set. The two high bits are setuid (4000) and setgid (2000) — the special bits, which let a program run with its owner's or group's authority. "Either special bit, anywhere" is the audit:

$ find tree -type f -perm -4000
tree/perms/setuid.sh

$ find tree -type f -perm /6000
tree/perms/setuid.sh

The setuid specimen shows its bit in the listing as the s in -rwsr-xr-x — the owner's execute position, replaced. (The /, -, and exact forms also accept symbolic patterns like -perm -o+w in GNU find; the octal forms are the ones that read the same on every system, so they are the ones taught here.)

The two audits, stated as recipes

These are the searches this chapter exists for, and they are run on real systems by real administrators:

find /srv/shared -type f -perm -0002
find / -xdev -type f -perm /6000 2>/dev/null

The first asks what the whole world can write in a shared tree — usually a shorter list than feared and a longer one than hoped. The second inventories every setuid/setgid program on the root filesystem (-xdev keeps find on one filesystem, out of /proc and mounted oddities) — a list that should contain only names you can explain. Two safety notes, plainly: run audits like these on systems you own or administer (the series' standing rule), and expect the second command to be slow and to need the errors redirected, as shown — permission-denied noise on a system-wide walk is normal weather, and chapter 12 explains how to read it.

Check: on the lab tree, -perm -0002 returns exactly world-writable.txt, -perm /6000 exactly setuid.sh, and -perm 600 exactly secret.txt. The tree was built so those three answers are known before the searches run; on a real tree, that is the one luxury you won't have, which is the entire reason the audits are worth running.