Article

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.

Classes

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.

Permissions

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

A 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.

Syntax

chmod adheres to the following syntax.

chmod [options] mode[,mode] file1 [file2 ...]

Options ([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.

Modes (mode[,mode]) can be octal or numerical. More on that later. Files (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

Octal notation

-rwxrw----

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?".

-[rwx]rw----

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.

-rwx[rw-]---

The middle part defines the permissions for the Group class. In this example the Group has read and write permission.

-rwxrw-[---]

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.

Numerical notation

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.

Permission Octal Numerical Binary
read, write, execute rwx 7 111
read and write rw- 6 110
read and execute r-x 5 101
read only r-- 4 100
write and execute -wx 3 011
write only -w- 2 010
execute only --x 1 001
nothing --- 0 000

Hold up! What about that first symbol?

Why does -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.

For example, example-directory and 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

Running 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 rwx permissions. 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 (user:edwin:r--).

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 setfacl instead.

Some handy code snippets

List directory contents, in long format, listing directory entries whose names begin with a dot (.).

ls -la

Snippets for chmod

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

Snippets for setfacl & getfacl

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 OBJECT_NAME.

getfacl OBJECT_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

Resources

Edwin Kortman

Software Developer

Want to learn more? Join us at Future500

We are always looking for new colleagues that want to learn with us.
Check out our vacancies or write us at count-me-in@future500.nl