Chapter 06Lesson 05~70 minutes

Access Control Lists and Permission Troubleshooting

Owner/group/other modes intentionally provide a compact policy. Real systems sometimes need named-user or named-group access without changing the owning group. POSIX ACLs add those entries and an ACL mask. They also add a common troubleshooting trap: displayed mode bits can summarize the ACL mask rather than a single group entry. This lesson combines ACL mechanics with a disciplined permission-debugging workflow.

IntermediatePOSIX ACLsTroubleshooting

Learning objectives

By the end of this lesson

  • Recognize minimal and extended ACLs in ls and getfacl output.
  • Create, modify, remove, and copy access ACL entries.
  • Explain how the ACL mask limits named users, named groups, and the owning group.
  • Use default directory ACLs to establish inherited access.
  • Troubleshoot permission failures across identity, path traversal, modes, ACLs, mount state, and later security layers.

1. ACLs extend the group-class decision

An extended access ACL can contain named-user and named-group entries in addition to the file owner, owning group, and other entries. The ACL mask limits the effective permissions of named users, named groups, and the owning-group entry. The file owner entry and other entry are not limited by that mask.

Simplified POSIX ACL evaluation
flowchart TB
  P["Process effective UID and groups"] --> O{"Matches file owner?"}
  O -->|yes| UE["Use owner entry"]
  O -->|no| NU{"Named user entry?"}
  NU -->|yes| UM["Named-user entry AND mask"]
  NU -->|no| GM{"Any matching group entries?"}
  GM -->|yes| AG["Union matching groups AND mask"]
  GM -->|no| OT["Use other entry"]
  UE --> R{"Requested access allowed?"}
  UM --> R
  AG --> R
  OT --> R
lab="$HOME/devops-academy/linux/chapter06/lesson05"
mkdir -p -- "$lab"
printf 'deployment=approved
' > "$lab/release.txt"

ls -l -- "$lab/release.txt"
getfacl -p -- "$lab/release.txt"

A plus sign after the mode string in many ls -l implementations indicates additional ACL information. Use getfacl for the authoritative entry set and effective-permission comments.

2. setfacl changes named entries and the mask

The common modify form is setfacl -m SPEC FILE. Entries include u:NAME:PERMS, g:NAME:PERMS, and m::PERMS for the mask. -x removes selected entries and -b removes all extended entries.

file="$HOME/devops-academy/linux/chapter06/lesson05/release.txt"

# Add a named-user entry for an account commonly present on Linux systems.
if getent passwd nobody >/dev/null; then
  setfacl -m u:nobody:r-- -- "$file"
fi

# Add a named group entry only when a supplementary group is available.
primary_group=$(id -gn)
acl_group=$(id -nG | tr ' ' '\n' | awk -v primary="$primary_group" '$0 != primary { print; exit }')
if [ -n "$acl_group" ]; then
  setfacl -m "g:$acl_group:r--" -- "$file"
fi

# Inspect entries and effective permissions.
getfacl -p -- "$file"

# Remove the named nobody entry if it was added.
if getent passwd nobody >/dev/null; then
  setfacl -x u:nobody -- "$file"
fi

By default, setfacl may recalculate the mask to include permissions required by modified entries. Use explicit mask management only when the policy is understood; an unexpectedly narrow mask is a frequent source of “the ACL says rw but access is read-only” incidents.

3. The mask defines effective group-class access

Consider a named entry user:deploy:rw- with mask r--. The stored entry requests read/write, but its effective permission is read-only because write is removed by the mask. getfacl normally prints an #effective: annotation when the mask reduces an entry.

file="$HOME/devops-academy/linux/chapter06/lesson05/mask-demo.txt"
printf 'mask demo
' > "$file"

if getent passwd nobody >/dev/null; then
  setfacl -m u:nobody:rw- -- "$file"
  setfacl -m m::r-- -- "$file"
  getfacl -p -- "$file"
  # Restore a mask that allows the named write permission.
  setfacl -m m::rw- -- "$file"
fi
chmod and ACLs interact

On a file with an extended ACL, changing the traditional group mode bits generally changes the ACL mask. A later chmod g-w can therefore reduce effective permissions for several named entries, not only the owning group.

4. Default ACLs define inherited entries for new children

A directory can carry a default ACL. When a child is created, that default is used to derive the child’s access ACL, constrained by the creating program’s requested mode. Default ACLs are not retroactive and do not automatically repair existing content.

shared="$HOME/devops-academy/linux/chapter06/lesson05/shared"
rm -rf -- "$shared"
mkdir -p -- "$shared"
chmod 2770 -- "$shared"

# Give the owning group inherited read/write on files and traversal on dirs.
setfacl -m d:u::rwx,d:g::rwx,d:o::---,d:m::rwx -- "$shared"

printf 'new artifact
' > "$shared/artifact.txt"
mkdir -- "$shared/release-dir"

getfacl -p -- "$shared"
getfacl -p -- "$shared/artifact.txt"
getfacl -p -- "$shared/release-dir"

For a named team group, add both an access entry on the directory and a default named-group entry, then ensure the default mask permits the intended rights. Always create a test child and inspect it.

5. Troubleshoot permissions from the process outward

01Capture the exact error and operation

Reading, opening for write, creating, renaming, deleting, and executing require different checks.

02Reproduce as the real identity

Record effective UID, groups, service configuration, container user, and credential transitions.

03Trace every path component

Use namei -l; inspect parent-directory execute and write semantics.

04Inspect mode, ownership, and ACL

Use stat and getfacl; read effective mask annotations.

05Check filesystem state

Read-only mounts, unsupported ACLs, NFS identity, immutable attributes, quotas, or full filesystems can resemble permission failures.

06Check additional security layers

SELinux, AppArmor, systemd sandboxing, container confinement, and capabilities are covered later; ordinary mode repair will not override them.

target="$HOME/devops-academy/linux/chapter06/lesson05/shared/artifact.txt"

id
namei -l -- "$target"
stat -c 'mode=%A octal=%a owner=%U:%G ids=%u:%g type=%F name=%n' -- "$target"
getfacl -p -- "$target"
findmnt -T "$target" -o TARGET,SOURCE,FSTYPE,OPTIONS
lsattr -- "$target" 2>/dev/null || true
df -h -- "$target"
df -i -- "$target"
Preserve evidence before repair

Capture identity, metadata, ACLs, mount options, and the failing command. A broad repair may restore service while destroying the evidence needed to understand why it failed.

6. Hands-on lab: create and diagnose an ACL policy

The getfacl and setfacl tools are commonly provided by an acl package. The lab exits with a clear message if they are unavailable.

set -eu
command -v getfacl >/dev/null || { printf 'Install the acl tools first.
' >&2; exit 1; }
command -v setfacl >/dev/null || { printf 'Install the acl tools first.
' >&2; exit 1; }

lab="$HOME/devops-academy/linux/chapter06/lesson05"
root="$lab/acl-lab"
rm -rf -- "$root"
mkdir -p -- "$root/shared"
printf 'build=42
' > "$root/shared/manifest.txt"
chmod 750 -- "$root/shared"
chmod 640 -- "$root/shared/manifest.txt"

# Add and then deliberately mask a named entry when nobody exists.
if getent passwd nobody >/dev/null; then
  setfacl -m u:nobody:rw-,m::r-- -- "$root/shared/manifest.txt"
fi

{
  printf '=== identity ===
'
  id
  printf '
=== path ===
'
  namei -l -- "$root/shared/manifest.txt"
  printf '
=== stat ===
'
  stat -c '%A %a %U:%G %n' -- "$root/shared/manifest.txt"
  printf '
=== acl before repair ===
'
  getfacl -p -- "$root/shared/manifest.txt"
} > "$lab/acl-diagnosis.txt"

# Repair the ACL mask if the named entry exists.
if getent passwd nobody >/dev/null; then
  setfacl -m m::rw- -- "$root/shared/manifest.txt"
fi

printf '
=== acl after repair ===
' >> "$lab/acl-diagnosis.txt"
getfacl -p -- "$root/shared/manifest.txt" >> "$lab/acl-diagnosis.txt"
cat -- "$lab/acl-diagnosis.txt"

Verification checklist

7. Common ACL and troubleshooting mistakes

Reading only ls -l

Extended ACL entries and effective mask reductions require getfacl.

Ignoring parent traversal

A correct file ACL cannot compensate for a blocked parent directory.

Running chmod after ACL design without review

Group-mode changes can modify the ACL mask and reduce several entries.

Changing permissions before reproducing identity

The incident may belong to a service user, container UID, or sandbox rather than your interactive shell.

8. Knowledge check

Question 1. Which ACL entries are limited by the ACL mask?

Question 2. Why can an ACL entry display rw- but have only read access effectively?

Question 3. What should be inspected before changing a file that reports permission denied?

9. Summary

POSIX ACLs add named identities and default inheritance to the traditional permission model, while the ACL mask defines effective group-class access. Permission troubleshooting must proceed from the real process identity through path traversal, modes, ownership, ACLs, filesystem state, and additional security controls. Preserve evidence, make the smallest repair, and verify the exact operation.

Next chapter

Local Users, Groups, and Identity Files

Chapter 7 begins with the identity records, numeric credentials, group memberships, and name-service lookups that Linux uses to authorize users and processes.

10. Further reading

  • Linux man-pages and ACL manuals: acl(5), getfacl(1), and setfacl(1).
  • POSIX access-control list model and Linux filesystem ACL documentation.
  • Linux man-pages: path_resolution(7), stat(2), and mount(8).
  • Filesystem manuals for extended attributes, mount options, and ACL support.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.