Access Control Lists (ACLs)

Updated: May 06, 2022

Some filesystems, such as the Power-Safe (fs-qnx6.so) filesystem, extend file permissions with Access Control Lists.

With the traditional file permissions as set with chmod, if you want someone to have special access to a file, you have few choices:

Keeping track of the users in each group can become complicated, and allowing “others” additional permissions can make your system less secure. ACLs extend file permissions, giving you finer control over who has access to what. In an ACL, the permissions are divided into these classes:

An access control list consists of a number of entries, each in one of the following forms (given with the constants used in code to identify the tag type):

Entry type Tag type Form
Owner ACL_USER_OBJ user::permissions
Named user (identified by name or by numerical ID) ACL_USER user:user_identifier:permissions
Owning group ACL_GROUP_OBJ group::permissions
Named group (identified by name or numerical ID) ACL_GROUP group:group_identifier:permissions
The upper bound on permissions for the group class ACL_MASK mask::permissions
Others ACL_OTHER other::permissions

The permissions are in the form rwx, with a hyphen (-) replacing any permissions that aren't granted. Here's an example of the ACL for a file:

user::rw-
user:violetta:r--
group::rw-
mask::rw-
other::---

The owner of the file has read and write permissions, as does the owning group. Others have no permissions at all. The user violetta has been granted read permission, so she's more privileged than “others”, but not quite as privileged as the owning user or group. If violetta hadn't been granted a special permission, the ACL would be the same as file permissions of rw-rw----.

If an ACL can be represented simply as file permissions, it's called a minimal ACL; if it can't, it's called an extended ACL. An extended ACL always has a mask entry, and can include any number of entries for named users and named groups. If a file or directory has an extended ACL, its permissions in the output of ls -l are followed by a plus sign (+).

The mask entry is the union of the permissions for the owning group, all named users, and all named groups. For example, let's consider a file whose owning group has no write permission:

# ls -l file.txt
-rw-r--r--   1 mabel    techies          50 Sep 27 21:22 file.txt

If we use the getfacl utility to get its ACL, we see:

# getfacl -q file.txt
user::rw-
group::r--
other::r--

The -q option suppresses some comments, listing the file name, owner, and group, that getfacl displays by default. Next, let's suppose that mabel uses setfacl to add an entry for frank that grants him read and write permission (in order to modify the ACL, you must be the owner of the file or directory, or have appropriate privileges):

# setfacl -m u:frank:rw- file.txt
# getfacl -q file.txt
user::rw-
user:frank:rw-
group::r--
mask::rw-
other::r--
# ls -l file.txt
-rw-rw-r--+  1 mabel    techies          50 Sep 27 21:22 file.txt

In addition to the entry for frank, the ACL now includes a mask entry that lists read and write permission. The output of ls also indicates read and write permission for the group.

Modifying the file permissions (e.g., using chmod) can affect the ACLs, and vice versa:

Let's continue with the same sample file. Now, let's have mabel use chmod to remove write permission for the group:

# chmod g-w file.txt
# getfacl -q file.txt
user::rw-
user:frank:rw-          # effective: r--
group::r--
mask::r--
other::r--
# ls -l file.txt
-rw-r--r--+  1 mabel    techies          50 Sep 27 21:22 file.txt

The entry for frank still lists read and write permission, but a comment warns us that his effective permissions are read only, because we explicitly removed write permission from the mask.

The following pseudo-code shows the algorithm for checking the access to a file or directory:

if (the process's effective user ID matches the object owner's user ID)
{
   The matched entry is the owner ACL entry
}
else if (the process's effective user ID matches the user ID specified in any
         named user ACL entry)
{
   The matched entry is the matching named user entry
}
else if (the process's effective group ID or any of its supplementary group IDs
         matches the group ID of the object or matches the group ID
         specified in any named group entry)
{
   if (the requested access modes are granted by at least one entry
       matched by the process's effective group ID or any of its supplementary
       group IDs)
   {
       The matched entry is one of the granting entries (it doesn't matter which)
   }
   else
   {
       Access is denied
   }
}
else if (the requested access modes are granted by the “other” ACL entry)
{
   The matched entry is the “other” entry
}

if (the requested access modes are granted by the matched entry)
{
   if (the matched entry is the owning user or “other” entry)
   {
       Access is granted
   }
   else if (the requested access modes are also granted by the mask entry,
            or no mask entry exists in the ACL)
   {
       Access is granted
   }
   else
   {
       Access is denied
   }
}
else
{
    Access is denied
}

For more information about getfacl or setfacl, see the Utilities Reference.

There are also functions that you can use to work with ACLs in your programs; for information about them, see Working with Access Control Lists in the QNX Neutrino Programmer's Guide, and the acl_*() entries in the QNX Neutrino C Library Reference.

Note: