Linux getfacl Command for Granular Permissions
Standard Linux file permissions follow the traditional
User-Group-Other (UGO) model, which often lacks the flexibility required
for complex environments. To overcome this limitation, Linux utilizes
POSIX Access Control Lists (ACLs), and the getfacl (get
file access control list) command is the primary utility used to display
and verify these granular permissions. This article explains how the
Linux operating system retrieves, interprets, and displays file ACLs
using getfacl, covering underlying system calls, extended
file attributes, and permission evaluation mechanics.
How Linux Stores Granular Permissions
Traditional Linux permissions use 9 mode bits (read, write, execute for owner, group, and others) stored directly inside the file's inode metadata. Because an inode has limited space, it cannot store arbitrary numbers of user or group rules.
To support ACLs, Linux relies on Extended Attributes
(xattr). When you assign granular permissions using
setfacl, the filesystem stores these additional rules in a
dedicated extended attribute namespace named
system.posix_acl_access. For directories, default
inheritance rules are stored under
system.posix_acl_default.
How the OS Executes
getfacl
When a user executes getfacl <path>, the Linux
operating system handles the request through several internal steps:
- System Calls Execution: The
getfaclbinary invokes system calls such asgetxattr()orfgetxattr()targeting the specified path, requesting thesystem.posix_acl_accessattribute. - Virtual File System (VFS) Routing: The Linux VFS layer determines whether the underlying filesystem (such as ext4, XFS, or Btrfs) was mounted with ACL support (typically enabled by default on modern distributions).
- Data Retrieval from Disk: The filesystem driver reads the extended attribute blocks linked to the inode and passes the raw binary ACL structure back to user space.
- Binary Parsing: The
libacllibrary unpacks the binary representation into human-readable text and outputs it to standard output.
Anatomy of getfacl
Output
Running getfacl produces a structured report containing
file metadata and security descriptors:
# file: project_report.txt
# owner: alice
# group: developers
user::rw-
user:bob:r--
group::r--
group:qa:rw-
mask::rw-
other::---
Each component serves a specific function in permission verification:
- File Metadata: Lines preceded by
#indicate the file path, owner, and primary group. - Base Owner/Other:
user::andother::represent the traditional owner and world permissions. - Named User Entries:
user:bob:r--grants specific permissions to a named user without modifying file ownership. - Named Group Entries:
group:qa:rw-grants specific permissions to a secondary group without changing the file's primary group. - The Mask:
mask::defines the upper ceiling of permissions granted to all named users, named groups, and the owning group.
Resolving Effective Permissions and the Mask
A critical role of getfacl is displaying effective
permissions. If a named user has permissions that exceed the mask limit,
getfacl computes the bitwise AND between the entry and the
mask, appending a comment to show the effective rights:
user:bob:rwx #effective:r-x
mask::r-x
In this scenario, Linux prevents bob from writing to the
file because the mask restricts write access, regardless of the explicit
rwx grant.
Evaluating Directory Inheritance
When run against directories, getfacl also queries the
system.posix_acl_default attribute. Default permissions do
not restrict the directory itself; instead, the Linux kernel reads them
upon creating any new child file or subdirectory within that parent,
automatically applying the specified ACL rules to the newly created
inode.