LFCS Part 35: Access Control Lists (ACLs) and File Attributes

Master advanced Linux permissions with ACLs (getfacl, setfacl) and file attributes (chattr, lsattr). Learn how to grant granular permissions beyond owner/group/other and protect files with immutable and append-only attributes.

28 min read

In our previous post, we mastered basic Linux file permissions with chmod, chown, and special permissions like setuid, setgid, and the sticky bit. While traditional Unix permissions are powerful, they have a fundamental limitation: you can only assign permissions to one owner, one group, and everyone else.

But what if you need to give specific permissions to multiple different users or groups? What if you want to make a file completely immutable, even for root? This is where Access Control Lists (ACLs) and file attributes come in.

What You'll Learn

In this comprehensive guide, you'll master:

  • Understanding ACL fundamentals and when to use them
  • Traditional permission limitations and why ACLs solve them
  • Viewing ACLs with getfacl
  • Setting ACLs with setfacl for users and groups
  • ACL masks and effective permissions
  • Default ACLs for directories
  • File attributes with chattr and lsattr
  • Immutable files that can't be modified or deleted
  • Append-only files for secure logging
  • Real-world security scenarios and best practices

Part 1: Understanding Access Control Lists (ACLs)

What Are ACLs?

Access Control Lists (ACLs) provide fine-grained access control beyond the traditional owner/group/other permission model. They allow you to:

  • Grant permissions to multiple specific users
  • Grant permissions to multiple specific groups
  • Set default permissions for new files in a directory
  • Create complex permission schemes without creating numerous groups

The Limitation of Traditional Permissions

Let's understand the problem ACLs solve with a real-world scenario:

# You have a file owned by alice
ls -l project_data.txt
-rw-r--r-- 1 alice developers 1024 Dec 10 10:00 project_data.txt

The Scenario:

  • Alice (owner) needs read/write access
  • Bob and Charlie (not in developers group) need read/write access
  • The developers group needs read-only access
  • Everyone else should have no access

The Problem: With traditional permissions, you cannot achieve this! You can only set permissions for:

  1. One owner (alice)
  2. One group (developers)
  3. Everyone else (other)

You'd have to:

  • Create a new group containing alice, bob, and charlie
  • Change the file's group ownership
  • Manage this group separately

The Solution: ACLs let you grant specific permissions to bob and charlie directly, without changing ownership or creating new groups!

Do You Have ACL Support?

Most modern Linux filesystems support ACLs by default:

# Check if your filesystem supports ACLs
tune2fs -l /dev/sda1 | grep "Default mount options"
# Look for: acl

# Or check current mount options
mount | grep "acl"

Common filesystems with ACL support:

  • ext4 (default in most distributions)
  • ext3
  • XFS
  • Btrfs

If ACLs aren't enabled, you can mount with ACL support:

sudo mount -o remount,acl /

Part 2: Working with ACLs

The getfacl Command - Viewing ACLs

The getfacl command displays the Access Control List of a file or directory.

Basic syntax:

getfacl [OPTIONS] FILE

Example 1: Viewing a file without ACLs

# Create a test file
touch regular_file.txt
ls -l regular_file.txt
-rw-r--r-- 1 owais owais 0 Dec 10 10:00 regular_file.txt

# View its ACL
getfacl regular_file.txt

Output:

# file: regular_file.txt
# owner: owais
# group: owais
user::rw-
group::r--
other::r--

Understanding the output:

  • # file: - The filename
  • # owner: - File owner
  • # group: - File group
  • user::rw- - Owner has read/write
  • group::r-- - Group has read-only
  • other::r-- - Others have read-only

This is just the standard Unix permissions shown in ACL format!

The setfacl Command - Setting ACLs

The setfacl command modifies the Access Control List of files and directories.

Basic syntax:

setfacl [OPTIONS] ACL_SPECIFICATION FILE

Common options:

  • -m - Modify ACL (add or change entries)
  • -x - Remove specific ACL entries
  • -b - Remove all extended ACL entries
  • -d - Set default ACLs (for directories)
  • -R - Recursive (apply to directory and contents)
  • -M - Read ACL entries from a file

Granting Permissions to Specific Users

Example 2: Grant read/write to a specific user

# Create a file
echo "Project data" > data.txt
ls -l data.txt
-rw-r--r-- 1 alice alice 13 Dec 10 10:05 data.txt

# Grant read/write to user bob
setfacl -m u:bob:rw data.txt

# View the ACL
getfacl data.txt

Output:

# file: data.txt
# owner: alice
# group: alice
user::rw-
user:bob:rw-          ← Bob has read/write!
group::r--
mask::rw-
other::r--

Notice:

  • user:bob:rw- - Bob now has read/write access
  • mask::rw- - A mask entry appeared (explained later)
  • The traditional ls -l output shows a + sign:
ls -l data.txt
-rw-rw-r--+ 1 alice alice 13 Dec 10 10:05 data.txt
            ↑
            + indicates extended ACLs

The ACL syntax:

setfacl -m u:USERNAME:PERMISSIONS FILE
           ↑  ↑        ↑
           │  │        └─ rwx permissions
           │  └────────── username
           └─────────────── u for user

Example 3: Grant permissions to multiple users

# Grant different permissions to multiple users
setfacl -m u:bob:rw,u:charlie:r data.txt

# View the result
getfacl data.txt

Output:

# file: data.txt
# owner: alice
# group: alice
user::rw-
user:bob:rw-         ← Bob has read/write
user:charlie:r--     ← Charlie has read-only
group::r--
mask::rw-
other::r--

Granting Permissions to Specific Groups

Example 4: Grant permissions to a specific group

# Grant read/write to the developers group
setfacl -m g:developers:rw data.txt

# View the ACL
getfacl data.txt

Output:

# file: data.txt
# owner: alice
# group: alice
user::rw-
user:bob:rw-
group::r--
group:developers:rw-  ← developers group has read/write
mask::rw-
other::r--

The ACL syntax for groups:

setfacl -m g:GROUPNAME:PERMISSIONS FILE
           ↑  ↑         ↑
           │  │         └─ rwx permissions
           │  └─────────── group name
           └───────────── g for group

Understanding the ACL Mask

The mask defines the maximum effective permissions for all ACL entries (except owner and other).

Think of the mask as a permission filter:

  • Even if you grant rwx to a user, the mask limits the actual permissions
  • The mask applies to: named users, named groups, and the owning group

Example 5: How the mask works

# Grant full permissions to bob
setfacl -m u:bob:rwx data.txt

# Set a restrictive mask
setfacl -m m::r data.txt

# View the effective permissions
getfacl data.txt

Output:

# file: data.txt
# owner: alice
# group: alice
user::rw-
user:bob:rwx                  #effective:r--
                              ↑
                              The mask limits bob to read-only!
group::r--
mask::r--                     ← Mask only allows read
other::r--

Key points:

  • Bob's ACL entry says rwx
  • But the mask is r--
  • So bob's effective permissions are only r--
  • The #effective: comment shows the actual permissions after applying the mask

When is the mask set? The mask is automatically calculated when you add ACL entries. It's set to the union of all permissions granted.

Removing ACL Entries

Example 6: Remove a specific user's ACL

# Remove bob's ACL entry
setfacl -x u:bob data.txt

# View the result
getfacl data.txt

Now bob's specific ACL entry is gone.

Example 7: Remove all ACLs

# Remove all extended ACL entries
setfacl -b data.txt

# View the result
getfacl data.txt

Output:

# file: data.txt
# owner: alice
# group: alice
user::rw-
group::r--
other::r--

Back to standard Unix permissions only! Notice the + is gone:

ls -l data.txt
-rw-r--r-- 1 alice alice 13 Dec 10 10:05 data.txt

Part 3: Default ACLs for Directories

Default ACLs are incredibly powerful for directories. They define what ACLs new files and subdirectories will inherit.

Setting Default ACLs

Example 8: Create a shared project directory

# Create a project directory
mkdir /tmp/project
cd /tmp/project

# Set default ACL: new files will give bob read/write
setfacl -m d:u:bob:rw /tmp/project

# View the ACL
getfacl /tmp/project

Output:

# file: /tmp/project
# owner: alice
# group: alice
user::rwx
group::r-x
other::r-x
default:user::rwx
default:user:bob:rw-     ← Default ACL for bob
default:group::r-x
default:mask::rwx
default:other::r-x

Now create a file:

# Create a new file in the directory
touch /tmp/project/newfile.txt

# Check its ACL
getfacl /tmp/project/newfile.txt

Output:

# file: /tmp/project/newfile.txt
# owner: alice
# group: alice
user::rw-
user:bob:rw-            ← Bob automatically has rw on the new file!
group::r-x              #effective:r--
mask::rw-
other::r--

Amazing! The file automatically inherited bob's read/write permissions!

Example 9: Multiple default ACLs

# Set default ACLs for multiple users and groups
setfacl -m d:u:bob:rw,d:u:charlie:r,d:g:developers:rw /tmp/project

# Create a file
touch /tmp/project/report.txt

# Check its ACL
getfacl /tmp/project/report.txt

Output:

# file: /tmp/project/report.txt
# owner: alice
# group: alice
user::rw-
user:bob:rw-              ← Inherited
user:charlie:r--          ← Inherited
group::r-x                #effective:r--
group:developers:rw-      ← Inherited
mask::rw-
other::r--

All the ACLs were inherited automatically!

Recursive ACL Changes

Example 10: Apply ACLs recursively

# Create directory structure
mkdir -p /tmp/project/{src,docs,tests}
touch /tmp/project/src/main.c
touch /tmp/project/docs/readme.txt

# Apply ACL recursively to all existing files
setfacl -R -m u:bob:rw /tmp/project

# Check a nested file
getfacl /tmp/project/src/main.c

The -R flag applies the ACL to the directory and all its contents.

Best practice:

# For existing files AND future files, do both:
setfacl -R -m u:bob:rw /tmp/project        # Existing files
setfacl -m d:u:bob:rw /tmp/project         # Future files (default ACL)

Part 4: File Attributes with chattr and lsattr

File attributes provide additional control over files at the filesystem level. These are separate from permissions and ACLs.

The lsattr Command - Viewing Attributes

The lsattr command lists file attributes.

Basic syntax:

lsattr [OPTIONS] [FILES]

Common options:

  • -a - Show hidden files
  • -d - List directories like files (don't list contents)
  • -R - Recursive

Example 11: View file attributes

# Create a test file
echo "Important data" > important.txt

# View its attributes
lsattr important.txt

Output:

--------------e------- important.txt
              ↑
              'e' means the file uses extents (ext4)

Common attribute flags:

  • - - No attribute set
  • i - Immutable (cannot be modified, deleted, or renamed)
  • a - Append-only (can only append data)
  • e - Extent format (ext4 default, informational)
  • A - No atime updates (performance optimization)
  • S - Synchronous updates (writes are immediate)
  • s - Secure deletion (zeros data on delete)
  • u - Undeletable (can be recovered after deletion)

The chattr Command - Changing Attributes

The chattr command changes file attributes.

Basic syntax:

chattr [OPTIONS] [MODE] FILE

Modes:

  • +ATTRIBUTE - Add an attribute
  • -ATTRIBUTE - Remove an attribute
  • =ATTRIBUTE - Set exact attributes

Common options:

  • -R - Recursive
  • -V - Verbose

The Immutable Attribute (+i)

The immutable attribute makes a file completely unchangeable - even root cannot modify or delete it!

Example 12: Make a file immutable

# Create a critical file
echo "DO NOT MODIFY" > critical.conf
cat critical.conf
DO NOT MODIFY

# Make it immutable
sudo chattr +i critical.conf

# Check the attribute
lsattr critical.conf
----i---------e------- critical.conf
    ↑
    'i' = immutable

Now try to modify it:

# Try to modify (will fail!)
echo "Trying to change" > critical.conf
bash: critical.conf: Operation not permitted

# Try to delete (will fail!)
rm -f critical.conf
rm: cannot remove 'critical.conf': Operation not permitted

# Even root cannot modify!
sudo rm -f critical.conf
rm: cannot remove 'critical.conf': Operation not permitted

# Can't even change permissions!
sudo chmod 777 critical.conf
chmod: changing permissions of 'critical.conf': Operation not permitted

Nothing works! The file is completely protected.

To modify the file, first remove the immutable attribute:

# Remove immutable attribute (requires root)
sudo chattr -i critical.conf

# Now you can modify it
echo "Modified" > critical.conf
cat critical.conf
Modified

Real-world use cases for immutable files:

  • Protecting critical system configuration files
  • Preventing accidental deletion of important data
  • Securing log files from tampering
  • Protecting files during system maintenance
  • Complying with audit requirements

The Append-Only Attribute (+a)

The append-only attribute allows appending data but prevents modification or deletion.

Example 13: Create an append-only log file

# Create a log file
echo "Log started" > application.log

# Make it append-only
sudo chattr +a application.log

# Check the attribute
lsattr application.log
-----a--------e------- application.log
     ↑
     'a' = append-only

Now test the behavior:

# Appending works!
echo "Log entry 1" >> application.log
echo "Log entry 2" >> application.log
cat application.log
Log started
Log entry 1
Log entry 2

# But overwriting fails
echo "Erase log" > application.log
bash: application.log: Operation not permitted

# And deletion fails
rm -f application.log
rm: cannot remove 'application.log': Operation not permitted

# Even with sudo!
sudo rm -f application.log
rm: cannot remove 'application.log': Operation not permitted

Perfect for logging! You can add log entries, but nobody (not even root) can delete or modify existing entries.

To remove the append-only attribute:

# Remove append-only attribute (requires root)
sudo chattr -a application.log

# Now you can modify or delete
rm application.log

Real-world use cases for append-only files:

  • Protecting log files from tampering
  • Audit trails that must remain accurate
  • Security logs that cannot be erased
  • Financial transaction logs
  • Compliance with regulations (HIPAA, SOX, PCI-DSS)

Combining Attributes

Example 14: Multiple attributes

# Create a file with multiple attributes
echo "Secure data" > secure.txt

# Set both immutable and synchronous writes
sudo chattr +iS secure.txt

# Check attributes
lsattr secure.txt
----i-------S-e------- secure.txt
    ↑       ↑
    │       └─ Synchronous
    └───────── Immutable

Recursive Attribute Changes

Example 15: Apply attributes recursively

# Create directory structure
mkdir -p /tmp/secure_logs
touch /tmp/secure_logs/app.log
touch /tmp/secure_logs/system.log

# Make all logs append-only
sudo chattr -R +a /tmp/secure_logs

# Verify
lsattr -d /tmp/secure_logs
-----a--------e------- /tmp/secure_logs

lsattr /tmp/secure_logs/*
-----a--------e------- /tmp/secure_logs/app.log
-----a--------e------- /tmp/secure_logs/system.log

Part 5: Real-World Scenarios

Scenario 1: Shared Project Directory

Requirement:

  • Alice owns the project directory
  • Bob and Charlie need full access to all files
  • The QA team needs read-only access
  • New files should automatically have these permissions

Solution:

# Create the project directory
sudo mkdir /opt/project
sudo chown alice:alice /opt/project

# Set ACLs for bob and charlie (read/write)
sudo setfacl -m u:bob:rwx /opt/project
sudo setfacl -m u:charlie:rwx /opt/project

# Set ACL for qa group (read-only)
sudo setfacl -m g:qa:rx /opt/project

# Set default ACLs for new files
sudo setfacl -m d:u:bob:rwx /opt/project
sudo setfacl -m d:u:charlie:rwx /opt/project
sudo setfacl -m d:g:qa:rx /opt/project

# Verify
getfacl /opt/project

Scenario 2: Protected Configuration File

Requirement:

  • Web server configuration must not be accidentally modified
  • Only specific maintenance windows allow changes

Solution:

# Make config immutable
sudo chattr +i /etc/httpd/conf/httpd.conf

# During maintenance window, unlock it
sudo chattr -i /etc/httpd/conf/httpd.conf

# Make changes
sudo vim /etc/httpd/conf/httpd.conf

# Lock it again
sudo chattr +i /etc/httpd/conf/httpd.conf

Scenario 3: Tamper-Proof Audit Logs

Requirement:

  • Application logs must be append-only
  • Logs cannot be deleted or modified (regulatory compliance)
  • Rotation happens weekly by log management system

Solution:

# Make log append-only
sudo chattr +a /var/log/application/app.log

# Application can still append
echo "[$(date)] User login" >> /var/log/application/app.log

# For log rotation, temporarily remove attribute
sudo chattr -a /var/log/application/app.log
# Perform rotation
sudo mv /var/log/application/app.log /var/log/application/app.log.1
sudo touch /var/log/application/app.log
# Reapply attribute
sudo chattr +a /var/log/application/app.log

Scenario 4: Database File Permissions

Requirement:

  • Database files owned by postgres user
  • DBA bob needs read/write access for maintenance
  • Monitoring user needs read-only access
  • Backup service (backup group) needs read access

Solution:

# Set ACLs on database directory
sudo setfacl -R -m u:bob:rwx /var/lib/postgresql
sudo setfacl -R -m u:monitoring:rx /var/lib/postgresql
sudo setfacl -R -m g:backup:rx /var/lib/postgresql

# Set default ACLs for new files
sudo setfacl -m d:u:bob:rwx /var/lib/postgresql
sudo setfacl -m d:u:monitoring:rx /var/lib/postgresql
sudo setfacl -m d:g:backup:rx /var/lib/postgresql

Practice Labs

Time to practice! Complete these 20 hands-on labs to master ACLs and file attributes.

Warm-up Labs (1-5): Basic ACLs

Lab 1: View ACLs of System Files

Task: Use getfacl to view the ACLs of /etc/passwd, /etc/shadow, and /tmp.

Solution
# View ACL of /etc/passwd
getfacl /etc/passwd

# View ACL of /etc/shadow
getfacl /etc/shadow

# View ACL of /tmp directory
getfacl /tmp

What to notice:

  • Most files don't have extended ACLs by default
  • The output shows standard Unix permissions in ACL format
  • Some directories (like /tmp) might have special ACLs

Lab 2: Grant Read Access to Another User

Task: Create a file private_data.txt and grant read access to a specific user (use a real username on your system).

Solution
# Create file
echo "Private information" > private_data.txt

# Check current permissions
ls -l private_data.txt

# Grant read access to user bob
setfacl -m u:bob:r private_data.txt

# Verify
getfacl private_data.txt
ls -l private_data.txt    # Notice the + sign

Lab 3: Grant Write Access to Multiple Users

Task: Create shared.txt and grant read/write access to two different users.

Solution
# Create file
echo "Shared content" > shared.txt

# Grant rw to alice and bob
setfacl -m u:alice:rw,u:bob:rw shared.txt

# Verify
getfacl shared.txt

Expected output:

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

Lab 4: Remove Specific ACL Entry

Task: Using the file from Lab 3, remove alice's ACL entry but keep bob's.

Solution
# Remove alice's entry
setfacl -x u:alice shared.txt

# Verify
getfacl shared.txt

Result: Only bob's ACL entry should remain.

Lab 5: Remove All ACLs

Task: Remove all extended ACL entries from shared.txt.

Solution
# Remove all ACLs
setfacl -b shared.txt

# Verify
getfacl shared.txt
ls -l shared.txt    # The + sign should be gone

Core Labs (6-13): Default ACLs and File Attributes

Lab 6: Create Shared Directory with Default ACLs

Task: Create /tmp/team_project and set default ACLs so that new files automatically grant read/write to bob.

Solution
# Create directory
mkdir /tmp/team_project

# Set default ACL
setfacl -m d:u:bob:rw /tmp/team_project

# Verify
getfacl /tmp/team_project

# Test by creating a file
touch /tmp/team_project/test.txt
getfacl /tmp/team_project/test.txt

Verify: The new file should automatically have bob with rw permissions.

Lab 7: Grant Group Access with ACLs

Task: Grant the developers group (or any group on your system) read/write access to a directory using ACLs.

Solution
# Create directory
mkdir /tmp/dev_workspace

# Grant group access
setfacl -m g:developers:rwx /tmp/dev_workspace

# Set as default for new files
setfacl -m d:g:developers:rwx /tmp/dev_workspace

# Verify
getfacl /tmp/dev_workspace

Lab 8: View File Attributes

Task: Create 3 files and use lsattr to view their attributes.

Solution
# Create files
touch file1.txt file2.txt file3.txt

# View attributes
lsattr file1.txt file2.txt file3.txt

# View all files in directory
lsattr

Lab 9: Make File Immutable

Task: Create a file called important.txt, make it immutable, and try to modify or delete it.

Solution
# Create file
echo "Important data" > important.txt

# Make immutable (requires root)
sudo chattr +i important.txt

# Verify attribute
lsattr important.txt

# Try to modify (should fail)
echo "New data" > important.txt

# Try to delete (should fail)
rm important.txt

# Remove immutable to clean up
sudo chattr -i important.txt
rm important.txt

Lab 10: Create Append-Only Log File

Task: Create a log file that can only be appended to, not modified or deleted.

Solution
# Create log
echo "=== Application Log ===" > app.log

# Make append-only
sudo chattr +a app.log

# Verify
lsattr app.log

# Try appending (should work)
echo "Entry 1: User logged in" >> app.log

# Try overwriting (should fail)
echo "Erase" > app.log

# Try deleting (should fail)
rm app.log

# Verify contents
cat app.log

# Clean up
sudo chattr -a app.log
rm app.log

Lab 11: Recursive ACL Application

Task: Create a directory structure and apply ACLs recursively to all files and subdirectories.

Solution
# Create structure
mkdir -p /tmp/recursive_test/{dir1,dir2,dir3}
touch /tmp/recursive_test/dir1/file1.txt
touch /tmp/recursive_test/dir2/file2.txt
touch /tmp/recursive_test/dir3/file3.txt

# Apply ACL recursively
setfacl -R -m u:bob:rx /tmp/recursive_test

# Verify on various files
getfacl /tmp/recursive_test
getfacl /tmp/recursive_test/dir1
getfacl /tmp/recursive_test/dir1/file1.txt

Lab 12: Combine ACLs with Default ACLs

Task: Create a directory, set both regular and default ACLs, then verify both existing and new files have correct permissions.

Solution
# Create directory with file
mkdir /tmp/combined_test
touch /tmp/combined_test/existing.txt

# Set ACL on existing files
setfacl -R -m u:bob:rw /tmp/combined_test

# Set default ACL for new files
setfacl -m d:u:bob:rw /tmp/combined_test

# Verify existing file
getfacl /tmp/combined_test/existing.txt

# Create new file
touch /tmp/combined_test/newfile.txt

# Verify new file
getfacl /tmp/combined_test/newfile.txt

Both should have bob with rw permissions!

Lab 13: Recursive Immutable Directory

Task: Create a directory with files, make everything immutable recursively, then test protection.

Solution
# Create structure
mkdir /tmp/protected
echo "Doc 1" > /tmp/protected/doc1.txt
echo "Doc 2" > /tmp/protected/doc2.txt

# Make everything immutable
sudo chattr -R +i /tmp/protected

# Verify
lsattr -d /tmp/protected
lsattr /tmp/protected/*

# Try to create file (should fail)
touch /tmp/protected/newfile.txt

# Try to delete file (should fail)
rm /tmp/protected/doc1.txt

# Try to remove directory (should fail)
rmdir /tmp/protected

# Clean up (remove attributes first!)
sudo chattr -R -i /tmp/protected
rm -rf /tmp/protected

Advanced Labs (14-20): Real-World Scenarios

Lab 14: Shared Development Environment

Task: Set up a shared development directory where:

  • Multiple developers (alice, bob, charlie) have full access
  • Testers group has read-only access
  • New files inherit these permissions
Solution
# Create directory
sudo mkdir /opt/dev_project
sudo chown $USER:$USER /opt/dev_project

# Grant developer access
setfacl -m u:alice:rwx,u:bob:rwx,u:charlie:rwx /opt/dev_project
setfacl -m g:testers:rx /opt/dev_project

# Set defaults for new files
setfacl -m d:u:alice:rwx,d:u:bob:rwx,d:u:charlie:rwx /opt/dev_project
setfacl -m d:g:testers:rx /opt/dev_project

# Verify
getfacl /opt/dev_project

# Test with new file
touch /opt/dev_project/main.py
getfacl /opt/dev_project/main.py

Lab 15: Protected System Configuration

Task: Create a simulated system config file, make it immutable, attempt modifications, then perform "maintenance window" changes.

Solution
# Simulate system config
echo "ServerName=production.example.com" > /tmp/server.conf
echo "Port=443" >> /tmp/server.conf

# Protect it
sudo chattr +i /tmp/server.conf

# Try to modify (should fail)
echo "Port=8080" >> /tmp/server.conf

# Maintenance window: unlock
sudo chattr -i /tmp/server.conf

# Make change
echo "MaxConnections=1000" >> /tmp/server.conf

# Lock again
sudo chattr +i /tmp/server.conf

# Verify
lsattr /tmp/server.conf
cat /tmp/server.conf

# Clean up
sudo chattr -i /tmp/server.conf
rm /tmp/server.conf

Lab 16: Audit Log System

Task: Create an audit log system where logs can be appended but never deleted or modified.

Solution
# Create audit log
sudo mkdir -p /var/log/audit_test
sudo touch /var/log/audit_test/security.log
echo "$(date): Audit log initialized" | sudo tee -a /var/log/audit_test/security.log

# Make append-only
sudo chattr +a /var/log/audit_test/security.log

# Add entries (should work)
echo "$(date): User alice logged in" | sudo tee -a /var/log/audit_test/security.log
echo "$(date): File accessed: /etc/passwd" | sudo tee -a /var/log/audit_test/security.log

# Try to erase (should fail)
echo "" | sudo tee /var/log/audit_test/security.log

# Try to delete (should fail)
sudo rm /var/log/audit_test/security.log

# Verify log integrity
cat /var/log/audit_test/security.log

# Clean up
sudo chattr -a /var/log/audit_test/security.log
sudo rm -rf /var/log/audit_test

Lab 17: Mask Behavior Experiment

Task: Explore how the ACL mask affects effective permissions.

Solution
# Create file
echo "Test data" > mask_test.txt

# Grant full permissions to bob
setfacl -m u:bob:rwx mask_test.txt

# Check permissions
getfacl mask_test.txt
# Note bob's effective permissions

# Set restrictive mask
setfacl -m m::r mask_test.txt

# Check again
getfacl mask_test.txt
# Note the #effective comment showing limited permissions

# Verify bob only has read access despite rwx in ACL
ls -l mask_test.txt

Lab 18: Complex Multi-User Scenario

Task: Create a scenario with 3 users having different permissions, 2 groups with different access, and default ACLs.

Solution
# Create project directory
mkdir /tmp/complex_project

# User ACLs
setfacl -m u:alice:rwx /tmp/complex_project    # Project lead - full access
setfacl -m u:bob:rwx /tmp/complex_project      # Developer - full access
setfacl -m u:charlie:rx /tmp/complex_project   # Reviewer - read/execute only

# Group ACLs
setfacl -m g:developers:rwx /tmp/complex_project    # Dev team - full
setfacl -m g:managers:rx /tmp/complex_project       # Management - read only

# Set defaults
setfacl -m d:u:alice:rwx,d:u:bob:rwx,d:u:charlie:rx /tmp/complex_project
setfacl -m d:g:developers:rwx,d:g:managers:rx /tmp/complex_project

# Verify
getfacl /tmp/complex_project

# Test with new file
touch /tmp/complex_project/architecture.md
getfacl /tmp/complex_project/architecture.md

Lab 19: Backup Immutable Files

Task: Practice working with immutable files during backup operations.

Solution
# Create files to back up
mkdir /tmp/data_backup_test
echo "Important file 1" > /tmp/data_backup_test/file1.txt
echo "Important file 2" > /tmp/data_backup_test/file2.txt

# Make them immutable
sudo chattr -R +i /tmp/data_backup_test

# Attempt regular backup (tar can read immutable files)
tar -czf /tmp/backup.tar.gz /tmp/data_backup_test

# Verify backup was created
ls -lh /tmp/backup.tar.gz

# Extract to verify
mkdir /tmp/restore_test
tar -xzf /tmp/backup.tar.gz -C /tmp/restore_test

# Verify contents
cat /tmp/restore_test/tmp/data_backup_test/file1.txt

# Clean up
sudo chattr -R -i /tmp/data_backup_test
rm -rf /tmp/data_backup_test /tmp/restore_test /tmp/backup.tar.gz

Key learning: Immutable files can still be read and backed up, just not modified!

Lab 20: ACL Troubleshooting

Task: Create a scenario where permissions appear wrong and use ACLs to diagnose the issue.

Solution
# Create scenario
mkdir /tmp/troubleshoot
touch /tmp/troubleshoot/mystery.txt
chmod 000 /tmp/troubleshoot/mystery.txt

# User bob reports they can't access the file
# Regular permissions show no access
ls -l /tmp/troubleshoot/mystery.txt
---------+ 1 user user 0 Dec 10 10:00 mystery.txt

# Notice the + sign? ACLs might be involved!
getfacl /tmp/troubleshoot/mystery.txt

# Discover bob has ACL access
# Grant access via ACL
setfacl -m u:bob:rw /tmp/troubleshoot/mystery.txt

# Verify
getfacl /tmp/troubleshoot/mystery.txt

# The mystery: regular permissions show 000 but bob has rw via ACL!
# This demonstrates why you must check ACLs when troubleshooting permissions

Best Practices

ACL Best Practices

  1. Use ACLs sparingly

    • Traditional permissions are simpler and easier to manage
    • Only use ACLs when you need granular permissions
  2. Document ACL usage

    • Keep track of which files/directories have ACLs
    • Document why ACLs were needed
  3. Always set default ACLs on directories

    • Use both -R -m for existing files and -m d: for future files
    • Prevents permission inconsistencies
  4. Check for the + sign

    • The + in ls -l output indicates extended ACLs
    • Always use getfacl to see complete permissions
  5. Be careful with the mask

    • The mask can limit effective permissions
    • Use getfacl to see #effective: permissions
  6. Backup ACLs

    • Use getfacl -R directory > acls.txt to save ACLs
    • Restore with setfacl --restore=acls.txt
  7. Test thoroughly

    • Always test ACLs with the actual users
    • Don't assume ACLs work as expected without testing

File Attribute Best Practices

  1. Use immutable for critical configs

    • Protect system configs from accidental changes
    • Document which files are immutable
  2. Use append-only for logs

    • Perfect for audit trails and security logs
    • Consider automated log rotation needs
  3. Require root for attributes

    • Only root can change attributes
    • This adds an extra layer of security
  4. Check before operations

    • Always check attributes with lsattr when operations fail
    • Mysterious permission errors might be due to attributes
  5. Remove attributes for maintenance

    • Plan maintenance windows to remove attributes
    • Re-apply attributes after changes
  6. Document attribute usage

    • Keep inventory of files with special attributes
    • Include removal procedures for emergencies

Common Pitfalls

ACL Pitfalls

  1. Forgetting the mask

    # You grant rwx to bob
    setfacl -m u:bob:rwx file.txt
    
    # But mask limits it to rw
    getfacl file.txt
    user:bob:rwx    #effective:rw-
    mask::rw-
    
    # Bob can't execute despite rwx in ACL!
    
  2. Not setting default ACLs

    # You set ACL on directory
    setfacl -m u:bob:rwx /project
    
    # But forgot default ACL
    # New files won't have bob's access!
    
    # Always add both:
    setfacl -R -m u:bob:rwx /project     # Existing
    setfacl -m d:u:bob:rwx /project      # Future
    
  3. Copying files loses ACLs

    # Regular cp loses ACLs
    cp file_with_acls.txt backup.txt
    getfacl backup.txt    # ACLs are gone!
    
    # Use -a to preserve
    cp -a file_with_acls.txt backup.txt
    
  4. mv preserves ACLs, cp doesn't (by default)

    # mv keeps ACLs
    mv file_with_acls.txt newname.txt
    
    # cp loses them (unless -a)
    cp file_with_acls.txt copy.txt
    
  5. Forgetting to check for +

    # File shows restricted permissions
    ls -l secret.txt
    -r--r-----+ 1 alice alice 100 Dec 10 10:00 secret.txt
               ↑
               Don't miss this +!
    
    # But bob might have write access via ACL
    getfacl secret.txt
    

File Attribute Pitfalls

  1. Root can't delete immutable files

    sudo rm -rf /    # This won't delete immutable files!
    # Immutable files survive even catastrophic mistakes
    
  2. Forgetting to remove attributes

    # Can't rotate logs
    mv app.log app.log.1
    mv: cannot move 'app.log': Operation not permitted
    
    # Must remove +a first
    sudo chattr -a app.log
    mv app.log app.log.1
    
  3. Backup tools may skip attributes

    # Regular tar doesn't preserve attributes
    tar -czf backup.tar.gz file.txt
    
    # Use star or GNU tar with --xattrs
    tar --xattrs -czf backup.tar.gz file.txt
    
  4. Not all filesystems support all attributes

    # Some attributes work on ext4 but not on other filesystems
    # Always check your filesystem capabilities
    
  5. Scripts failing mysteriously

    # Your automated script fails
    echo "data" > file.txt
    # Operation not permitted
    
    # Check for attributes!
    lsattr file.txt
    ----i---------e------- file.txt
    

Quick Reference: ACL Commands

| Command | Description | Example | |---------|-------------|---------| | getfacl FILE | View ACLs | getfacl data.txt | | setfacl -m u:USER:PERMS FILE | Grant user permissions | setfacl -m u:bob:rw file.txt | | setfacl -m g:GROUP:PERMS FILE | Grant group permissions | setfacl -m g:dev:rwx dir/ | | setfacl -x u:USER FILE | Remove user ACL | setfacl -x u:bob file.txt | | setfacl -b FILE | Remove all ACLs | setfacl -b file.txt | | setfacl -m d:u:USER:PERMS DIR | Set default ACL | setfacl -m d:u:bob:rw dir/ | | setfacl -R -m u:USER:PERMS DIR | Recursive ACL | setfacl -R -m u:bob:rx /data | | setfacl -m m::PERMS FILE | Set mask | setfacl -m m::r file.txt | | getfacl -R dir > acls.txt | Backup ACLs | getfacl -R /project > backup.txt | | setfacl --restore=acls.txt | Restore ACLs | setfacl --restore=backup.txt |


Quick Reference: File Attribute Commands

| Command | Description | Example | |---------|-------------|---------| | lsattr FILE | View attributes | lsattr important.txt | | lsattr -d DIR | View directory attributes | lsattr -d /project | | lsattr -a | Include hidden files | lsattr -a | | sudo chattr +i FILE | Make immutable | sudo chattr +i config.txt | | sudo chattr -i FILE | Remove immutable | sudo chattr -i config.txt | | sudo chattr +a FILE | Make append-only | sudo chattr +a app.log | | sudo chattr -a FILE | Remove append-only | sudo chattr -a app.log | | sudo chattr -R +i DIR | Recursive immutable | sudo chattr -R +i /backup | | sudo chattr +A FILE | No atime updates | sudo chattr +A bigfile.dat | | sudo chattr +S FILE | Synchronous writes | sudo chattr +S critical.db |


Common Attribute Flags

| Flag | Meaning | Effect | |------|---------|--------| | i | Immutable | Cannot modify, delete, rename, or link | | a | Append-only | Can only append data, can't modify existing | | A | No atime | Don't update access time (performance) | | S | Synchronous | Changes written immediately to disk | | s | Secure delete | Zeros data blocks on deletion | | u | Undeletable | Can be recovered after deletion | | c | Compressed | Automatically compressed (if supported) | | e | Extent format | Uses extents (ext4 default) |


Key Takeaways

  1. ACLs extend traditional permissions to allow fine-grained control for multiple users and groups

  2. getfacl views ACLs, setfacl modifies them

  3. The + sign in ls -l output indicates extended ACLs are present

  4. Default ACLs on directories define permissions for newly created files

  5. The mask limits effective permissions for ACL entries

  6. File attributes provide filesystem-level protection beyond permissions

  7. lsattr views attributes, chattr modifies them (requires root)

  8. Immutable (+i) prevents any modifications, even by root

  9. Append-only (+a) allows appending data but prevents modification or deletion

  10. Always document ACL and attribute usage for system maintenance

  11. Backup ACLs with getfacl -R and restore with setfacl --restore

  12. Check for attributes first when troubleshooting mysterious permission errors


What's Next?

You've now mastered advanced permission control with ACLs and file attributes! In the next post, we'll dive into Regular Expressions Part 1: Basics, where you'll learn:

  • What regular expressions are and why they're powerful
  • Basic regex patterns (^, $, .)
  • Character classes ([abc], [a-z], [0-9])
  • Quantifiers (*, +, ?)
  • Using regex with grep for powerful pattern matching
  • Real-world log parsing and text searching

Regular expressions are one of the most powerful tools in a system administrator's arsenal. Get ready to unlock pattern matching superpowers!

Continue your LFCS journey: LFCS Part 36: Regular Expressions - Basics


Previous Post: LFCS Part 34: Understanding File Permissions and chmod

Next Post: LFCS Part 36: Regular Expressions - Basics


Practice, practice, practice! ACLs and file attributes are powerful tools that require hands-on experience. Complete all 20 labs and experiment with your own scenarios. The more you practice, the more comfortable you'll become with these advanced permission controls.

Happy learning! 🚀

Thank you for reading!

Published on December 26, 2025

Owais

Written by Owais

I'm an AIOps Engineer with a passion for AI, Operating Systems, Cloud, and Security—sharing insights that matter in today's tech world.

I completed the UK's Eduqual Level 6 Diploma in AIOps from Al Nafi International College, a globally recognized program that's changing careers worldwide. This diploma is:

  • ✅ Available online in 17+ languages
  • ✅ Includes free student visa guidance for Master's programs in Computer Science fields across the UK, USA, Canada, and more
  • ✅ Comes with job placement support and a 90-day success plan once you land a role
  • ✅ Offers a 1-year internship experience letter while you study—all with no hidden costs

It's not just a diploma—it's a career accelerator.

👉 Start your journey today with a 7-day free trial

Related Articles

Continue exploring with these handpicked articles that complement what you just read

25 min read

LFCS Part 42: Understanding SSH and Remote Server Access

Master SSH for secure remote server access in Linux. Learn SSH vs Telnet, installing and configuring SSH/sshd, making remote connections, transferring files with scp, SSH key authentication, and essential remote administration techniques.

#Linux#LFCS+7 more
Read article
21 min read

LFCS Part 38: Text Transformation with tr

Master the tr command for character-by-character text transformation. Learn case conversion, character deletion, squeezing repeats, and complement sets for efficient text processing.

#Linux#LFCS+6 more
Read article

More Reading

One more article you might find interesting