Skip to content

Lab: Permissions and ACLs in a Shared Directory

The permissions, ownership, and special permissions articles each covered one mechanism in isolation. A real production incident rarely involves just one — it involves a shared directory where three different teams need different levels of access, new files keep landing with the wrong group, and someone eventually calls you because "the developers can't read the ops logs." This lab reproduces exactly that setup on a disposable lab machine and fixes it using DAC (chmod/chgrp), setgid for automatic group inheritance, the sticky bit, and POSIX ACLs for the one exception that ordinary Unix permissions cannot express on their own.

Goal and End Result

By the end of this lab, /srv/shared-project will:

  • be owned by a shared group project-team, with every new file automatically inheriting that group (setgid);
  • allow every project-team member to create and edit files, but not delete files owned by other members (sticky bit);
  • grant one additional user, auditor, read-only access without adding them to project-team at all (ACL);
  • be verified from the point of view of each user separately, not just as root.

Topology and Starting State

A single lab VM or container is enough; no networking is required. You will create three ordinary users and one shared group.

sudo groupadd project-team
sudo useradd -m -G project-team dev1
sudo useradd -m -G project-team dev2
sudo useradd -m auditor
sudo passwd dev1
sudo passwd dev2
sudo passwd auditor

Requirements

  • acl package installed, for setfacl/getfacl:
sudo apt install acl
  • ability to switch users (su - <user>) to verify behavior from each account's perspective, not only as root.

Security and Snapshot Note

Warning

This lab creates real user accounts and modifies permissions under /srv. If you are on a shared or production-adjacent machine, run this in a disposable VM or container instead. Before changing anything, record the current state so you have something to compare against and roll back to:

ls -ld /srv
getent group project-team 2>/dev/null && echo "group already exists — stop and check"

Step 1: Create the Shared Directory

sudo mkdir -p /srv/shared-project
sudo chgrp project-team /srv/shared-project
sudo chmod 2775 /srv/shared-project

2775 breaks down the same way Special Permissions explained: the leading 2 sets the setgid bit, 775 gives the owner and group full read/write/execute, others read/execute only.

Verify:

ls -ld /srv/shared-project
drwxrwsr-x 2 root project-team 4096 Jul 29 10:00 /srv/shared-project

The s in place of the group's execute bit confirms setgid is active — this is the detail to check immediately if new files ever start appearing with the wrong group later in this lab.

Step 2: Confirm setgid Inheritance

su - dev1
touch /srv/shared-project/dev1-notes.txt
ls -l /srv/shared-project/dev1-notes.txt
-rw-rw-r-- 1 dev1 project-team 0 Jul 29 10:02 dev1-notes.txt

The file's group is project-team, not dev1's primary group — exactly the setgid behavior being tested. Without setgid on the parent directory, this file would have inherited dev1's own primary group instead, and dev2 would have been unable to write to it despite both being in project-team.

exit

Step 3: Add the Sticky Bit to Prevent Cross-Deletion

Right now, any project-team member can delete any other member's file, because both have write access to the directory itself — write access to a directory, not to the file, is what rm actually checks.

sudo chmod +t /srv/shared-project
ls -ld /srv/shared-project
drwxrwsr-t 2 root project-team 4096 Jul 29 10:02 /srv/shared-project

Verify the sticky bit actually blocks cross-deletion:

su - dev2
touch /srv/shared-project/dev2-file.txt
exit

su - dev1
rm /srv/shared-project/dev2-file.txt
rm: cannot remove '/srv/shared-project/dev2-file.txt': Operation not permitted

This confirms the exact mechanism from Special Permissions: the sticky bit restricts deletion to a file's owner (or root), even when every group member has write access to the directory that contains it.

su - dev2
rm /srv/shared-project/dev2-file.txt
exit

dev2 can still remove their own file — the sticky bit only blocks deletion by other users, not by the owner.

Step 4: Grant Read-Only Access to One Extra User with ACLs

auditor needs to read everything in /srv/shared-project without becoming a full project-team member (which would also grant write access) and without opening the directory to every other user on the system — a requirement ordinary Unix permissions cannot express, since there is no fourth permission slot for "this one specific extra user."

sudo setfacl -m u:auditor:rx /srv/shared-project
sudo setfacl -d -m u:auditor:rx /srv/shared-project

The first command grants auditor read and execute (traverse) on the directory itself; the second sets a default ACL, which is inherited by every file and subdirectory created afterward — without it, auditor's access would apply only to the directory entry, not to any of the files inside it.

Before running getfacl, note that an ordinary ls -ld already tells you an ACL is present:

ls -ld /srv/shared-project
drwxrwsr-t+ 2 root project-team 4096 Jul 29 10:05 /srv/shared-project

The trailing + on the permission string (drwxrwsr-t+) is the signal that an ACL beyond the standard owner/group/other bits exists on this path — a detail interviewers ask about directly ("how do you tell a file has an ACL without running getfacl?"), and the reason the plain mode bits shown by ls -l can be misleading on their own: a + means the effective permissions are not fully described by the rwx triplets alone.

Verify:

getfacl /srv/shared-project
# file: srv/shared-project
# owner: root
# group: project-team
user::rwx
user:auditor:r-x
group::rwx
mask::rwx
other::r-x
default:user::rwx
default:user:auditor:r-x
default:group::rwx
default:mask::rwx
default:other::r-x
su - auditor
ls /srv/shared-project
cat /srv/shared-project/dev1-notes.txt
touch /srv/shared-project/should-fail.txt
touch: cannot touch '/srv/shared-project/should-fail.txt': Permission denied

auditor can list and read, exactly as granted, and cannot create files — the ACL entry stopped exactly at rx, with no w.

exit

Troubleshooting Tips

  • A new file has the wrong group despite setgid being set. Check that setgid is set on the directory the file was created in, not a parent directory further up — setgid is not automatically recursive to subdirectories created before the bit was set; each existing subdirectory needs chmod g+s applied individually, or chmod -R g+s if this is genuinely intended for the whole tree (see the danger note below).
  • getfacl shows no ACL entries at all. The acl package may not be installed, or the filesystem may have been mounted without ACL support — check with mount | grep <mountpoint> for the acl option, and add it in /etc/fstab if missing (requires a remount).
  • A permission that should apply doesn't, and mask:: in getfacl output is more restrictive than expected. The ACL mask caps the effective permissions of every named user and group entry — a mask::r-- silently reduces an ACL entry that grants rwx down to r--; setfacl -m mask::rwx <path> fixes this if it was unintentional.

Rollback and Cleanup

Danger

chmod -R and userdel -r are destructive and irreversible on real data. Confirm you are removing lab-only accounts and directories, not anything with real content, before running the following.

sudo rm -rf /srv/shared-project
sudo userdel -r dev1
sudo userdel -r dev2
sudo userdel -r auditor
sudo groupdel project-team

userdel -r also removes each user's home directory — appropriate here since these were lab-only accounts created in Step 0, but never run this against an account that might hold real data without confirming first.

Final Assessment Criterion

This lab is complete when all of the following hold:

  • a file created by dev1 inside /srv/shared-project is owned by group project-team, not dev1's own primary group;
  • dev1 cannot delete a file created by dev2 in the same directory, and vice versa;
  • auditor can read every file in the directory and list its contents, but cannot create or modify anything inside it;
  • getfacl output for the directory shows both a regular and a default ACL entry for auditor.

Exercises

  1. Add a third developer, dev3, to project-team after completing this lab, and confirm — without re-running any setfacl or chmod command — that dev3 immediately has the same group-based access as dev1 and dev2. Explain why no ACL change was needed for this, but would have been needed for auditor.
  2. Remove the sticky bit (chmod -t /srv/shared-project) and repeat Step 3's cross-deletion test. Confirm the deletion now succeeds, then restore the sticky bit.
  3. Using find, write a single command that audits /srv for any directory with the setgid bit set, in the style of Special Permissions' audit section.
  4. Grant auditor write access to exactly one specific file in the directory (not the whole directory) using a file-level ACL entry, and verify with getfacl on that file alone that the permission differs from the directory's default.

References