• 14 Sep 2023: change owning users to owning user

1 Users and Groups

Every program runs as some user. This is true even of the user interface, a program that allows you to run other programs. When one program runs another, the new program runs as the same user as the old one except in a few special circumstances. An example special circumstance is the log in program, which itself runs as root, but after you log in, runs your user interface as your user account.

You can find out what user you are running as via the command whoami.

Each user generally has a name and also a numerical ID. Typically, the numerical ID is what is used internally by the kernel to identify a user.

Every user can belong to any number of groups. You can find out which groups a user belongs to by running the command groups <username>; if you omit the username, it will list your own group memberships.

Every file and directory also has a user and a group—but just one group, not a whole set. The user of a file does not need to belong to the group of the file.

2 POSIX file permissions

Permissions are split into three kinds, with different meanings for:

for files
permission to read its contents (e.g. cat file works)
for directories
permission to list its contents (e.g. ls directory/ works)
for files
permission to write its contents (e.g. echo whatnot >> file works)
for directories
permission to add and remove its contents (e.g. rm directory/whatever works)
for files
permission to execute its contents (e.g. ./file works)
for directories
permission to access its contents (e.g. directory/whatever works)

Every file has these permissions for 3 classes of users, stored as a nine-bit number; from high to low order, those bits are

owning user may read/write/execute
members of owning group may read/write/execute
others may read/write/execute

ls -l includes the nine permission bits in letter form: a subset of rwxrwxrwx (e.g. rw-rw---- means the owner and all users in the owning group have r and w permissions, but not x permission; and other users have no permissions). Commands that change these often use octal (base-8) representation of the number (e.g. 660 for rw-rw----).

Using chmod

The most commonly used permission tool is chmod, used as chmod [permission] file. As noted in man chmod, the permission argument can be either letters or octal

  • chmod 644 file means “change the permission bits to exactly 6448 = 1101001002 = rw-r–r–
  • chmod ug+rw file means add r and w permissions for the owning user and the owning group

2.1 Defaults: the umask

When you make a new file, its gets all permissions except a few; the omitted few are specified by the umask. A special command, umask, can display (and change) these, either in octal or letter format.

On the department machines, if you run umask you’ll see 0022. That means that new files get permission 0755: a nine-bit ~0022. What that actually looks like can be see by adding the symbolic flag: umask -S shows u=rwx,g=rx,o=rx.

2.2 setuid, setgid, and sticky

File permissions in POSIX-compatible systems also have three more permission bits which we recommend not using because of their potential dangers.

executable file

If executable xyxxy is owned by mst3k and has setuid permissions, then when tj1a runs ./xyxxy, the program runs as mst3k, not as tj1a. This is often used by OS-supplied programs like sudo that require more permissions than the user running them would normally have.

There are many ways in which naively setting an executable program setuid is likely to create a major security vulnerability. Code that would be perfectly safe in other sensitive programs can be dangerous in setuid programs because of the extraordinary control an attacker has over the setuid program’s environment. Even the expertly-maintained programs like sudo have made subtle but very serious mistakes.

non-executable file
does nothing
does nothing on most POSIX systems
executable file
like setuid, but with group, not user. This can be a security vulnerability and should not be used except when absolutely necessary.
non-executable file
does nothing
when a new file is created in the directory, it inherits the directory’s group instead of the creating user’s group. This can be a security vulnerability and should not be used unless you are sure you know what you are doing.
does nothing in most POSIX systems
the files inside it can only be removed or renamed by the owner of the file, owner of the directory (but root is always allowed).

If you use a four-digital octal with chmod, these permissions will be the first octal digit. Sticky may sometimes be worth setting; we recommend never using the other two.

3 Access Control Lists

Sometimes we need more fine-grained control than the three-way user-group-other distinction. This is provided using more general access control lists, or ACLs; they are a list of user+permission pairs associated with each file. Unlike the simpler POSIX permission bits, they can include settings for much more than a single user or group. Every OS I’ve ever used has ACL support, though actual use of them is relatively uncommon; the standard system works in most cases.

The command getfacl file shows the full permission information for a file. The command setfacl creates and modifies entries in the permissions list. There are many ways of doing this, as man setfacl shows, but three examples will suffice for most common cases:

While ACLs are not commonly needed, they are a safe way of handling cases where they are needed.

4 Executable text files

What does it mean for a file to be executable? On POSIX, there are two main cases where this is sensible:

A quine is a program that, when run, displays its own contents. The following file is a quine, provided it is executable:


So is the following:

Quines are interesting to create in many languages.
But if you use shebangs, they are trivial to create
using the interpreter "cat."

  1. ”shebang” comes from the colloqial name of the first two characters: # is ”hash” and ! is ”bang”. ”Hashbang” was shortened to ”shbang,” with a vowel added for readability. You can still sometimes hear ”hashbang” used to mean the #! itself, as in ”a shebang begins with a hashbang, then path to the interpreter.”↩︎