Shared finance directory, default ACLs and a setuid import script
On an Ubuntu 22.04 file server, /srv/finance is owned root:finance, mode 2775. Users alice, bob and carol are members of finance and nothing else. The login shell default umask is 0022. Alice creates budget.ods; it appears as -rw-r--r-- alice finance, so bob can read it but cannot edit it. Carol reports the same for files she creates. An administrator runs setfacl -m g:finance:rwx /srv/finance on the directory, but newly created files are still not group-writable. Meanwhile /usr/local/bin/import.sh, owned by root, mode 4755, is supposed to let finance users run a fixed import; it sits on an NFS mount exported with nosuid, and it invokes /bin/bash with arguments taken from the caller. The team wants group collaboration to work without giving everyone sudo, and wants the import tool to remain usable only by finance.
1. Compute the mode Alice's file receives and explain why the setgid bit and the directory ACL did not make it group-writable.
Read the worked answer
Base file mode is 0666 for a normal file, then the umask is applied: 0666 & ~0022 = 0644. That is rw- for the owner and r-- for group and others. Alice's file is -rw-r--r-- alice finance, exactly as observed; bob can read but not write.
The setgid bit on /srv/finance does two things: new files inherit the directory's group, finance, and new subdirectories inherit setgid. It does not add group write permission. Group ownership is correct; the permission bits are not.
The command setfacl -m g:finance:rwx /srv/finance sets an access ACL on the directory itself. It does not propagate to files created later. Propagation requires a default ACL, setfacl -d -m g:finance:rwx /srv/finance, which is copied into the ACL of each new file and directory. Without -d, the only effect is on access to the directory, not on its new contents. Also remember that the ACL mask caps effective permissions, so getfacl should be checked after the change.
2. Recommend a concrete, least-privilege configuration and state the trade-offs of umask versus default ACLs.
Read the worked answer
Least-privilege setup:
# group collaboration, inherited by new files and directories
setfacl -d -m g:finance:rwx /srv/finance
setfacl -m g:finance:rwx /srv/finance
# fix existing files if appropriate
setfacl -R -m g:finance:rwX /srv/finance
The default ACL gives new files a group entry of rwx and a mask; because regular files are created without execute permission, the effective group permission on a regular file will be rw-. Execute is only meaningful for directories or scripts. Existing files need a one-time recursive ACL; capital X grants execute only where it is already set or where the target is a directory.
Trade-offs:
- Default ACL is per-directory and survives users with different umasks; it is the better fit for a shared project tree. It can be modified by a later
chmodon the file, which recalculates the mask, so users can still accidentally remove group access. - umask 0002 in a shared shell profile is simpler but global to the user's session; it also makes all new files group-writable everywhere, not just in
/srv/finance. It does not help files created by services or by users who have not sourced the profile.
Use the default ACL, keep the setgid bit for group inheritance, and audit with getfacl.
3. Evaluate the import.sh setuid plan: will it grant root? What about nosuid and the bash argument handling? Propose a safer mechanism.
Read the worked answer
Three independent reasons the setuid plan fails or is unsafe.
- Linux ignores setuid on interpreted scripts. The kernel honors the setuid bit only on ELF binaries. For a script, the interpreter is executed and the script is passed as an argument; the setuid bit on the script is not applied. Mode 4755 shows in
ls, but the process runs as the calling user, not root. - nosuid. The script is on an NFS mount exported with
nosuid, so even an ELF setuid binary there would not gain privilege.mountwould shownosuid; moving the binary to a local filesystem would be required, but that does not fix the shell-script problem. - Argument injection. Even a working privileged wrapper that invokes
/bin/bashwith caller-supplied arguments is dangerous. A caller can pass-c, redirections or environment variables such asBASH_ENVand obtain a root shell. Environment variables must be cleared and arguments validated against a strict allowlist.
Safer mechanism: keep import.sh root-owned and not writable by finance, and grant a narrowly scoped sudo rule:
%finance ALL=(root) /usr/local/bin/import.sh
The script must not trust its arguments; validate them, use absolute paths and avoid passing them to a shell. If the tool needs more than a fixed command, write a small compiled helper instead of a shell script. Verify with sudo -l as a finance user.