Linux ACL Part 8: Complete Advanced ACL Guide

 

Linux ACL – Part 8
Comprehensive Interview Q&A — All Topics in One Place
40+ Questions
🧠
Concept + Code
🎯
All 7 Topics
💼
Interview Ready

This is your one-stop reference for Linux ACL interview preparation. The questions are grouped by topic, progress from basic to advanced, and include code-based questions that often appear in Linux system programming interviews. Each answer is detailed enough to satisfy a senior-level interviewer but clear enough to understand at a glance.

Jump to Topic
Overview & Tag Types Permission Algorithm Text Forms ACL_MASK getfacl / setfacl Default ACLs C API Implementation Limits Tricky / Scenario Questions

Section 1: Overview & Tag Types

Overview Q1. What is an Access Control List (ACL) and why is it needed in Linux?
Linux’s traditional file permission model grants permissions to three categories only: owner, group, and others. This is too coarse for scenarios where you need to give specific permissions to individual users or multiple groups without adding them all to the file’s group. ACLs extend this model by allowing per-user and per-group permissions for an arbitrary number of users and groups. Linux supports ACLs from kernel 2.6 onward and bases its implementation on the POSIX.1e Draft 17 standard.
Overview Q2. What are the six ACL tag types? Explain each briefly.
  • ACL_USER_OBJ — Permissions for the file owner. Exactly one per ACL.
  • ACL_USER — Permissions for a specific user identified by UID. Zero or more per ACL.
  • ACL_GROUP_OBJ — Permissions for the file’s owning group. Exactly one per ACL.
  • ACL_GROUP — Permissions for a specific group identified by GID. Zero or more per ACL.
  • ACL_MASK — Upper bound on permissions granted by ACL_USER, ACL_GROUP_OBJ, and ACL_GROUP entries combined. At most one per ACL.
  • ACL_OTHER — Permissions for users matching none of the above. Exactly one per ACL.
Overview Q3. What is the difference between a minimal ACL and an extended ACL?
A minimal ACL has exactly three entries — one each of ACL_USER_OBJ, ACL_GROUP_OBJ, and ACL_OTHER — and is semantically equivalent to the traditional Unix permission bits. It is stored in the standard inode permission bits and does not require an extended attribute. An extended ACL additionally contains ACL_USER, ACL_GROUP, and ACL_MASK entries. It requires the system.posix_acl_access extended attribute to be stored.
Overview Q4. How is an ACL stored on disk in Linux?
ACLs are stored as system extended attributes. The access ACL is stored in the extended attribute named system.posix_acl_access. The default ACL (on directories) is stored in system.posix_acl_default. For a minimal ACL, only the standard inode permission bits are used and no extended attribute is needed. To enable ACLs on ext2/ext3/ext4/Reiserfs, the file system must be mounted with the -o acl mount option.
Overview Q5. Can ACL_USER and ACL_GROUP have multiple entries for the same user or group?
No. An ACL may contain multiple ACL_USER entries, but at most one ACL_USER entry per specific user ID. Similarly, at most one ACL_GROUP entry per specific group ID is allowed. An ACL with duplicate entries for the same UID or GID is considered invalid and will be rejected by acl_valid().

Section 2: Permission-Checking Algorithm

Algorithm Q6. Describe the ACL permission-checking algorithm in order.

The kernel checks in this fixed order, stopping at the first match:

  1. Privileged process: All access granted. Exception: execute is granted only if at least one ACL entry grants it.
  2. ACL_USER_OBJ: If the process’s effective UID matches the file owner, permissions from this entry are used (no mask applied).
  3. ACL_USER: If the effective UID matches an ACL_USER entry’s qualifier, that entry’s permissions ANDed with ACL_MASK are granted.
  4. Group class: If any of the process’s group IDs (effective or supplementary) match the file group or any ACL_GROUP qualifier, the matching entry’s permissions ANDed with ACL_MASK are used. If a match is found but denies access, deny (no fallthrough to ACL_OTHER).
  5. ACL_OTHER: If none of the above matched, permissions from ACL_OTHER are granted.
Algorithm Q7. A process has GIDs 100 and 102. A file’s group is 100. The file’s ACL grants rwx via ACL_GROUP_OBJ and the mask is –x. The process requests read access. Is it granted?
The process matches the file group (GID 100 = ACL_GROUP_OBJ). The ACL_GROUP_OBJ grants rwx. But the result is ANDed with ACL_MASK (–x). So the effective permissions for this process via the group class are –x. Since the process requested read (r) and the effective permissions only allow execute (x), access is denied. This is the classic mask-restricts-group-class trap.
Algorithm Q8. Why is ACL_MASK NOT applied to the ACL_USER_OBJ entry?
ACL_USER_OBJ represents the file owner’s permissions. In Unix, the owner’s access is traditionally independent of group permissions. ACL_MASK is designed to be a cap on the “group class” (ACL_USER, ACL_GROUP_OBJ, ACL_GROUP). The owner’s entry is not part of the group class and therefore is never masked. Only ACL_USER, ACL_GROUP_OBJ, and ACL_GROUP entries are subject to masking by ACL_MASK.
Algorithm Q9. A process belongs to both group 102 and group 103. The ACL has an ACL_GROUP entry for 102 granting r– and an entry for 103 granting -w-. The process calls access(file, R_OK | W_OK). Does it succeed?
No, it fails. During group-class checking, the kernel looks for a single ACL_GROUP entry that grants all the requested permissions. The entry for GID 102 grants only read; the entry for GID 103 grants only write. No single entry grants both read and write together, so the kernel finds no matching entry that satisfies the combined R_OK | W_OK request, and access is denied.

Section 3: ACL Text Forms

Text Forms Q10. What are the two text forms of an ACL? Give an example of each.

Long text form: one entry per line, supports comments starting with #. Used by getfacl output and setfacl -M file. Example:

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

Short text form: all entries on one line separated by commas. Used with setfacl -m. Example:

u::rw-,u:alice:r--,g::r--,m::rw-,o::---
Text Forms Q11. Write the text form entry for: user paulh has read and execute; group teach has write only.

u:paulh:r-x,g:teach:-w- (short form) or equivalently:

user:paulh:r-x
group:teach:-w-

Note that you can also abbreviate permissions as rx and w (omitting the dash) in short text form.

Text Forms Q12. What is the difference between u::rwx and u:alice:rwx in ACL text form?
u::rwx (no qualifier between the colons) means ACL_USER_OBJ — permissions for the file owner. u:alice:rwx (with qualifier “alice”) means ACL_USER — permissions for the specific user named alice. The presence or absence of the tag qualifier is what distinguishes ACL_USER_OBJ from ACL_USER, and ACL_GROUP_OBJ from ACL_GROUP.

Section 4: ACL_MASK

Mask Q13. What is the purpose of the ACL_MASK entry?
ACL_MASK provides consistent behaviour for ACL-unaware applications that use chmod(). It acts as an upper bound on the permissions of the “group class” (ACL_USER, ACL_GROUP_OBJ, ACL_GROUP entries). When an ACL-unaware application calls chmod(file, mode), instead of destroying the fine-grained ACL_USER and ACL_GROUP entries, Linux changes the ACL_MASK entry to reflect the new group permissions. This preserves the individual per-user and per-group ACL entries while still honouring the semantics intended by the chmod() call.
Mask Q14. What does chmod() actually change when a file has an extended ACL?
When a file has an extended ACL (one with ACL_MASK present), chmod() changes ACL_MASK when you modify the group bits — not ACL_GROUP_OBJ. Similarly, the group permission bits returned by stat() in st_mode reflect the ACL_MASK permissions, not ACL_GROUP_OBJ. The owner and other bits still map directly to ACL_USER_OBJ and ACL_OTHER.
Mask Q15. What does the #effective: comment in getfacl output mean?
The #effective: comment is shown by getfacl after an ACL entry when the permissions that entry actually grants are less than what is written in the entry, due to masking by ACL_MASK. For example, user:paulh:r-x #effective:--x means the ACL_USER entry for paulh says r-x, but after ANDing with the ACL_MASK (--x), paulh effectively only gets execute permission.
Mask Q16. When is the ACL_MASK entry mandatory?
ACL_MASK is mandatory whenever the ACL contains any ACL_USER or ACL_GROUP entries. If the ACL has only ACL_USER_OBJ, ACL_GROUP_OBJ, and ACL_OTHER (a minimal ACL), then ACL_MASK is optional. The setfacl command and acl_calc_mask() both create the ACL_MASK entry automatically when you add ACL_USER or ACL_GROUP entries.

Section 5: getfacl & setfacl Commands

Shell Q17. What does ls -l show to indicate a file has an extended ACL?
When a file has an extended ACL, ls -l appends a plus sign (+) after the traditional 9-character permission field. For example: -rwxr-x--x+. The + is the signal to use getfacl to see the full permissions.
Shell Q18. What is the difference between setfacl -m and setfacl –set?
setfacl -m modifies — it adds or updates only the specified entries while leaving all other existing entries intact. setfacl --set replaces the entire ACL with exactly the entries you provide; any entries not specified are removed. Use --set when you want full control over the resulting ACL and don’t want old entries to linger.
Shell Q19. How do you back up and restore ACLs for an entire directory tree?
# Backup ACLs of entire /data tree
getfacl -R /data > acl_backup.txt

# Restore ACLs from backup
setfacl --restore=acl_backup.txt

This preserves all ACL entries including named users, named groups, and default ACLs. It is especially useful before operations like tar or rsync that may not preserve ACLs.

Shell Q20. What does setfacl -n do and why would you use it?
setfacl -n (or --no-mask) prevents setfacl from automatically recalculating and updating the ACL_MASK entry after a modification. Normally, after any -m or -x operation, setfacl adjusts the mask to be the union of all group class entries. If you want precise, manual control over the mask value and don’t want it automatically adjusted, use -n.

Section 6: Default ACLs & File Creation

Default ACL Q21. What is a default ACL, and on what type of filesystem object can it be set?
A default ACL is a special ACL that can only be set on directories. It serves as a permission template: when any new file or subdirectory is created inside that directory, the new object automatically inherits the default ACL as its access ACL. The default ACL itself plays no role in access checks on the directory.
Default ACL Q22. How does a new file inherit permissions from a parent directory’s default ACL?
The new file’s access ACL is set to the default ACL of the parent. However, three entries in the inherited ACL are ANDed against the corresponding bits of the mode argument passed to open(): ACL_USER_OBJ (ANDed with owner bits), ACL_MASK or ACL_GROUP_OBJ if no mask (ANDed with group bits), and ACL_OTHER (ANDed with other bits). All other entries (named ACL_USER, ACL_GROUP) are carried over unchanged. The process umask is completely ignored.
Default ACL Q23. How does a default ACL propagate through a directory tree?
When a new subdirectory is created inside a directory that has a default ACL, the subdirectory gets the parent’s default ACL as both its access ACL and its own default ACL. This means the default ACL automatically propagates to all newly created subdirectories at any depth, ensuring consistent permissions throughout the tree without manual intervention.
Default ACL Q24. If a directory has NO default ACL, what ACL does a new file created in it get?
It gets a minimal ACL derived from the traditional Unix rules: the file’s permission bits are set to the mode argument of open() after clearing bits turned off by the process umask. The resulting minimal ACL has only ACL_USER_OBJ, ACL_GROUP_OBJ, and ACL_OTHER entries.
Default ACL Q25. What extended attribute stores the default ACL?
system.posix_acl_default. The access ACL is stored in system.posix_acl_access. You can inspect these with getfattr -d <directory>.

Section 7: ACL C API

C API Q26. What is the correct way to iterate through all entries in an acl_t?
acl_entry_t entry;
int eid;
for (eid = ACL_FIRST_ENTRY; acl_get_entry(acl, eid, &entry) == 1;
     eid = ACL_NEXT_ENTRY) {
    /* process entry */
}

Use ACL_FIRST_ENTRY on the first call and ACL_NEXT_ENTRY on all subsequent calls. The function returns 1 for a valid entry, 0 when there are no more entries, and -1 on error.

C API Q27. How do you add a new ACL_USER entry for uid 1005 with read-write permissions to an existing ACL?
acl_entry_t entry;
acl_permset_t ps;
uid_t uid = 1005;

acl_create_entry(&acl, &entry);
acl_set_tag_type(entry, ACL_USER);
acl_set_qualifier(entry, &uid);
acl_get_permset(entry, &ps);
acl_clear_perms(ps);
acl_add_perm(ps, ACL_READ);
acl_add_perm(ps, ACL_WRITE);
acl_set_permset(entry, ps);
acl_calc_mask(&acl);   /* Update/create ACL_MASK */
C API Q28. Why must acl_calc_mask() be called after modifying ACL entries?
acl_calc_mask() recalculates the ACL_MASK entry as the union of all permissions in ACL_USER, ACL_GROUP, and ACL_GROUP_OBJ entries. If you add or modify any of these entries and don’t call acl_calc_mask(), the mask may be stale and no longer reflect the actual group class permissions. It also creates the ACL_MASK entry if one doesn’t exist, which is mandatory for ACLs with ACL_USER or ACL_GROUP entries.
C API Q29. List all ACL library allocations that require acl_free().

All of the following return heap-allocated objects that must be freed with acl_free():

  • acl_get_file() → acl_t
  • acl_from_text() → acl_t
  • acl_init() → acl_t
  • acl_dup() → acl_t
  • acl_to_text() → char*
  • acl_get_qualifier() → void* (uid_t* or gid_t*)

Using standard free() on these is incorrect; always use acl_free().

C API Q30. What is the return value of acl_get_entry() and what does each value mean?
acl_get_entry() returns: 1 when it successfully retrieves an ACL entry; 0 when there are no more entries in the ACL (end of list); -1 on error (check errno). This is different from most other ACL functions which return 0 on success and -1 on failure.
C API Q31. What is acl_valid() and what conditions make an ACL valid?
acl_valid(acl) returns 0 if the ACL is structurally valid. An ACL is valid when: ACL_USER_OBJ, ACL_GROUP_OBJ, and ACL_OTHER each appear exactly once; an ACL_MASK entry is present if any ACL_USER or ACL_GROUP entries exist; there is at most one ACL_MASK entry; no two ACL_USER entries share the same UID; and no two ACL_GROUP entries share the same GID.
C API Q32. What is the purpose of acl_dup() and when would you use it?
acl_dup(acl) creates a deep copy of an in-memory ACL and returns a handle to the new copy. You use it when you want to modify an ACL without affecting the original — for example, when you want to experiment with a modified version of an ACL before deciding whether to apply it to a file, or when you want to keep the original ACL for comparison.

Section 8: Implementation Limits

Limits Q33. What are the ACL entry limits for major Linux file systems?
  • ext2/ext3/ext4: ~500 entries (block-size limited; ~500 for 4 kB blocks). Kernels before 2.6.11 had a hard limit of 32.
  • XFS: 25 entries (hard internal limit).
  • Reiserfs/JFS: 8191 entries (limited by the 64 kB VFS xattr value size).
  • Btrfs: ~500 entries (same block-based constraint as ext4 at time of writing).
Limits Q34. Why is it bad practice to have very large ACLs even if the file system allows it?
Two main reasons: first, the permission-checking algorithm scans ACL entries sequentially, so performance degrades linearly with the number of entries — every file access takes longer. Second, large ACLs become extremely difficult to manage: it is easy to make mistakes, hard to audit, and time-consuming to maintain. The recommended approach is to use Unix groups — put users in appropriate groups in /etc/group and reference those groups in the ACL instead of listing individual users.

Section 9: Tricky / Scenario Questions

Tricky Q35. A file has ACL: u::rwx, u:alice:r-x, g::r–, m::r–, o::—. Alice tries to write to the file. Is she allowed?
No. Alice matches the ACL_USER entry for alice, which grants r-x. But this entry is subject to ACL_MASK. The mask is r– (read only). After ANDing: r-x AND r– = r–. Alice effectively only gets read permission. Write is denied. The #effective: r-- comment in getfacl output would indicate this.
Tricky Q36. What happens when you run chmod 700 on a file that has an extended ACL?
Because the file has an extended ACL (with ACL_MASK), chmod 700: sets ACL_USER_OBJ to rwx (owner gets full access), sets ACL_MASK to — (the group bits of 700 are 0), and sets ACL_OTHER to — (other bits of 700 are 0). The ACL_GROUP_OBJ, ACL_USER, and ACL_GROUP entries are not deleted but their effective permissions become — because ACL_MASK is now —. This is the intended behaviour — ACL entries are preserved but masked to zero, and can be unmasked again by a later chmod that sets group bits.
Tricky Q37. You write a C program that calls acl_get_entry() in a loop using ACL_NEXT_ENTRY. How does the kernel know which entry was “last retrieved”?
The ACL library maintains internal state within the acl_t object tracking a “current position” cursor. Each successful call to acl_get_entry(acl, ACL_NEXT_ENTRY, &entry) advances this cursor and returns the next entry. This means the iteration state is bound to the specific acl_t handle — if you start iterating a second time, you must restart with ACL_FIRST_ENTRY.
Tricky Q38. A directory has a default ACL. You create a file inside it with open(path, O_CREAT, 0000). What permissions does the file get?
Even with mode 0000, the default ACL is inherited and then ANDed against the mode. The ACL_USER_OBJ is ANDed with owner bits of 0000 = 000, so owner gets no permissions. ACL_MASK is ANDed with group bits of 0000 = 000, so group class gets no permissions. ACL_OTHER ANDed with 0000 = 000. The file gets zero permissions for everyone, but the full default ACL structure (including named users and groups) is still inherited — those entries just all end up with — permissions after the AND with 0000.
Tricky Q39. Can you use getxattr() and setxattr() directly to manipulate ACLs instead of the ACL API? Is it recommended?
Yes, it is technically possible because ACLs are stored as extended attributes (system.posix_acl_access and system.posix_acl_default), and you can read and write them with getxattr() and setxattr(). However, it is not recommended because the on-disk encoding of ACL entries is a binary format specific to the Linux ACL implementation. The ACL library API handles all encoding/decoding transparently, correctly, and portably. Direct xattr manipulation would require you to understand and manage the binary layout yourself, which is error-prone and non-portable.
Tricky Q40. Write a shell one-liner to give user bob read access to all .c files in the current directory.
setfacl -m u:bob:r-- *.c

Or recursively for a directory tree:

find . -name "*.c" -exec setfacl -m u:bob:r-- {} \;
Tricky Q41. How is acl_get_perm() different from the standard ACL permission functions and why is it needed?
acl_get_perm(permset, perm) is a Linux extension to the POSIX.1e draft standard (not in the portable API). It returns 1 if the specified permission (ACL_READ, ACL_WRITE, or ACL_EXECUTE) is set in the permission set, 0 if not, or -1 on error. The standard POSIX.1e draft does not include a function to query individual permission bits from a permset — you would have to inspect the permset structure directly in a non-portable way. acl_get_perm() fills this gap cleanly. Requires #include <acl/libacl.h>.

Quick Reference — Common Commands

# View ACL of a file
getfacl filename

# View without header comments
getfacl --omit-header filename

# View default ACL of a directory
getfacl -d directory/

# Add/modify entries (leaves others intact)
setfacl -m u:alice:rw,g:devteam:r filename

# Set entire ACL (replaces all existing entries)
setfacl --set u::rwx,u:alice:r--,g::r--,m::rw-,o::--- filename

# Remove a specific entry
setfacl -x u:alice filename

# Remove ALL extended entries (back to minimal)
setfacl -b filename

# Remove default ACL from a directory
setfacl -k directory/

# Set a default ACL on a directory
setfacl -d -m u::rwx,g::rwx,o::rx directory/

# Recursively apply ACL
setfacl -R -m u:bob:r-- directory/

# Backup ACLs
getfacl -R . > acls.bak

# Restore ACLs
setfacl --restore=acls.bak

Linux ACL Series — Complete!

You have covered the full Linux ACL chapter: overview, algorithm, text forms, mask, shell commands, default ACLs, C API, and interview prep. Share EmbeddedPathashala with fellow embedded & Linux learners.

← Start from Part 1 ← Part 7: C API

Leave a Reply

Your email address will not be published. Required fields are marked *