Unix File Systems and Permissions
Permissions are one of those things you think you understand until you have to explain them to someone else. The nine-character string on ls -l output — -rw-r--r-- — looks simple, but there are enough edge cases hiding in there to keep things interesting. This covers the core concepts and the parts that actually trip people up.
The Directory Tree
Everything in Unix lives under /. There's no C: drive, no separate volumes by letter — it's one tree, and other disks get mounted into it at whatever point you choose. Key spots:
- /bin, /usr/bin — system and user binaries
- /etc — configuration files (plain text, almost always)
- /home — user home directories
- /var — logs, caches, mail, anything that grows over time
- /tmp — temporary files, usually wiped on reboot
- /proc, /sys — not real files; the kernel exposing itself as a filesystem
File Types
The first character of ls -l output tells you what something actually is:
- regular file d directory l symbolic link c character device (terminals, serial ports) b block device (disks) s socket p named pipe (FIFO)
Most of the time it's - or d. The device files live in /dev and you generally don't touch them directly.
Reading the Permission Bits
Take this output:
-rw-r--r-- 1 jason users 4096 Feb 5 12:34 notes.txt
After the file type character, the next nine characters are three groups of three: owner, group, others. Each group is rwx — read, write, execute. A dash means the permission isn't set.
rw- owner (jason) can read and write, not execute r-- group (users) can read only r-- everyone else can read only
For directories, x means you can enter it (traverse). Without execute on a directory, you can't cd into it even if you can read the listing.
Changing Permissions with chmod
Two ways to do it — symbolic and numeric. I use numeric when I know exactly what I want, symbolic when I'm making a targeted change.
Numeric
Read = 4, write = 2, execute = 1. Add them up for each group:
$ chmod 755 script.sh # rwxr-xr-x (owner full, others read+execute) $ chmod 644 config.txt # rw-r--r-- (owner read+write, others read) $ chmod 600 id_rsa # rw------- (owner only, private key territory)
Symbolic
$ chmod u+x script.sh # add execute for owner $ chmod go-w file.txt # remove write from group and others $ chmod a+r readme.txt # add read for all (a = all)
Ownership: chown and chgrp
$ chown jason file.txt # change owner $ chown jason:users file.txt # change owner and group together $ chgrp www-data /var/www/html # change group only $ chown -R jason:jason ~/project # recursive, useful after copying files as root
You need root (or sudo) to give a file to another user. You can change your own files to a group you belong to without sudo.
Special Permissions
Three extra bits that don't show up in the basic rwx display — they sit in a fourth position in the numeric notation.
Setuid (4xxx)
When set on an executable, it runs as the file's owner rather than whoever ran it. passwd is the classic example — it needs root access to modify /etc/shadow, but ordinary users need to be able to run it:
$ ls -l /usr/bin/passwd -rwsr-xr-x 1 root root 59976 ... /usr/bin/passwd
The s in the owner execute slot is setuid. On a directory, setuid is ignored on Linux (though not on some BSDs).
Setgid (2xxx)
On an executable, same idea — runs with the file's group. On a directory, new files created inside inherit the directory's group instead of the creator's primary group. Useful for shared project directories:
$ chmod 2775 /srv/shared $ ls -ld /srv/shared drwxrwsr-x 2 root devteam 4096 ... /srv/shared
Sticky Bit (1xxx)
On a directory, only the file's owner (or root) can delete or rename files inside, even if others have write permission on the directory. /tmp uses this — everyone can write there, but you can't delete each other's files:
$ ls -ld /tmp drwxrwxrwt 12 root root 4096 ... /tmp
The t at the end is the sticky bit.
Access Control Lists
Standard Unix permissions only give you three buckets — owner, group, everyone else. ACLs let you add specific per-user or per-group permissions on top of that. Not every filesystem supports them, but ext4, XFS, and Btrfs all do.
$ getfacl file.txt # view current ACL $ setfacl -m u:sarah:rw file.txt # give sarah read+write $ setfacl -m g:contractors:r file.txt # give contractors read $ setfacl -x u:sarah file.txt # remove sarah's entry $ setfacl -b file.txt # remove all ACL entries
When a file has an ACL, ls -l shows a + at the end of the permission string.
Finding Files by Permission
Sometimes you need to audit what's out there. The find command handles this well:
$ find /usr/bin -perm -4000 # find all setuid binaries $ find /home -perm 777 # world-writable files (usually wrong) $ find /var/www -not -user www-data # files not owned by web user
dispelled