POSIX ACLs in Linux

An article on POSIX ACLs in Linux, useful for understanding file permissions in CVS

This is an article copied from linux.com Monday August 02, 2004.  You may find the section on using ACLs useful.

By: Mike Peters

In most *nix filesystems administrators can assign read (r), write (w), and execute (x) permissions to files, and set permissions differently for a file’s owner, users in the same group, and others.  This scheme is simple and effective, but for more complicated scenarios, administrators often have to implement elaborate and cumbersome directory structures and multiple user groups to model an appropriate permission system.  A better approach is the use of filesystem access control lists (ACLs) to provide a finer-grained level of control over permissions. With ACLs you can specify which users and groups can access a file, regardless of the owner of the file or directory.

ACL implementations have been present in Unix distros for several years.  ACLs were added to the 2.5 series development Linux kernel in November 2002. A few distros, such as SUSE, have integrated the patches into the earlier stable 2.4 series, and they are available in the standard 2.6 series kernels.

Currently, the Linux implementation supports the Ext2, Ext3, IBM JFS, ReiserFS, and SGI XFS filesystems and has support for with Solaris-compatible NFS version 3.

Installation

In order to enable ACL support you will need to recompile your kernel.  ACL support is enabled by selecting POSIX Access Control Lists under the Extended Attributes option in the File Systems section of the kernel configuration.  For 2.4 series kernels and for NFS support on 2.6 you will first need to acquire and apply the appropriate patches.

Once you have compiled your kernel with ACL support enabled you need to mount the filesystem with the acl option: e.g.mount /data -o remount,acl. Replace /data with the actual filesystem for which you want to enable ACLs.   Once you have verified that ACL support is working properly, you can enable this option every time the computer boots by adding it to the /etc/fstab file, with a line like:

/dev/hda3 /data ext3 defaults,acl 1 1

As far as I am aware, at the time of writing, SuSE is the only distro to currently support ACLs out of the box, and has done since version 8.1.  To use them, you must remount your filesystems with the acl option described above.

Using ACLs

When we create a file or directory it is given an initial set of permissions determined by the kernel and umask settings in the current shell (set in /etc/profile for the bash shell).  The actual permissions of a newly created file or directory can be calculated by subtracting the current umask from 0666 for a file and 0777 for a directory.  So an umask of 022 will mean newly created files will have permissions of 0644 (or -rw-r–r–) and directories 0755 (or drwxr-xr-x).

For the purpose of testing ACLs, let’s set the umask for the current shell to 027 with the command umask 027. This means any files we create in the current session will have initial permissions of 0640 (or -rw-r—–) and directories will have initial permissions of 0750 (or drwxr-x—).  Setting the umask in this way is not necessary for ACLs to work, it just makes it easier to see what is happening in the examples below.

Suppose we now create a directory with mkdir acldir. Running ls -ld acldir shows this directory as:

drwxr-x— 2 foo bar 4096 Jul 03 12:20 acldir

User foo has full access to the directory, and members of the group bar have read access and can execute (i.e. open) the directory.   Other users have no rights over the directory at all.

Without doing anything extra, though, on our ACL-enabled filesystem, we have also created an ACL for the directory.   We can view the ACL of a file or directory using the getfacl utility. Using getfacl acldir we see:

# file: acldir
# owner: foo
# group: bar
user::rwx
group::r-x
other::—

This shows the directory to have what is termed a minimal ACL.  Minimal ACLs correspond directly to the traditional file permissions to which you are already accustomed.   The information given by getfacl is therefore very similar to that obtained using ls.  The headers of the output (the first three lines) show the file name, file owner, and group.  These headers can be suppressed using the –omit-headeroption to getfacl.  The next lines show the permissions for the three permission fields user, group, and other in the form field::rwx.

The same is true for files.  If we create a file with touch acldir/aclfile, the output from getfacl acldir/aclfile shows:

# file: acldir/aclfile
# owner: foo
# group: bar
user::rw-
group::r–
other::—

ls -l shows the file to have -rw-r—– permissions, as expected.   This direct mapping of minimal ACLs and the traditional file permissions ensures a level of compatibility between filesystems with ACL support and those without.

So far we have seen nothing to set ACLs apart from the traditional permissions we are used to.  The extra capabilities of ACLs are provided by extended ACLs.  This second class of ACLs extends the traditional system by adding three additional permission fields:named usernamed group, and mask.

The named user field allows us to set the permissions of a file or directory for a specific user.  Similarly, the named group field allows us to set permissions for a particular group.  I’ll explain the mask field in detail shortly.  First, let’s look at an example.

Suppose we wish to give a particular user, scooby, and a particular group, doo, full access (rwx) to the acldir directory we created above.  We do this by creating an extended ACL with the setfacl utility.   After using the command setfacl -m user:scooby:rwx,group:doo:rwx acldir the output from getfacl acldir now looks like this:

# file: acldir
# owner: foo
# group: bar
user::rwx
user:scooby:rwx
group::r-x
group:doo:rwx
mask::rwx
other::—

The -m option tells setfacl to modify the permissions.  You can assign multiple permissions to be modified using a comma-separated list.

As you can see, the extended ACL fields for the named user scooby and the named group doo are now visible, along with a mask entry.  The text representation of the fields is similar to what we saw above with minimal ACLs, with the only difference being that named users and groups are shown by the presence of the group or user name in the form field:name:rwx.   ACLs are passed to setfacl using the same text representation.

File permissions can be modified in the same way.  If we execute

setfacl -m user:scooby:rw,user:scrappy:rw,user:daphne:rw acldir/aclfile

the output from getfacl acldir/aclfile now shows:

# file: acldir/aclfile
# owner: foo
# group: bar
user::rw-
user:scooby:rw-
user:scrappy:rw-
user:daphne:rw-
group::r–
mask::rw-
other::—

Mask permissions are created automatically by merging the owning group, named group, and named user permissions, unless you specify otherwise with the -n option.  The -n option keeps the mask field unchanged if one exists, or otherwise create a new mask from the existing group permissions.

If we view our directory with ls -ld acldir, the output now looks like this:

drwxrwx—+ 2 foo bar 4096 Jul 03 12:20 acldir

The group permissions are now shown as rwx, reflecting the mask permissions of the extended ACL.  This would seem to indicate that group bar now has write access to the directory, but that is not the case; bar‘s access is still determined by the owning group permissions from the ACL, i.e. r-x.  Unfortunately we can’t tell this by looking solely at the output of ls.   The ls command appends a + to the permissions (drwxrwx—+) to indicate the presence of an extended ACL.  (However, when I tested this on Slackware running the 2.6.6 kernel, the + was absent.)

The mask field applies to the named user, owning group, and named group permission fields.  If a mask entry is present in an ACL, a permission bit must be set in both the mask and the field for it to be effective.   If a permission bit is present only in either the mask or the entry, it will not be effective.   For example:

Field       | Permissions
------------+---------------
named user  | user:john:rwx
mask        | mask::r-x

User john has the effective permissions of r-x; he will not have write access to the file, as w is not set in the mask.

In the case of file systems where ACLs are not supported, the mask permissions of an extended ACL are mapped to the group permissions in the traditional permission system.  The named user, named group, and owning group permissions are ignored.  Our aclfile from the example above would therefore be seen to have permissions of -rw-rw—- on a file system without ACL support, and the extended ACL information would be lost.

It is possible to modify the mask permissions of an extended ACL using either chmod or setfacl.   For example, chmod g-w acldir normally removes write permissions for the group class.   With an extended ACL, the chmod command now modifies the mask permissions.   After executing this command, ls -ld acldir shows:

drwxr-x—+ 2 foo bar 4096 Jul 03 12:20 acldir

and getfacl acldir displays:

# file: acldir
# owner: foo
# group: bar
user::rwx
user:scooby:rwx # effective: r-x
group::r-x
group:doo:rwx # effective: r-x
mask::r-x
other::—

Notice only the mask has changed, but now the named user and group entries have effective permissions of r-x.  getfacl indicates this by adding a comment showing the effective permissions next to the appropriate entry.   We could have achieved the same result using the command setfacl -m mask::r-x acldir.

The maskgroupuser, and other options to setfacl can all be shortened to their respective initials.   We can therefore shorten the command setfacl -m user:scooby:rwx,group:doo:rwx acldir to setfacl -m u:scooby:rwx,g:doo:rwx acldir.  Omitting the group or user name from the ACL applies the permissions to the owning group or user, as in

setfacl -m u::rwx,g::rwx acldir

Entries can be removed from an ACL by passing the -x option to setfacl.  For example, to remove the scooby entry from acldir, we would use setfacl -x u:scooby acldir.   The -b option to setfacl removes (or blanks) all extended ACL permissions from a file or directory.

Default ACLs

You can assign default ACLs to directories to specify the initial ACLs of any files or subdirectories created within them.  To add a default ACL to a directory, use setfacl‘s -d option.   If we run the command setfacl -d -m group:doo:r-x acldir and check our results with getfacl acldir we now see:

# file: acldir
# owner: foo
# group: bar
user::rwx
user:scooby:rwx
group::r-x
group:doo:rwx
mask::rwx
other::—
default:user::rwx
default:group::r-x
default:group:doo:r-x
default:mask::r-x
default:other::—

Notice that, although our command only specified the default permissions to be used for named group, default permissions were assigned to the other classes by copying the corresponding existing permissions on the directory.  These default permissions do not affect existing files in the directory, only newly created files and directories.

If we now create a subdirectory in acldir using mkdir aclsubdir and view the permissions using getfacl aclsubdir we see:

# file: aclsubdir
# owner: foo
# group: bar
user::rwx
group::r-x
group:doo:r-x
mask::rwx
other::—
default:user::rwx
default:group::r-x
default:group:doo:r-x
default:mask::r-x
default:other::—

The new directory has inherited the permissions of the parent directory.   No access is granted to the named user scooby as no corresponding entry is present in the default ACL of the parent directory.

Just as with directories, when we create a new file using touch newfile in the acldir directory, the default ACLs affect the permissions of the new file. getfacl newfile shows:

# file: newfile
# owner: foo
# group: bar
user::rw-
group::r–
group:doo:r-x #effective:r–
mask::r–
other::—

The named group doo has the effective permissions of read-only because, without any default ACLs present, touch would have created a file with -rw-r—– permissions.  The group’s permissions, r–, are translated to the mask entry of the extended ACL.

Default ACLs can be modified by prepending d: or default: to the ACL passed to setfacl. For example, setfacl -m d:u::rx acldir changes the default user entry of acldir to r-x.  The -k option to setfacl removes the default ACL from a file or directory.

Uses of ACLs

As we stated earlier, ACLs can be used in place of complicated directory structures and user groups.  Individual users can assign access rights to other users without having to belong to the same user group or have root privileges.

ACLs can be used to control access to SUID binaries.  For example, certain binaries may need to be SUID root to run but, because of security concerns such as buffer overflows, you may not want to give access to such programs to your general users.   Using ACLs you can easily grant access to only those specific users or groups that need access to a program.

ACLs can also be used in conjunction with Samba to integrate a Linux server with a Windows 2000 domain running Active Directory.  Although the relationship between POSIX ACLs and Windows 2000 ACLs is not 1:1, the relationship is close enough that you can perform most, although not all, actions on the server’s file system from a Windows client.

Backup

Unfortunately, the standard tar and cpio backup utilities do not currently support the backup of ACLs.  If you need to perform backups of filesystems that make use of ACLs, you should use the Star archiver.

setfacl also has the ability to restore ACLs from a file created by dumping the output of getfacl. For example, if create your dump file with getfacl -R * > getfacl.out, you can restore it using setfacl –restore=getfacl.out.   While this can be useful when restoring a whole filesystem, it is not so useful when you only need to restore a small number of files.

Summary

ACLs allow for more complicated permission models than the traditional permission implementation permits.   They are a welcome and necessary addition an administrator’s arsenal, but their current implementation has some limitations.  Finer control of users’ rights, such as restricting the ability to create or delete files while allowing write access and setting append-only or immutable permissions through ACLs, would be useful.

While the basic command line utilities (such as cp and mv) support ACLs already, in general, application support for ACLs is very limited.  For example, I know of no desktop file managers that support the editing of ACLs, and many editors alter ACLs unexpectedly when saving files.  Therefore, if you choose to use ACLs, test them carefully and thoroughly before rolling them into a production environment.

Mike Peters is a freelance consultant and programmer and long-time Linux user.