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
setfaclfor users and groups - ACL masks and effective permissions
- Default ACLs for directories
- File attributes with
chattrandlsattr - 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:
- One owner (alice)
- One group (developers)
- 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 groupuser::rw-- Owner has read/writegroup::r--- Group has read-onlyother::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 accessmask::rw-- A mask entry appeared (explained later)- The traditional
ls -loutput 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
rwxto 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 seti- 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
-
Use ACLs sparingly
- Traditional permissions are simpler and easier to manage
- Only use ACLs when you need granular permissions
-
Document ACL usage
- Keep track of which files/directories have ACLs
- Document why ACLs were needed
-
Always set default ACLs on directories
- Use both
-R -mfor existing files and-m d:for future files - Prevents permission inconsistencies
- Use both
-
Check for the + sign
- The
+inls -loutput indicates extended ACLs - Always use
getfaclto see complete permissions
- The
-
Be careful with the mask
- The mask can limit effective permissions
- Use
getfaclto see#effective:permissions
-
Backup ACLs
- Use
getfacl -R directory > acls.txtto save ACLs - Restore with
setfacl --restore=acls.txt
- Use
-
Test thoroughly
- Always test ACLs with the actual users
- Don't assume ACLs work as expected without testing
File Attribute Best Practices
-
Use immutable for critical configs
- Protect system configs from accidental changes
- Document which files are immutable
-
Use append-only for logs
- Perfect for audit trails and security logs
- Consider automated log rotation needs
-
Require root for attributes
- Only root can change attributes
- This adds an extra layer of security
-
Check before operations
- Always check attributes with
lsattrwhen operations fail - Mysterious permission errors might be due to attributes
- Always check attributes with
-
Remove attributes for maintenance
- Plan maintenance windows to remove attributes
- Re-apply attributes after changes
-
Document attribute usage
- Keep inventory of files with special attributes
- Include removal procedures for emergencies
Common Pitfalls
ACL Pitfalls
-
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! -
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 -
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 -
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 -
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
-
Root can't delete immutable files
sudo rm -rf / # This won't delete immutable files! # Immutable files survive even catastrophic mistakes -
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 -
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 -
Not all filesystems support all attributes
# Some attributes work on ext4 but not on other filesystems # Always check your filesystem capabilities -
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
-
ACLs extend traditional permissions to allow fine-grained control for multiple users and groups
-
getfacl views ACLs, setfacl modifies them
-
The + sign in
ls -loutput indicates extended ACLs are present -
Default ACLs on directories define permissions for newly created files
-
The mask limits effective permissions for ACL entries
-
File attributes provide filesystem-level protection beyond permissions
-
lsattr views attributes, chattr modifies them (requires root)
-
Immutable (+i) prevents any modifications, even by root
-
Append-only (+a) allows appending data but prevents modification or deletion
-
Always document ACL and attribute usage for system maintenance
-
Backup ACLs with
getfacl -Rand restore withsetfacl --restore -
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! 🚀

