Read Linux ACLs Safely with getfacl
getfacl shows the access control list on a file, including named users, named groups and the effective-rights mask. Plain owner and group bits never reveal any of that. The examples use getfacl from acl version 2.3.2-1build1.1. Allow about ten minutes.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need a shell and read access to the paths you are checking. Nothing in this guide changes permissions or restarts a service.
1. Inspect One File
Start with a path you can read. Use -p when you want the full path in the header:
$ getfacl -p /srv/project/report.txt
# file: /srv/project/report.txt
# owner: alice
# group: analysts
user::rw-
group::r--
other::---
- Base entries. The three base lines correspond to the file mode's owner, group and other permissions.
- Named entries. A line such as
user:bob:r--grants rights to Bob specifically. A named group works the same way for a group. - Comment lines. The leading
#lines describe the file, owner and group; they are not ACL entries themselves.
Checkpoint
Confirm the path, owner and group are the ones you meant. If the command says permission is denied, do not jump straight to sudo. Check the containing directory and the file first:
$ namei -l /srv/project/report.txt
$ ls -l /srv/project/report.txt
Reading an ACL needs search access to the containing directory, much like reading the file itself. Use elevated privileges only when your access policy allows it and the diagnostic genuinely needs them:
$ sudo getfacl -p /srv/project/report.txt
2. Read the Mask Correctly
Extended ACLs usually include a mask:: entry. It caps the effective rights of named users, named groups and the owning group. It does not limit the file owner or the other:: entry:
$ getfacl -p /srv/project/shared.txt
# file: /srv/project/shared.txt
# owner: alice
# group: analysts
user::rw-
user:bob:rwx #effective:r--
group::r-- #effective:r--
group:reviewers:r-x #effective:r--
mask::r--
other::---
Bob's ACL entry says rwx, but the mask is r--, so his effective rights are read-only. The same cap applies to the owning group and the named group. Do not read the text before #effective: as what a user actually gets.
By default, effective-rights comments appear only when they differ from the entry. Use -e to show every effective-rights comment, and -E to suppress them. Suppressing the comments changes the display, not the ACL:
$ getfacl -E -p /srv/project/shared.txt
$ getfacl -e -p /srv/project/shared.txt
3. Check a Directory's Default ACL
A directory can carry a default ACL that new children inherit, separate from its access ACL. Ask for it explicitly with -d:
$ getfacl -p -d /srv/project
# file: /srv/project
# owner: alice
# group: analysts
user::rwx
group::r-x
mask::r-x
other::---
The exact entries depend on the directory. A regular file cannot have a default ACL, and a directory without one reports that no default ACL exists. That is a useful result: it means there is no directory-level default to inspect, not that the command silently found an empty policy.
Tip
For the normal combined view, omit -d: getfacl prints the access ACL and, when present, the directory's default ACL together. Use -a for the access ACL alone only when a script or comparison needs to exclude defaults.
4. Make Paths and Identities Unambiguous
Without -p, getfacl strips leading slashes from absolute paths and may print a notice on standard error. It still read the same file, but the stripped output can confuse anyone copying it later. Keep -p in reports and troubleshooting commands.
Names are easier to read, but they can change or be missing on another host. Use -n for numeric user and group IDs when comparing machines or preserving evidence:
$ getfacl -n -p /srv/project/shared.txt
# file: /srv/project/shared.txt
# owner: 1001
# group: 1008
user::rw-
group::r--
other::---
Use -c to drop the first three comment lines when a consumer only needs the ACL entries themselves. Do not use it as a substitute for recording the file's identity; capture the path separately in your report.
5. Inspect a Tree Without Following Surprise Links
-R reads a directory tree recursively. The default walk follows a symbolic-link argument but skips symbolic links found below the starting directory. Make that boundary explicit in scripts: -P forces a physical walk, -L follows symbolic links to directories. Both only affect recursive operation:
$ getfacl -R -P -p /srv/project > project-acls.txt
$ sed -n '1,24p' project-acls.txt
Redirection creates or truncates project-acls.txt. Pick a new report path, or protect an existing one, before you rely on that form:
$ getfacl -R -P -p /srv/project > project-acls.txt.new
$ test -s project-acls.txt.new && mv project-acls.txt.new project-acls.txt
The first command only reads the tree. The second replaces the old report only if the new file is non-empty. If it fails, inspect the error and keep the previous report; remove the leftover .new file later, once you have checked it is disposable.
6. Use Lists and Machine-Friendly Checks
A single dash tells getfacl to read file names from standard input, handy when another command has already picked the paths:
$ printf '%s\n' /srv/project/report.txt /srv/project/shared.txt | getfacl -p -
Put -- before a path that starts with a dash, so it cannot be mistaken for an option:
$ getfacl -p -- ./-draft.txt
On a file system without ACL support, getfacl shows the permissions represented by the traditional mode bits. That output is still useful, but it does not prove extended named entries are available. If a report needs comparing later, record the command, the full path and whether -n, -p or -R was used.
Done means
- Path confirmed. You inspected the intended path and checked its owner, group and base entries.
- Mask understood. You treated the mask as the limit on effective group and named-user rights.
- Defaults checked separately. A directory's default ACL was inspected on its own when inheritance mattered.
- Identities unambiguous. You used
-pfor full paths and-nwhen numeric identities mattered. - Recursion deliberate. You chose
-Por-Lon purpose and did not overwrite a useful report by accident.