POSIX ACLs in Linux

4783

Author: 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-header option 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 user,
named 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 mask, group, user, 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.

Category:

  • Security