Report issue Add example

setfacl

Set file Access Control Lists (ACLs).

Description

The setfacl command is used to set ACLs (Access Control Lists) on the command line. A sequence of commands is followed by a sequence of filenames.

Options

-b, --remove-all: Remove all extended ACL entries. The base ACL entries (owner, group, and others) are retained.
-k, --remove-default: Remove the default ACL. If no default ACL exists, no warnings are issued.
-n, --no-mask: Do not recalculate the effective rights mask. The default behavior of setfacl is to recalculate the ACL mask unless a mask entry was explicitly given.
--mask: Recalculate the effective rights mask, even if an ACL mask entry was explicitly given.
-d, --default: All operations apply to the default ACL.
--restore=file: Restore an ACL backup from a file (these files can be generated by getfacl -R). This mechanism can restore ACLs for an entire directory tree. This parameter cannot be used with any other parameters except --test.
--test: Test mode. Instead of changing the ACLs of any files, the resulting ACLs are listed.
-R, --recursive: Apply operations to all files and directories recursively.
-L, --logical: Follow symbolic links. By default, it only follows symbolic link files and skips symbolic link directories.
-P, --physical: Skip all symbolic links, including symbolic link files.
--version: Output the version of setfacl and exit.
--help: Output help information.
--: End of command line options. All remaining parameters are interpreted as filenames.
-: If the filename is -, setfacl reads filenames from standard input.

When reading rules from a file using the -M or -X options, setfacl accepts the format output by the getfacl command. There must be at least one rule per line, and lines starting with # are treated as comments.

If the setfacl command is used on a filesystem that does not support ACLs, it will modify the file permission bits. If the ACL rules do not perfectly match the file permission bits, setfacl will modify the permission bits to reflect the ACL rules as closely as possible, send an error message to standard error, and return with a status greater than 0.

Permissions

The owner of a file and processes with the CAP_FOWNER capability can set the ACL of a file. (On current Linux systems, the root user is usually the only user with the CAP_FOWNER capability.)

ACL Rules

The setfacl command recognizes the following rule formats:

[d[efault]:] [u[ser]:]uid [:perms]  Permissions for a specific user. Owner permissions if uid is not specified.
[d[efault]:] g[roup]:gid [:perms]   Permissions for a specific group. Owning group permissions if gid is not specified.
[d[efault]:] m[ask][:] [:perms]     Effective rights mask.
[d[efault]:] o[ther] [:perms]       Permissions for others.

Appropriate ACL rules are used in modify and set operations. For uid and gid, you can specify either a number or a name. The perms field is a combination of letters representing various permissions: read (r), write (w), and execute (x). Execute is only suitable for directories and some executable files. The perms field can also be set in octal format.

Automatically Created Rules

Initially, a file or directory contains only three basic ACL rules. For the rules to execute correctly, the following conditions must be met:

ACL Terminology Definitions

Let's look at the definitions of terms in ACLs. Most of these are taken from the man pages and are helpful for understanding the content below.

An ACL consists of a series of Access Entries. Each Access Entry defines the operations a specific category can perform on a file. An Access Entry has three components: Entry tag type, qualifier (optional), and permission.

First, let's look at the most important part, the Entry tag type:

ACL_USER_OBJ: Equivalent to the file owner's permission in Linux.
ACL_USER: Defines permissions for additional users.
ACL_GROUP_OBJ: Equivalent to the group's permission in Linux.
ACL_GROUP: Defines permissions for additional groups.
ACL_MASK: Defines the maximum permissions for ACL_USER, ACL_GROUP_OBJ, and ACL_GROUP (discussed further below).
ACL_OTHER: Equivalent to others' permission in Linux.

Let's use an example to illustrate. We will use the getfacl command to view a file with defined ACLs:

[root@localhost ~]# getfacl ./test.txt
# file: test.txt
# owner: root
# group: admin
user::rw-
user:john:rw-
group::rw-
group:dev:r--
mask::rw- other::r--

The first three lines starting with # define the filename, file owner, and group. This information isn't crucial and can be omitted using --omit-header.

user::rw-       Defines ACL_USER_OBJ, indicating the file owner has read and write permissions.
user:john:rw-   Defines ACL_USER, giving user john read and write permissions to the file.
group::rw-      Defines ACL_GROUP_OBJ, indicating the file's group has read and write permissions.
group:dev:r--   Defines ACL_GROUP, giving the dev group read permission to the file.
mask::rw-       Defines ACL_MASK permissions as read and write.
other::r--      Defines ACL_OTHER permissions as read.

From this, we can see that ACLs provide the ability to define permissions for specific users and groups. Now let's see how to set a file's ACL:

How to Set ACL Files

First, let's discuss the format for setting ACL files. From the example above, each Access Entry consists of three fields separated by colons (:). The first is the Entry tag type.

user   Corresponds to ACL_USER_OBJ and ACL_USER.
group  Corresponds to ACL_GROUP_OBJ and ACL_GROUP.
mask   Corresponds to ACL_MASK.
other  Corresponds to ACL_OTHER.

The second field is the qualifier, such as john and the dev group in the example above. It defines the permissions for specific users and groups. Only user and group have qualifiers; others are empty. The third field is the familiar permission. It's defined the same way as Linux permissions.

Now let's see how to set the ACL for test.txt to meet the requirements mentioned above.

Initially, the file has no extra ACL attributes:

[root@localhost ~]# ls -l
-rw-rw-r-- 1 root admin 0 Jul 3 22:06 test.txt

[root@localhost ~]# getfacl --omit-header ./test.txt
user::rw- group::rw- other::r--

First, let's give user john read and write permissions for test.txt:

[root@localhost ~]# setfacl -m user:john:rw- ./test.txt
[root@localhost ~]# getfacl --omit-header ./test.txt
user::rw-
user:john:rw-
group::rw-
mask::rw-
other::r--

Now we can see that user john has read and write permissions in the ACL. If we check the Linux permissions, we'll notice something different.

[root@localhost ~]# ls -l ./test.txt
-rw-rw-r--+ 1 root admin 0 Jul 3 22:06 ./test.txt

A + sign has appeared at the end of the file permissions. When a file has an ACL_USER or ACL_GROUP value, it's called an ACL file, and the + sign is used to indicate this. We can also notice that when a file has an ACL_USER or ACL_GROUP value, ACL_MASK is also defined.

Next, let's set the dev group to have read permission:

[root@localhost ~]# setfacl -m group:dev:r-- ./test.txt
[root@localhost ~]# getfacl --omit-header ./test.txt
user::rw-
user:john:rw-
group::rw-
group:dev:r--
mask::rw-
other::r--

This completes the requirements. Pretty simple, right?

ACL_MASK and Effective Permissions

It's important to highlight ACL_MASK here as it's key to mastering ACLs. In standard Linux file permissions, for something like rw-rw-r--, the middle rw- refers to the group permissions. However, in ACLs, this is only true if ACL_MASK does not exist. If a file has an ACL_MASK value, the middle rw- represents the mask value instead of the group permission.

Let's look at this example:

[root@localhost ~]# ls -l
-rwxrw-r-- 1 root admin 0 Jul 3 23:10 test.sh

Here, test.sh only gives the file owner root read, write, and execute permissions. The admin group has only read and write permissions. Now we want user john to have the same permissions as root.

[root@localhost ~]# setfacl -m user:john:rwx ./test.sh
[root@localhost ~]# getfacl --omit-header ./test.sh
user::rwx user:john:rwx
group::rw-
mask::rwx
other::r--

We see john has rwx permissions and the mask value is also set to rwx. This is because the mask defines the maximum permissions for ACL_USER, ACL_GROUP, and ACL_GROUP_OBJ. Checking the Linux permissions for test.sh now:

[root@localhost ~]# ls -l
-rwxrwxr--+ 1 root admin 0 Jul 3 23:10 test.sh

So, what happens if a user in the admin group tries to execute test.sh? They will be denied permission. This is because the admin group actually only has read and write permissions. The rwx shown in the middle is the ACL_MASK value, not the group's permission.

Therefore, if a file has the + mark, you must use getfacl to confirm its actual permissions to avoid confusion.

Let's look at another example. Suppose we set the mask for test.sh to read-only. Will users in the admin group still have write permission?

[root@localhost ~]# setfacl -m mask::r-- ./test.sh
[root@localhost ~]# getfacl --omit-header ./test.sh
user::rwx
user:john:rwx   #effective:r--
group::rw-      #effective:r--
mask::r--
other::r--

Now we see #effective:r-- next to ACL_USER and ACL_GROUP_OBJ. What does this mean? Let's revisit the definition of ACL_MASK. It defines the maximum permissions for ACL_USER, ACL_GROUP_OBJ, and ACL_GROUP. In our example, their maximum permission is read-only. Even though we set other permissions for ACL_USER and ACL_GROUP_OBJ, their effective permission is only read.

Checking the Linux file permissions for test.sh again, the group permission will show the mask value (i.e., r--):

[root@localhost ~]# ls -l
-rwxr--r--+ 1 root admin 0 Jul 3 23:10 test.sh

Default ACL

Everything discussed so far relates to Access ACLs, which apply to files. Now let's briefly discuss Default ACLs. A Default ACL is set on a directory, and files created within that directory will inherit its ACL.

Let's test this. For example, the root user creates a directory named dir:

[root@localhost ~]# mkdir dir

The user wants all files created in this directory to be accessible by user john. So, we should set a Default ACL for the dir directory.

[root@localhost ~]# setfacl -d -m user:john:rw ./dir
[root@localhost ~]# getfacl --omit-header ./dir
user::rwx
group::rwx
other::r-x
default:user::rwx
default:user:john:rwx
default:group::rwx
default:mask::rwx
default: other::r-x

Here we see the ACL has the default option defined, and user john has default read, write, and execute permissions. All undefined defaults are copied from the file permissions. Now the root user creates a test.txt file in dir.

[root@localhost ~]# touch ./dir/test.txt
[root@localhost ~]# ls -l ./dir/test.txt
-rw-rw-r--+ 1 root root 0 Jul 3 23:46 ./dir/test.txt

[root@localhost ~]# getfacl --omit-header ./dir/test.txt
user::rw-
user:john:rw-
group::rwx #effective:rw-
mask::rw-
other::r--

We see that for the file created in dir, user john automatically has read and write permissions.

ACL Related Commands

In the previous examples, we noted that getfacl is used to read a file's ACL and setfacl is used to set a file's Access ACL. There is also chacl, which is used to change a file or directory's Access ACL and Default ACL; see the man page for specific parameters. I want to mention chacl -B, which can completely remove the ACL attributes (including Default ACL) of a file or directory. For instance, even if you use setfacl -x to delete all ACL attributes, the + sign might still appear at the end of the filename. The correct way to remove it is using chacl -B. When using cp to copy files, you can add the -p option to copy the file's ACL attributes; a warning will be issued for ACL attributes that cannot be copied.

The mv command will move the file's ACL attributes by default, and similarly, a warning will be issued if the operation is not allowed.

Points to Note

If your filesystem does not support ACLs, you may need to remount it:

mount -o remount,acl [mount point]

Using the chmod command to change Linux file permissions will also change the corresponding ACL values, and vice versa.