Filesystem ACLs and Permissions
Overview
We will first explain simple POSIX permissions, because POSIX ACLs are an extension of them, and understanding the basic concepts is useful for the more complex topic of ACLs. If you are familiar with POSIX file permissions, feel free to skip ahead to the section on ACLs. The section on POSIX permissions serves the purpose of bringing everyone up to speed.
If you are a Windows User, it is still highly reccomended, that you read and understand this documentation. It is possible to grant ACL permissions using Windows Explorer
, which provides a graphical interface, but works with the same POSIX ACLs in the backend. Make sure, that the configurations you perform in the GUI actually correspond to what you want on the POSIX side. Spending half an hour thinking about ACLs is time well spent compared to the work accidentally granting the wrong people permissions on your files can cause.
The topic of ACLs can seem a bit complex in the beginning, so we provide examples of common configurations in the best practices section. There is also a very well written article by one of the original implementers of ACLs on Linux.
Where can i request a group?
The instructions in this article will heavily use UNIX groups. If you do not yet have a fitting group for your workgroup / institute / use-case, the process how you can request your own group is described here.
Common POSIX permissions
The basic POSIX permission concept knows three kinds of users: The user
(sometimes referred to as owner), to which a file belongs, the group
, to which a file belongs and finally all other
users. Permissions can be granted to each of these individually. Permissions can grant read
, write
or execute
access and are commonly abbreviated using the letters r
w
and x
and likewise, user
, group
and other
are often abbreviated using u
, g
and o
Because of the way shares are made available university wide, others
in the context of file shares is equivalent to anyone on the university network. Under normal circumstances, you should not grant permissions to the others group.
File Permissions
- The read permission allows reading the content of simple files, such as with
cat
or a text editor. Copying a file also requires read permissions, because the copying program needs to read the content of the file to be created from somewhere. - The write permission allows modifying the content of simple files and overwriting the file.
- The execute permission allows the file to be executed as a program by the shell. This is necessary for compiled binaries and scripts alike.
Directory Permissions
- The read permission allows looking up the content of a directory.
- The write permission allows modifying the content of directories (adding and removing files).
- The execute permission works slightly differently for directories. It allows accessing the metadata of files contained within the directory. This is obviously something you need when you want to read or write files within the directory (it is in fact not possible to e.g. access files when only the read permission is set on the directory), so whenever one of these permissions is granted to someone on a directory, the execute permission is usually also granted.
Working with permissions
It is also possible to express POSIX permissions in Octal format, such as 744
or 640
. Octal refers to the fact, that each of the digits of the octal number can assume one of eight possible values. The digits correspond to user, group and others, in order of their appearance. r
corresponds to 4
, w
corresponds to 2
and x
corresponds to 1
. Adding these numbers up results in the actual digit representing the permissions for that group
Consider this output of ls -l
:
$ls -l
-rw------- 1 root root 4017 Feb 24 2022 vimrc
Starting from the right side of the output, we can see the following:
- The file
vimrc
was created on the 24. of February in 2022 and its size is 4017 bytes. - It belongs to the
root
group and theroot
user (normally, each user also belongs to a group with the same name and this group will be associated with all files that user creates — members of the group gain access to every file with the respective permissions on that file) - It has a total of 1 hard link referring to it
- Finally, we get the permission block, which looks like this:
-rw-------.
- The first character is a
-
sign, signifying that this is a normal file (if this were a directory, it would instead readd
, for example) - The next 9 characters represent the permissions for the user, group and others. The absence of a permission is represented with a
-
, so none of the three groups hasexecute
permissions on our file, for example.
- The first character is a
If we wanted to, we could also express these permissions in octal format, as mentioned above:
User: rw- = 4+2+0 = 6
Group: --- = 0+0+0 = 0
Others: --- = 0+0+0 = 0
Currently, the group
does not have any permissions. If we want to grant the group
read permission, we can use the chmod
(change mode) command to do so. We can either define which permissions we want to grant to which group, or we can fully specify the permissions of all groups on the file using octal notation:
$ chmod g+r vimrc
$ chmod 640 vimrc
$ ls -l
-rw-r----- 1 root root 4017 Feb 24 2022 vimrc
If we granted these permissions in error, we can also remove them again:
$ chmod g-r vimrc
$ chmod 600 vimrc
$ ls -l
-rw-r----- 1 root root 4017 Feb 24 2022 vimrc
Linux ACLs
Access Control Lists (ACLs) extend the basic set of POSIX permissions. They were developed because more granular control over file access, rather than only one user, one group and everybody else, was required.
Let’s use a different example now and pretend we work in a university with a hierarchical structure of institutes comprising multiple workgroups each. We are Bernd the phd-student currently setting up a network share for our workgroup. Let’s take a look at the ACLs currently in effect. For this the command getfacl
exists:
$ getfacl network-share
# file: network-share
# owner: bernd
# group: bernd
user::rw-
group::r--
other::---
Apparently, the user
has read and write access and the group has only read access. If this seems familiar to you, it’s because these are just the basic permissions from earlier. So far, no ACLs beyond that are in effect. Let’s change that. The command setfacl
allows setting ACLs. It has many features, but for this introduction we will only use a few. The -m
flag modifies the ACL list:
$ setfacl -m "group:example-workgroup:rw" network-share
$ setfacl -m "group:example-institute:r" network-share
$ getfacl network-share
# file: network-share
# owner: bernd
# group: bernd
user::rw-
group::r--
group:example-institute:r--
group:example-workgroup:rw-
mask::rwx
other::---
Using ls
, we can now notice a +
next to the permissions of the network-share
directory, which is an indicator, that additional ACLs are in effect for this file (the -d flag allows us to list the directory rather than its content):
$ ls -ld
drw-r-----+ 1 bernd bernd 4096 Feb 24 2022 network-share
We granted the group example-workgroup
read-write access while granting the group example-institute
read access, perhaps because we want to share some of our data with colleagues in our institute. Acute readers will notice, that another entry called mask
has also appeared. The permissions in the mask
entry define the allowed set of permissions that can be granted by any ACL. The mask entry is required by ACLs and is automatically created based on the permissions of the group, if it is not specified. Permissions that are not set in the mask
entry, can not be granted by ACLs. To demonstrate this, we remove some basic permissions from the group, which will modify the derived mask:
chmod 600 network-share
$ getfacl network-share
# file: network-share
# owner: bernd
# group: bernd
user::rw-
group::---
group:example-institute:rw- #effective:---
group:example-workgroup:rw- #effective:---
mask::---
other::---
As we can see the effective permissions for the groups defined in the ACLs are ---
, which is due to the fact, that the mask
entry masks whatever permissions are unset in it. We can explicitly change the mask entry to fix this:
$ setfacl -m "mask:r" network-share
$ getfacl network-share
# file: network-share
# owner: bernd
# group: bernd
user::rw-
group::---
group:example-institute:rw- #effective:r--
group:example-workgroup:r--
mask::r--
other::---
Now suppose Bernd has a colleague Bob who is only in the institute group, but still closely works together with Bernd. He also needs read and write access to the network share, so we grant it to him as follows (we fix the mask entry first, because otherwise Bob’s effective permissions would amount to read access):
$ setfacl -m "mask:rwx" network-share
$ setfacl -m "user:bob:rw" network-share
$ getfacl network-share
# file: network-share
# owner: bernd
# group: bernd
user::rw-
user:bob:rw-
group::---
group:example-institute:r--
group:example-workgroup:rw-
mask::rwx
other::---
When Bob decides to change careers and become an antiquarian, we can remove the ACL granting his account access as follows:
$ setfacl -x "user:bob" network-share
$ getfacl network-share
# file: network-share
# owner: bernd
# group: bernd
user::rw-
group::---
group:example-institute:r--
group:example-workgroup:rw-
mask::rwx
other::---
This kind of upkeep is obviously not very feasible for large numbers of accounts, so it is usually best to use membership in a group as the criterion for access, automatically removing access through membership expiration. Moreover, Bernd will not be able to modify files created by Bob, which may be a problem when they want to work on the same files. But there is a solution for that too.
Default ACLs
There is a special type of ACLs that is inherited by objects from their parent directory at creation time – Default ACLs. They also grant permissions like normal ACLs, but the inheritance mechanism makes them especially useful for shared directories, because they allow setting an ACL once, which will then propagate to any file and directory created beneath the original parent directory. This obviously reduces the administrative overhead, so it’s highly reccomended (unless there is a specific reason why you don’t want them, you want them). Default ACLs are set using the -d
flag of setfacl
, everything else works exactly like before (for demonstration purposes, we add another bob-ACL to the network-share directory):
$ setfacl -d -m "group:example-workgroup:rw" network-share
$ setfacl -d -m "group:example-institute:r" network-share
$ setfacl -m "user:bob:rw" network-share
$ getfacl network-share
# file: network-share
# owner: bernd
# group: bernd
user::rw-
user:bob:rw-
group::---
group:example-institute:r--
group:example-workgroup:rw-
mask::rwx
other::---
default:user::rw-
default:group::---
default:group:example-institute:r--
default:group:example-workgroup:rw-
default:mask::rwx
default:other::---
If we now create another directory in the network-share
directory, the default ACLs will be inherited, and regular ACLs will be applied to the new directory based on the defaults. Notice how the user:bob:rw-
ACL can not be found in the child directory, because it has no corresponding default ACL.
mkdir network-share/child
$ getfacl network-share/child
# file: network-share/child
# owner: bernd
# group: bernd
user::rw-
group::---
group:example-institute:r--
group:example-workgroup:rw-
mask::rwx
other::---
default:user::rw-
default:group::---
default:group:example-institute:r--
default:group:example-workgroup:rw-
default:mask::rwx
default:other::---
The conclusion from this is, that default ACLs are the most useful in a network-share where new files and directories are created.
Best Practices
Recursively (-R
) set a default ACL and a regular ACL granting the permissions you wish. The X
permission will set the execute
permission, if the file in question is a directory or already has execute
set in one of user
group
and others
. This is useful, because execute
permissions are required on most directories to do anything with them.
$ setfacl -R -d -m "group:example-workgroup:rwX" network-share
$ setfacl -R -m "group:example-workgroup:rwX" network-share
Make sure you don’t accidentally grant permissions to groups you do not mean to grant access to (especially others
or Unix groups with members that should not have access)
$ getfacl network-share
# file: network-share
# owner: bernd
# group: bernd
user::rwx
group::---
group:example-workgroup:rwx
mask::rwx
other::---
default:user::rwx
default:group::---
default:group:example-workgroup:rwx
default:mask::rwx
default:other::---