ACL(5)
โจ ACL โ Access Control Lists โจ
okay bestie, welcome to acl(5), which is the File Formats Manual's little corner of the universe where we talk about Access Control Lists ๐
this is the section 5 page, so it's all about the format, not the tools โ those live elsewhere and we'll get to them.
๐ธ DESCRIPTION ๐ธ
So. This page describes POSIX Access Control Lists, aka ACLs, which exist so you can define more fine-grained discretionary access rights for files and directories than the plain old permission bits could ever dream of. it's giving "who's allowed to do what, and honestly, in detail." ๐
๐ฆ ACL TYPES ๐ฆ
Every object can be thought of as having an ACL associated with it that governs the discretionary access to that object โ this one is called the access ACL. ๐ซถ
Plus, a directory may have its own associated ACL that governs the initial access ACL for objects created inside that directory. That one is called the default ACL. so it's like the directory is the mom friend handing out vibes to every new file born in there. ๐
๐ ACL ENTRIES ๐
An ACL is a set of ACL entries, periodt. Each entry specifies the access permissions on the associated object for an individual user or a group of users, as a combination of read, write and search/execute permissions. ๐
An ACL entry contains:
- an entry tag type
- an optional entry tag qualifier
- and a set of permissions
and we use the term qualifier to mean the entry tag qualifier of an ACL entry. iykyk.
The qualifier denotes the identifier of a user or a group โ for entries with tag types of ACL_USER or ACL_GROUP, respectively. Entries with tag types other than ACL_USER or ACL_GROUP have no defined qualifiers. so don't go looking for one. ๐
The following entry tag types are defined:
ACL_USER_OBJโ theACL_USER_OBJentry denotes access rights for the file owner. main character energy, obviously. ๐ACL_USERโACL_USERentries denote access rights for users identified by the entry's qualifier.ACL_GROUP_OBJโ theACL_GROUP_OBJentry denotes access rights for the file group.ACL_GROUPโACL_GROUPentries denote access rights for groups identified by the entry's qualifier.ACL_MASKโ theACL_MASKentry denotes the maximum access rights that can be granted by entries of typeACL_USER,ACL_GROUP_OBJ, orACL_GROUP. it's the ceiling, bestie, the vibe check that caps everyone. โจACL_OTHERโ theACL_OTHERentry denotes access rights for processes that do not match any other entry in the ACL.
When an access check is performed, the ACL_USER_OBJ and ACL_USER entries are tested against the effective user ID. The effective group ID, as well as all supplementary group IDs, are tested against the ACL_GROUP_OBJ and ACL_GROUP entries. ๐ง
๐ VALID ACLs ๐
A valid ACL contains exactly one entry with each of the ACL_USER_OBJ, ACL_GROUP_OBJ, and ACL_OTHER tag types. no more, no less, it's a strict little trio. ๐
Entries with ACL_USER and ACL_GROUP tag types may appear zero or more times in an ACL. An ACL that contains entries of ACL_USER or ACL_GROUP tag types must contain exactly one entry of the ACL_MASK tag type. If an ACL contains no entries of ACL_USER or ACL_GROUP tag types, the ACL_MASK entry is optional. ๐
All user ID qualifiers must be unique among all entries of ACL_USER tag type, and all group IDs must be unique among all entries of ACL_GROUP tag type. no duplicates, that's the rule. ๐
โ๏ธ
The acl_get_file() function returns an ACL with zero ACL entries as the default ACL of a directory, if the directory is not associated with a default ACL. The acl_set_file() function also accepts an ACL with zero ACL entries as a valid default ACL for directories, denoting that the directory shall not be associated with a default ACL. This is equivalent to using the acl_delete_def_file() function. cute little shortcut, lowkey. ๐
๐ CORRESPONDENCE BETWEEN ACL ENTRIES AND FILE PERMISSION BITS ๐
The permissions defined by ACLs are a superset of the permissions specified by the file permission bits. yes, they're related, they're not strangers. ๐ธ
There's a correspondence between the file owner, group, and other permissions and specific ACL entries:
- the owner permissions correspond to the permissions of the
ACL_USER_OBJentry. - If the ACL has an
ACL_MASKentry, the group permissions correspond to the permissions of theACL_MASKentry. - Otherwise, if the ACL has no
ACL_MASKentry, the group permissions correspond to the permissions of theACL_GROUP_OBJentry. - The other permissions correspond to the permissions of the
ACL_OTHERentry.
The file owner, group, and other permissions always match the permissions of the corresponding ACL entry. Modification of the file permission bits results in the modification of the associated ACL entries, and modification of these ACL entries results in the modification of the file permission bits. it goes both ways, it's a whole relationship. ๐
๐ง OBJECT CREATION AND DEFAULT ACLs ๐ง
The access ACL of a file object is initialized when the object is created with any of the creat(), mkdir(), mknod(), mkfifo(), or open() functions. ๐ซถ
If a default ACL is associated with a directory, the mode parameter to the functions creating file objects and the default ACL of the directory are used to determine the ACL of the new object:
- The new object inherits the default ACL of the containing directory as its access ACL.
- The access ACL entries corresponding to the file permission bits are modified so that they contain no permissions that are not contained in the permissions specified by the
modeparameter.
If no default ACL is associated with a directory, the mode parameter to the functions creating file objects and the file creation mask (see umask(2)) are used to determine the ACL of the new object:
- The new object is assigned an access ACL containing entries of tag types
ACL_USER_OBJ,ACL_GROUP_OBJ, andACL_OTHER. The permissions of these entries are set to the permissions specified by the file creation mask. - The access ACL entries corresponding to the file permission bits are modified so that they contain no permissions that are not contained in the permissions specified by the
modeparameter.
so like, either way, step 2 is always there doing its little filtering thing. iconic consistency. โจ
๐ ACCESS CHECK ALGORITHM ๐
A process may request read, write, or execute/search access to a file object protected by an ACL. The access check algorithm determines whether access to the object will be granted. let's go through it, bestie, in order, no skipping. ๐
- If the effective user ID of the process matches the user ID of the file object owner, then
- if the
ACL_USER_OBJentry contains the requested permissions, access is granted, - else access is denied.
- if the
- else if the effective user ID of the process matches the qualifier of any entry of type
ACL_USER, then- if the matching
ACL_USERentry and theACL_MASKentry contain the requested permissions, access is granted, - else access is denied.
- if the matching
- else if the effective group ID or any of the supplementary group IDs of the process match the file group or the qualifier of any entry of type
ACL_GROUP, then- if the ACL contains an
ACL_MASKentry, then- if the
ACL_MASKentry and any of the matchingACL_GROUP_OBJorACL_GROUPentries contain the requested permissions, access is granted, - else access is denied.
- if the
- else (note that there can be no
ACL_GROUPentries without anACL_MASKentry)- if the
ACL_GROUP_OBJentry contains the requested permissions, access is granted, - else access is denied.
- if the
- if the ACL contains an
- else if the
ACL_OTHERentry contains the requested permissions, access is granted. - else access is denied. ๐
ngl the algorithm is just an if/else ladder wearing a fancy hat. respect it anyway. ๐ฉ
๐ ACL TEXT FORMS ๐
A long and a short text form for representing ACLs is defined. In both forms, ACL entries are represented as three colon separated fields:
- an ACL entry tag type
- an ACL entry qualifier
- the discretionary access permissions
The first field contains one of the following entry tag type keywords:
userโ a user ACL entry specifies the access granted to either the file owner (entry tag typeACL_USER_OBJ) or a specified user (entry tag typeACL_USER).groupโ a group ACL entry specifies the access granted to either the file group (entry tag typeACL_GROUP_OBJ) or a specified group (entry tag typeACL_GROUP).maskโ a mask ACL entry specifies the maximum access which can be granted by any ACL entry except the user entry for the file owner and the other entry (entry tag typeACL_MASK).otherโ an other ACL entry specifies the access granted to any process that does not match any user or group ACL entries (entry tag typeACL_OTHER).
The second field contains the user or group identifier of the user or group associated with the ACL entry for entries of entry tag type ACL_USER or ACL_GROUP, and is empty for all other entries. A user identifier can be a user name or a user ID number in decimal form. A group identifier can be a group name or a group ID number in decimal form. ๐
The third field contains the discretionary access permissions. The read, write and search/execute permissions are represented by the r, w, and x characters, in this order. Each of these characters is replaced by the - character to denote that a permission is absent in the ACL entry. When converting from the text form to the internal representation, permissions that are absent need not be specified. ๐
White space is permitted at the beginning and end of each ACL entry, and immediately before and after a field separator (the colon character). so breathe, bestie, the parser is chill about spaces. ๐ง
๐ LONG TEXT FORM ๐
The long text form contains one ACL entry per line. In addition, a number sign (#) may start a comment that extends until the end of the line. ๐
If an ACL_USER, ACL_GROUP_OBJ or ACL_GROUP ACL entry contains permissions that are not also contained in the ACL_MASK entry, the entry is followed by a number sign, the string effective:, and the effective access permissions defined by that entry. so you get to see what the mask is actually letting through. very transparent of it. โจ
This is an example of the long text form:
user::rw-
user:lisa:rw- #effective:r--
group::r--
group:toolies:rw- #effective:r--
mask::r--
other::r--
see how lisa and toolies are asking for rw- but the mask is like "no babe, r-- for you"? that's the #effective: note doing its thing. ๐
๐ SHORT TEXT FORM ๐
The short text form is a sequence of ACL entries separated by commas, and is used for input. Comments are not supported. ๐ซ
Entry tag type keywords may either appear in their full unabbreviated form, or in their single letter abbreviated form:
- the abbreviation for
userisu - the abbreviation for
groupisg - the abbreviation for
maskism - the abbreviation for
otheriso
The permissions may contain at most one each of the following characters in any order: r, w, x. ๐
These are examples of the short text form:
u::rw-,u:lisa:rw-,g::r--,g:toolies:rw-,m::r--,o::r--
g:toolies:rw,u:lisa:rw,u::wr,g::r,o::r,m::r
look at the second one, it's all out of order and it still slays. u::wr โ write and read, no x, we love a flexible format. ๐
๐ RATIONALE ๐
Okay bestie, history lesson time because this is lowkey iconic. IEEE 1003.1e draft 17 defines Access Control Lists that include entries of tag type ACL_MASK, and it defines a mapping between file permission bits that is not constant โ yes, it moves around, she's not stable and we love her anyway.
The standard working group defined this relatively complex interface on purpose: to make sure that applications compliant with IEEE 1003.1 (โPOSIX.1โ) will still function as expected on systems with ACLs. The IEEE 1003.1e draft 17 contains the rationale for choosing this interface in section B.23, if you want the full lore. โจ
๐ ๏ธ CHANGES TO THE FILE UTILITIES ๐ ๏ธ
So on a system that supports ACLs, the file utilities ls(1), cp(1), and mv(1) switch up their behavior like this:
- For files that have a default ACL or an access ACL that contains more than the three required ACL entries, the
ls(1)utility in the long form produced byls -ldisplays a plus sign (+) after the permission string. That little+is the vibe check, fr fr. ๐ - If the
-pflag is specified, thecp(1)utility also preserves ACLs. If this is not possible, a warning is produced. - The
mv(1)utility always preserves ACLs. If this is not possible, a warning is produced. No cap, she's committed. ๐ซถ
The effect of the chmod(1) utility, and of the chmod(2) system call, on the access ACL is described in โCORRESPONDENCE BETWEEN ACL ENTRIES AND FILE PERMISSION BITSโ โ you already got that section bestie, go reread it if you're fuzzy. ๐ญ
๐ STANDARDS ๐
The IEEE 1003.1e draft 17 (โPOSIX.1eโ) document describes several security extensions to the IEEE 1003.1 standard. And listen โ while the work on 1003.1e has been abandoned ๐, many UNIX style systems implement parts of POSIX.1e draft 17, or of earlier drafts. The ghost of a standard still haunts us all.
Linux Access Control Lists implement the full set of functions and utilities defined for Access Control Lists in POSIX.1e, plus several extensions. The implementation is fully compliant with POSIX.1e draft 17; extensions are marked as such. The Access Control List manipulation functions are defined in the ACL library (libacl, -lacl). The POSIX compliant interfaces are declared in the <sys/acl.h> header. Linux-specific extensions to these functions are declared in the <acl/libacl.h> header.
๐ NOTES ๐
๐ซ DENIED PERMISSIONS AND LINUX USER NAMESPACES ๐ซ
Okay so โ while ACLs can be used to deny processes permissions based on the groups they're in, this is considered bad practice. Not me telling you this is a red flag but like... it's a red flag, bestie. ๐
Privileged helpers such as newuidmap(1) can give unprivileged processes access to the setgroups(2) system call, which allows them to drop supplementary group membership and render restrictions based on that membership ineffective. So the denial just... doesn't deny. It's giving fake security. ๐
For further details, see user_namespaces(7).
๐ SEE ALSO ๐
chmod(1), creat(2), getfacl(1), ls(1), mkdir(2), mkfifo(2), mknod(2), mount(8), open(2), setfacl(1), stat(2), umask(1)
๐ POSIX 1003.1e DRAFT 17 ๐
https://wt.tuxomania.net/publications/posix.1e/download.html
๐ POSIX 1003.1e FUNCTIONS BY CATEGORY ๐
๐๏ธ ACL storage management
โ๏ธ ACL entry manipulation
acl_copy_entry(3),acl_create_entry(3),acl_delete_entry(3),acl_get_entry(3),acl_valid(3)acl_add_perm(3),acl_calc_mask(3),acl_clear_perms(3),acl_delete_perm(3),acl_get_permset(3),acl_set_permset(3)acl_get_qualifier(3),acl_get_tag_type(3),acl_set_qualifier(3),acl_set_tag_type(3)
๐ฏ ACL manipulation on an object
๐ ACL format translation
๐ POSIX 1003.1e FUNCTIONS BY AVAILABILITY ๐
The first group of functions is supported on most systems with POSIX-like access control lists, while the second group is supported on fewer systems. For applications that will be ported, the second group is best avoided. Like, bestie, don't build your whole personality on the rare ones if you wanna travel. ๐ญ
acl_delete_def_file(3),acl_dup(3),acl_free(3),acl_from_text(3),acl_get_fd(3),acl_get_file(3),acl_init(3),acl_set_fd(3),acl_set_file(3),acl_to_text(3),acl_valid(3)acl_add_perm(3),acl_calc_mask(3),acl_clear_perms(3),acl_copy_entry(3),acl_copy_ext(3),acl_copy_int(3),acl_create_entry(3),acl_delete_entry(3),acl_delete_perm(3),acl_get_entry(3),acl_get_permset(3),acl_get_qualifier(3),acl_get_tag_type(3),acl_set_permset(3),acl_set_qualifier(3),acl_set_tag_type(3),acl_size(3)
๐ง LINUX EXTENSIONS ๐ง
These non-portable extensions are available on Linux systems. She's exclusive, she's local, she doesn't travel. ๐
acl_check(3),acl_cmp(3),acl_delete_def_file_at(3),acl_entries(3),acl_equiv_mode(3),acl_error(3),acl_extended_fd(3),acl_extended_file(3),acl_extended_file_at(3),acl_extended_file_nofollow(3),acl_from_mode(3),acl_get_file_at(3),acl_get_perm(3),acl_set_file_at(3),acl_to_any_text(3)
๐ซถ AUTHOR ๐ซถ
Andreas Gruenbacher, <andreas.gruenbacher@gmail.com> โ the icon, the moment, the main character who wrote all this down so we could read it. ๐
That's the whole page bestie, you made it to the end!! ๐ This one came from the Linux ACL manual page set, dated June 5, 2026 โ go forth and setfacl responsibly, mwah ๐๐ฆโจ
๐ฆ where this page comes from
- arch rolling: acl 2.4.0-1 ยท LGPL-2.1-or-later AND GPL-2.0-or-later
- centos-stream 10: acl 2.4.0-2.el10 ยท GPL-2.0-or-later AND LGPL-2.1-or-later
- centos-stream 9: acl 2.4.0-2.el9 ยท GPLv2+
- fedora 43: acl 2.4.0-1.fc43 ยท GPL-2.0-or-later AND LGPL-2.1-or-later
- fedora 44: acl 2.4.0-1.fc44 ยท GPL-2.0-or-later AND LGPL-2.1-or-later
- nixpkgs unstable: acl 2.4.0
- opensuse-leap 16.0: acl 2.4.0-160000.1.1 ยท GPL-2.0-or-later AND LGPL-2.1-or-later
- opensuse-leap 16.0: acl 2.4.0-160000.1.1 ยท GPL-2.0-or-later AND LGPL-2.1-or-later
- opensuse-leap 16.0: acl 2.4.0-160000.1.1 ยท GPL-2.0-or-later AND LGPL-2.1-or-later
- opensuse-leap 16.0: acl 2.4.0-160000.1.1 ยท GPL-2.0-or-later AND LGPL-2.1-or-later
- ubuntu stonking: acl 2.4.0-1
- (C) 2002 Andreas Gruenbacher, <andreas.gruenbacher@gmail.com>
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms