Lesson 004 · Linux Administration Learning Path

Linux Files, Directories, Links, Permissions and ACLs

· Published · 9 min read

Labelled RHEL Linux administration learning path highlighting paths inodes hard links symbolic links ownership permissions ACLs and verification

A pathname is not the file itself. Directories map names to inode-backed objects, hard links add another name for the same inode, and symbolic links store a path to resolve later. Permissions are also evaluated along the path, not only on the final file. Administrators who skip those distinctions often delete the wrong name, expose a directory through an ACL mask, or apply a recursive change across a mount or symbolic link boundary they did not intend to cross.

Model names, objects and path traversal separately

A regular file has an inode containing metadata and references to data. Directory entries associate names with inode numbers. Removing one hard link removes one name; storage is reclaimed only when the link count and open references permit it. A symbolic link has its own inode and stores a path, which may become dangling or resolve differently inside a chroot, container or changed mount layout.

For a directory, read permits listing names, execute permits traversal and write permits changing entries, subject to sticky-bit and policy controls. Effective access can also involve POSIX ACL entries, their mask, SELinux labels, mount options and application privilege. Diagnose each layer rather than changing mode to 777.

Build the working model

LayerQuestion to answerEvidence
PathWhich names and directories are traversed?namei -om and resolved path
ObjectWhich inode and filesystem own the data?stat, device/inode and link count
Discretionary accessWhich owner, group, mode and ACL apply?getfacl including effective mask
Mandatory accessWhich SELinux context and policy decision apply?ls -Z and AVC evidence
Mount boundaryWhich filesystem and options contain the object?findmnt -T and mount options

Implementation sequence

  1. Resolve without modifying. Use namei, readlink, stat and findmnt to understand the path.
  2. Identify the access subject. Record the real/effective account, supplementary groups and service confinement.
  3. Read modes and ACLs together. An ACL mask can reduce named-user or group permissions even when entries appear broader.
  4. Separate ownership from collaboration. Prefer a defined group, setgid directory and default ACL over repeated broad mode changes.
  5. Bound recursion. Inventory the exact tree, mounts, link behavior and object count before any recursive operation.
  6. Verify as the intended account. Root success does not prove an application or user can traverse and use the path.

Commands and expected evidence

mkdir -p /tmp/nitwings-links/source
printf '%s\n' sample > /tmp/nitwings-links/source/data.txt
ln /tmp/nitwings-links/source/data.txt /tmp/nitwings-links/hard-name
ln -s source/data.txt /tmp/nitwings-links/symbolic-name
stat -c '%d:%i links=%h mode=%A owner=%U:%G name=%n' /tmp/nitwings-links/source/data.txt /tmp/nitwings-links/hard-name /tmp/nitwings-links/symbolic-name
readlink /tmp/nitwings-links/symbolic-name
readlink -f /tmp/nitwings-links/symbolic-name
namei -om /tmp/nitwings-links/source/data.txt
findmnt -T /tmp/nitwings-links/source/data.txt
getfacl -p /tmp/nitwings-links/source/data.txt
ls -lZ /tmp/nitwings-links/source/data.txt
  • Matching device and inode numbers prove the two hard-link names refer to the same inode on that filesystem. The symbolic link has its own inode.
  • readlink -f follows the current path to a resolved destination. Do not use the result as authorization if an attacker can change path components concurrently.
  • namei -om shows each directory component and makes a missing execute permission visible.
  • ACL and SELinux evidence complement mode bits. Changing only one layer may hide rather than solve the access decision.

Evidence and acceptance criteria

EvidenceHealthy resultFailure meaning
Object identityExpected device, inode, type and link countWrong object, bind mount or link assumption
Path traversalEvery required directory permits the intended traversalFinal-file mode is irrelevant until the path can be reached
ACL resultNamed entries and mask produce intended effective accessDisplayed ACL entry may be limited by the mask
SELinux contextType matches the service and approved path purposePolicy denial or incorrectly labelled content
Recursive scopeReviewed object list excludes other mounts and unintended linksChange can escape the approved tree or alter unrelated data

Worked scenario: the file is readable but the service gets permission denied

An application file shows group-readable mode, and an administrator repeatedly widens it. The service still fails because its account cannot traverse a parent directory. After execute permission is corrected through the intended service group, SELinux then records that the custom path has a type not permitted to the service.

The team restores ordinary discretionary permissions, assigns the documented SELinux file-context rule for that application path, applies it with restorecon, and retests as the service account. The fix addresses both decisions without making the file world-writable or disabling enforcement.

Practical how-to cases

Case 1: Compare hard and symbolic links

Prove which names share an inode and what happens when the original name is removed.

d=$(mktemp -d)
printf data >"$d/original"
ln "$d/original" "$d/hard"
ln -s original "$d/symbolic"
stat -c '%i %h %F %n' "$d/original" "$d/hard" "$d/symbolic"
rm -- "$d/original"
cat "$d/hard"
readlink "$d/symbolic"
CheckpointWhat to establish
Expected resultThe hard link retains the file and inode; the symbolic link retains path text but becomes dangling.
If it failsA hard-link failure across filesystems is expected because inode identity is filesystem-local.
Safe recoveryRecreate the intended name from the verified hard link or correct the symbolic target; never guess the desired content.

Case 2: Build shared group access

Create a collaboration directory whose new files inherit the project group.

sudo groupadd -f webops
sudo install -d -o root -g webops -m 2770 /srv/webops
sudo -u student touch /srv/webops/test 2>/dev/null || true
namei -om /srv/webops/test
stat -c '%A %U:%G %n' /srv/webops /srv/webops/test
CheckpointWhat to establish
Expected resultAuthorized members can traverse and create; the directory setgid bit makes new entries inherit webops.
If it failsPermission denied can come from membership, parent traversal, ACL mask, SELinux or read-only mount state.
Safe recoveryRemove the test file and restore the recorded owner/mode on the exact directory. Do not run recursive chmod on /srv.

Case 3: Grant and verify an ACL

Give one named user read access without changing the file owning group.

sudo setfacl -m u:student:r-- /srv/webops/report.txt
getfacl -p /srv/webops/report.txt
sudo -u student head -n 1 /srv/webops/report.txt
namei -om /srv/webops/report.txt
CheckpointWhat to establish
Expected resultThe access ACL names student and the effective mask permits read; every parent permits traversal.
If it failsAn ACL entry can exist but be limited by its mask, or a parent can block traversal.
Safe recoveryRemove only the added entry with setfacl -x u:student and verify the resulting ACL.

Case 4: Repair default ownership without following surprises

Preview a bounded tree before applying a recursive ownership correction.

sudo find /srv/webops -xdev -printf '%u:%g %m %p\n' | head -50
sudo find /srv/webops -xdev -type f ! -group webops -print
# After review only:
sudo find /srv/webops -xdev -type f ! -group webops -exec chgrp webops -- {} +
CheckpointWhat to establish
Expected resultOnly files on the intended filesystem and outside the expected group appear in the preview; the reviewed set is corrected.
If it failsA large or unexpected result means the boundary or assumption is wrong.
Safe recoveryStop before mutation, refine the predicate, and restore ownership from the captured manifest if a reviewed change is incorrect.

Independent practice tasks

  1. Create a team directory with setgid and a default ACL, then prove inheritance using two lab users.
  2. Show how umask 0022 and 0027 change newly created file and directory modes.
  3. Find files writable by others inside a bounded lab filesystem without crossing mounts.
  4. Recover access to a file blocked separately by parent traversal, ACL mask and SELinux label.

For this lesson on Linux Files, Links, Permissions and ACLs, complete each task without copying the worked command sequence. Record the initial state, exact change, verification, negative test and recovery command. A task is unfinished if it works now but does not survive a reboot where persistence is required.

Troubleshooting by symptom

SymptomInspect firstDefensible next action
Permission denied despite readable final fileParent traversal, ACL mask, SELinux and mount optionsCorrect the exact denying layer and retest as the subject
Deleting source appears not to free spaceHard-link count and processes holding an unlinked fileFind remaining names/open descriptors; do not delete unrelated data
Symbolic link works on one host onlyRelative target, mount layout, chroot/container rootUse a stable intended path and verify inside the real execution context
Recursive ownership takes too long or crosses dataMount boundaries, object count and link traversalStop safely, compare evidence and use a bounded find -xdev plan

Unsafe operations and recovery boundaries

  • Unsafe: chmod -R 777 grants broad write access and does not fix SELinux, path or identity design. Use the narrow owner/group/ACL required.
  • Unsafe: recursive chown on an unresolved application or filesystem root can break packages, services and security boundaries. Inventory exact targets first.
  • Unsafe: following mutable symbolic links during privileged automation can redirect a change. Work from verified file descriptors or controlled trees where possible.

Rewritten knowledge checks

What does a directory entry contain?
A name associated with an inode number in that filesystem.
Why can a hard link not normally cross filesystems?
The directory entry refers to an inode number meaningful within the same filesystem.
What happens when one hard-link name is removed?
That directory entry and the inode link count are reduced; other hard links still reference the data.
Why can a symbolic link become dangling?
It stores a path, and the destination named by that path can be absent or moved.
What does execute permission mean on a directory?
It permits traversal and lookup of entries, subject to other access controls.
What does an ACL mask control?
It limits effective permissions of named users, named groups and the owning group class.
Why test access as the service account?
Root or an administrator may bypass or differ from the identity and confinement used by the application.
What must precede recursive permission change?
Exact scope, mount/link behavior, owner intent, object inventory, backup or recovery and an acceptance test.

Guided lab and acceptance test

  1. Create the hard and symbolic links shown in the command block and compare inode, type and link count.
  2. Remove the source filename and prove which names still access the data. Recreate the lab before continuing.
  3. Create a group collaboration directory with setgid behavior and a default ACL for one lab user.
  4. Use namei and getfacl to predict access before testing as that user.
  5. Remove parent-directory traversal in the lab, observe the exact failure, then restore only the required permission.
  6. Document why mode bits, ACLs, SELinux and mount options are separate evidence layers.

Primary references

Advertisement