How to Add Write Permissions with setfacl Without Overriding Existing ACLs


4 views

When working with Access Control Lists (ACLs) in Linux, a common challenge arises when you need to add new permissions without disturbing existing ones. The standard setfacl -m command can be too aggressive, replacing the entire permission set rather than augmenting it.

Consider this typical command:

setfacl -R -m u:username:w directory/*

This will indeed grant write permissions, but at the cost of any existing permissions the user might have had. For example, if the user previously had execute (x) permissions, those would be lost.

To retain current permissions while adding new ones, we need to:

  1. First retrieve the existing permissions
  2. Then append the new permission

Here's the robust solution:

getfacl -R directory > acl_backup.txt
setfacl --restore=acl_backup.txt
setfacl -R -m u:username:rwx directory/*

For a more elegant solution that doesn't require temporary files:

find directory -exec setfacl -m u:username:rwX '{}' \;

The capital X grants execute permission only if it's already present on the file or if it's a directory.

Let's walk through a concrete example:

# Initial state: user 'dev' has rx permissions
$ getfacl project/file
# file: project/file
# owner: root
# group: team
user::rwx
user:dev:r-x
group::r-x
mask::r-x
other::r-x

# Wrong approach (overwrites existing permissions)
$ setfacl -m u:dev:w project/file

# Correct approach (preserves existing permissions)
$ setfacl -m u:dev:rwx project/file

For recursive operations, we must consider performance implications. The most efficient method is:

find /path/to/dir -type d -exec setfacl -m u:user:rwx '{}' \;
find /path/to/dir -type f -exec setfacl -m u:user:rw '{}' \;

This separates directory and file handling for optimal permission assignment.

Always remember that the effective permissions are the intersection of the ACL entry and the mask. After modifying permissions, you might need to adjust the mask:

setfacl -R -m m::rwx directory

After making changes, verify with:

getfacl filename
ls -ld filename

Look for the + sign in ls -l output which indicates ACLs are present.


When working with Linux filesystems, there's a crucial difference between replacing and modifying access control entries. The standard setfacl -m command replaces all permissions for the specified user/group, which often isn't the desired behavior when you just want to add one permission.

To add write permission while preserving existing permissions, we need to:

setfacl -R -m u:user:rwx,d:u:user:rwx dir/

Here's why this works:

  1. -R makes the change recursive
  2. -m modifies rather than replaces ACLs
  3. u:user:rwx grants read/write/execute (but only adds to existing permissions)
  4. d:u:user:rwx sets the same for future files/directories

Imagine we have a developer "johnd" who needs write access to a web directory but must keep existing execute permissions:

# Current permissions (shows john has r-x currently)
getfacl /var/www/html/

# Add write permission without changing others
setfacl -R -m u:johnd:rwx,d:u:johnd:rwx /var/www/html/

# Verify the changes
getfacl /var/www/html/main.js

For more precise control, you can read existing permissions first:

# Get current permissions
current_perm=$(getfacl -c dir/ | grep "^user:user:" | cut -d: -f3)

# Add write permission to whatever exists
setfacl -R -m u:user:${current_perm}w dir/

Remember that:

  • Default ACLs (d:) only affect newly created items
  • Existing files won't get new permissions automatically
  • The mask entry may limit effective permissions

If permissions aren't applying as expected:

# Check if filesystem is mounted with acl option
mount | grep acl

# Verify no conflicting SELinux contexts
ls -Z /path/to/dir