Chmod, Facl, no, but really who is the file owner
August 7th, 2020
Some days ago I was part of a discussion regarding file access right. At a point in the discussion we couldn't remember how the
chmod related to file access-control lists. In fact, the mask shown in
getfacl only raised more questions. The intention of this blog is to refresh your memory or give new insights into
chmod and file access-control lists.
System permissions in Unix, for this blog specifically file system permissions, are build around classes. The Unix system knows three classes: User, Group and Others.
Files and directories are owned by a user. The owner determines the file's User class.
In this snippet, the file
example.md is owned by edwin. Edwin is the User class.
-rw-r--r-- 1 edwin staff 0 Aug 4 15:32 example.md
Files and directories are assigned a group, which defines the file's Group class.
In the snippet, the file
example.md has the group
staff assigned. The owner may be a member of the group, but it doesn't have to be a member.
Users who are not the owner, nor a member of the group, are considered as the Others. Other than the last three permission bits, you won't see them mentioned as a separate thing unlike user and group.
The effective permissions are determined based on the first class the user accessing falls into. This in order of user, group then others. If the user falls into the group class, the permissions for others are superseded.
There are three specific permissions in play that apply to each class:
- The read permission allows reading a file/directory. When set on a directory it will only allow the reading of the names of files in the directory.
- The write permission allows modification of a file/directory. When set on a directory it will allow for modification of files in the directory. Modification includes creating, deleting and renaming files.
- The execute permission allows execution of a file. When set on a directory it's considered a search permission, and it will allow the user to access file contents and meta-information.
chmod command first appeared in Unix version 1. To put that in a perspective. Unix version 1 is released on 3 November 1971. A mere 48 years ago. I sadly could not find resources showing how it was used during the early years of Unix though I think the command did not change a lot.
chmod adheres to the following syntax.
chmod [options] mode[,mode] file1 [file2 ...]
[options]) commonly used include:
- -R Recursive, including files and directories in subdirectories.
- -v verbose, shows the files and directories changed.
There's a bunch more options though, so I recommend checking out the manual (
man chmod) or the manual.
mode[,mode]) can be octal or numerical. More on that later.
file1 [file2 ...]) can be files or directories. When you run
man chmod you will notice they talk about files, but it can be either a file or directory.
Notation of file permissions
The octal notation of permissions looks like this. It contains four parts of which we can ignore one for now. More on the actual first part in the section "Hold up! What about that first symbol?".
The first part defines the permissions for the User class. This is the file owner. In this example the owner has read, write and execute permission.
The middle part defines the permissions for the Group class. In this example the Group has read and write permission.
The last part defines the permissions for the Others class. In this example Others have no permissions. Others are users who are not the owner of the file and who are not members of the Group.
chmod accepts octal notation as well as numerical notation. For example, rwx can be noted as 7 or in binary 111.
Rewriting our octal example (
-rwxrw----), we get 760. 7 because user has read, write and execute. 6 because group has read and write. 0 because others have no permission for this file. You could express this in binary as 111 110 000, but let's stick to octal or numerical because explaining you accidentally set the directory's permission to 111 111 111 is more confusing than it's set to 777.
|read, write, execute||rwx||7||111|
|read and write||rw-||6||110|
|read and execute||r-x||5||101|
|write and execute||-wx||3||011|
Hold up! What about that first symbol?
-rwxrw---- start with a dash? Well, let's find out by comparing these two lines:
drwxr-xr-x 2 edwin staff 64 Aug 4 15:32 example-directory -rw-r--r-- 1 edwin staff 0 Aug 4 15:32 example.md
Note that the file permissions start with - and directory's start with d. This first symbol is the special file designator. Regular files like a markdown file (example.md) are just that. They get displayed as
-. As for which possible letters could be there, the following exist:
History of FACL (ACLs really)
When talking about ACLs we have to get specific. ACL or access-control list is implemented and used for a lot of things. The earliest in the filesystem of Multics in 1965. Typically, each entry in the ACL specifies who can do an action. For example, an entry could contain
Alice: read. This tells us that Alice is allowed to read this file or directory or whatever this ACL was part of.
As mentioned there are a bunch of standards out there but most of the Unix and Unix-like operating systems support the NFSv4 ACLs, which, unsurprisingly, are part of the NFSv4 standard. Systems like BSD or Solaris support POSIX. 1e ACLs, though many of them also are in the process of switching or have switched to NFSv4. For example, Mac OS X beginning with version 10.4.
Pub quiz knowledge aside though, how do we use them? To answer that question we first must learn how to spot them. If you are like me and use
ls -la for anything related to the file system, as soon as ACLs are used for a file of directory you'll be shown a + after the permissions.
example.md both have an ACL assigned.
drwxr-xr-x+ 2 edwin staff 4096 Aug 4 15:32 example-directory/ -rw-r--r--+ 1 edwin staff 0 Aug 4 15:32 example.md
getfacl example.md will give you the contents of the list.
# file: example.md # owner: someoneelse # group: staff user::rwx user:edwin:r-- group::r-x mask::r-x other::r-x
Remember that each entry of an ACL should tell you who the subject is and which action they are allowed to do. These lines adhere to that.
user::rwx the owner of this file has the
user:edwin:r-- user "Edwin" was specifically assigned the read permission.
As you can see ACLs follow the same standard of classes. The entry is either for the entire class (
group::r-x) or for a specific member of that class (
There's one oddball though. The
mask::r-x. Whoever or whatever mask is, they got the read and execute permission. To explain this we need an example with multiple users, each with a different set of permissions.
# file: example.md # owner: someoneelse # group: staff user::rwx user:edwin:r-- user:aidan:rwx user:emily:r-- user:grace:rw- group::r-x mask::rwx other::r-x
Let's assume that we want to lockdown example.md because somehow it contains a virus that no-one should be able to open. We do not want to type
setfacl -m u:edwin:--- for each user, each time we find a suspicious markdown file. We can set a mask with
setfacl -m m::--- example.md. The maximum allowed setting for all users is then set to
--- (so nothing). This effectively overrides user specific permissions.
If you run
getfacl example.md, you will get this output:
# file: example.md # owner: someoneelse # group: staff user::rwx user:edwin:r-- #effective:--- user:aidan:rwx #effective:--- user:emily:r-- #effective:--- user:grace:rw- #effective:--- group::r-x #effective:--- mask::--- other::---
Do note that the group and other permissions adjust accordingly. Group permissions get masked, permissions for other changes.
What happens if you
chmod a file that has an ACL set?
Given our example markdown file. The owner can do whatever, group and other have the read and execute permission.
# file: example.md # owner: someoneelse # group: staff user::rwx group::r-x mask::r-x other::r-x
If we run
chmod 000 example.md, the same thing happens when introducing the mask (
setfacl -m m::--- example.md).
# file: example.md # owner: someoneelse # group: staff user::--- group::r-x #effective:--- mask::--- other::---
There is a mask added which set the permissions to
--- and, the permissions for other removed. Small but important piece of advice here is: be careful when you notice the
+ next to a file or directory when
ls-ing through your system. When you want to change the permissions of a file, and you want to be sure not introduce a mask that could override special user permission, specify the ACL entry with
Some handy code snippets
List directory contents, in long format, listing directory entries whose names begin with a dot (.).
Changing permissions of a specific file. Given that they do not have an ACL attached.
chmod 777 FILE_NAME ## Anyone can read, write and execute chmod 700 FILE_NAME ## Only the user class (owner) can read, write and execute chmod 640 FILE_NAME ## The user class (owner) can read and write, group class can read
Changing permissions of a directory, including subdirectories. Given that they do not have an ACL attached. 640 permissions are equal to user class (owner) can read and write, group class can read file names in this directory, and it's subdirectories
chmod -R 640 DIRECTORY_NAME
Show the attached access-control list. For the sake of keeping examples short, file and directory names are interchangeable. It can be either. There's no difference in command like there is when doing a similar action with
chmod. Hence the name
setfacl -m u:edwin:rwx example-directory/ ## Add entry for user 'edwin' granting read, write and execute permissions setfacl -m g:people:r-x example.md ## Add entry for group 'people' granting read and execute permissions setfacl -m o::r-- example.md ## Add entry for other granting read permission setfacl -m m::--- example.md ## Add entry for masking overwriting any special user permissions with ---
Setting default permissions. This will make sure new objects created are granted the default permissions. Note that this command does contain
-R for recursive as we want to apply this on all objects that currently exist inside this directory. In this example new objects created in 'example-directory' get an entry for group 'people' granting read and execute permissions
setfacl -R -m d:g:people:r-x example-directory
- Manual for chmod - Linux
- Introduction to permissions
- Paper discussing file system Access Control Lists
- ACLs mask setting
- `getfacl` library for Mac OS X