Linux security - Access Control Lists

mail

ls reports unexpected group permissions on files with ACL

Don't trust what ls reports about group permissions of files with ACL :
  1. ls -l someFile
  2. When you see this :
    -rw-r-----+ 1 kevin admin 0 Feb 16 09:58 someFile
  3. Don't believe this :
    -rw-r-----+ 1 kevin admin 0 Feb 16 09:58 someFile

When a file has extended ACL :

  • its permissions are more complex than what can be reported by the Unix permissions —like -rw-r--r--— (aka minimal ACL)
  • the 2nd triad of permissions reported by ls
    • does not represent group permissions anymore
    • represents group class permissions

Examples

With a regular file

otherUser=nobody; showPerms() { local whichFile=$1; ls -l "$whichFile"; getfacl "$whichFile"; }; myFile=$(mktemp tmpFile.XXXXXXXX); echo 'WITHOUT ACL'; showPerms "$myFile"; echo 'WITH ACL'; setfacl -m u:"$otherUser":r "$myFile"; showPerms "$myFile"; [ -f "$myFile" ] && rm "$myFile"
WITHOUT ACL
-rw------- 1 kevin admin 0 Feb 16 12:02 tmpFile.SRnstAdC
# file: tmpFile.SRnstAdC
# owner: kevin
# group: admin
user::rw-
group::---
other::---

WITH ACL
-rw-r-----+ 1 kevin admin 0 Feb 16 12:02 tmpFile.SRnstAdC
# file: tmpFile.SRnstAdC
# owner: kevin
# group: admin
user::rw-
user:nobody:r--
group::---			actual group permissions
mask::r--
other::---

With a directory

otherUser=nobody; showPerms() { local thing=$1; [ -d "$thing" ] && ls -ld "$thing" || ls -l "$thing"; getfacl "$thing"; }; myDir=$(mktemp -d tmpThing.XXXXXXXX); echo 'WITHOUT ACL'; showPerms "$myDir"; echo 'WITH ACL'; setfacl -m u:"$otherUser":r "$myDir"; showPerms "$myDir"; [ -d "$myDir" ] && rmdir "$myDir"
WITHOUT ACL
drwx------ 2 kevin admin 4096 Feb 16 12:07 tmpThing.7mJSe9Pi
# file: tmpThing.7mJSe9Pi
# owner: kevin
# group: admin
user::rwx
group::---
other::---

WITH ACL
drwxr-----+ 2 kevin admin 4096 Feb 16 12:07 tmpThing.7mJSe9Pi
# file: tmpThing.7mJSe9Pi
# owner: kevin
# group: admin
user::rwx
user:nobody:r--
group::---			actual group permissions
mask::r--
other::---

With both directory + file and recursivity

otherUser=nobody; showPerms() { local thing=$1; [ -d "$thing" ] && ls -ld "$thing" || ls -l "$thing"; getfacl "$thing"; }; myDir=$(mktemp -d tmpThing.XXXXXXXX); chmod 700 "$myDir"; myFile=$(mktemp --tmpdir="$myDir" tmpThing.XXXXXXXX); chmod 600 "$myFile"; echo 'WITHOUT ACL'; showPerms "$myDir"; showPerms "$myFile"; echo 'WITH ACL'; setfacl -Rm u:"$otherUser":rX "$myDir"; showPerms "$myDir"; showPerms "$myFile"; [ -d "$myDir" ] && rm -Rf "$myDir"
WITHOUT ACL
drwx------ 2 kevin admin 4096 Feb 16 12:10 tmpThing.RmfK2aru
# file: tmpThing.RmfK2aru
# owner: kevin
# group: admin
user::rwx
group::---
other::---

-rw------- 1 kevin admin 0 Feb 16 12:10 tmpThing.RmfK2aru/tmpThing.zQMz5UHf
# file: tmpThing.RmfK2aru/tmpThing.zQMz5UHf
# owner: kevin
# group: admin
user::rw-
group::---
other::---

WITH ACL
drwxr-x---+ 2 kevin admin 4096 Feb 16 12:10 tmpThing.RmfK2aru
# file: tmpThing.RmfK2aru
# owner: kevin
# group: admin
user::rwx
user:nobody:r-x		due to the rX in setfacl
group::---
mask::r-x
other::---

-rw-r-----+ 1 kevin admin 0 Feb 16 12:10 tmpThing.RmfK2aru/tmpThing.zQMz5UHf
# file: tmpThing.RmfK2aru/tmpThing.zQMz5UHf
# owner: kevin
# group: admin
user::rw-
user:nobody:r--		not a directory, not executable, so only gains a r
group::---
mask::r--
other::---
I've also seen situations where files get an extra "x" in their "group permissions". Looks related to :
- permissions on parent directory
- permissions inherited by default ACL
- "create dir THEN set ACL (with -R, with default ACL) THEN create subfile"	vs	"create dir+file THEN set ACL (with -R, with default ACL)"
- ...
==> not clear yet, to be investigated

when playing/replaying commands and comparing "ls" before/after output, mind the extra characters :

	-rw-r--r--+ 1 kevin admin 0 Feb 15 16:20 myFile		BEFORE setfacl ...
	-rw-r-xr--+ 1 kevin admin 0 Feb 15 16:20 myFile		AFTER  setfacl ...

- the AFTER line has a "+", which is no surprise since we just added an ACL with setfacl
- the BEFORE line also has a "+", meaning other ACL existed prior to this experiment, which _could_ explain the extra x
mail

ACL

Usage

ACL support is built in the kernel since the early 2.6 versions and works with the EXTn filesystems (and many others). ACL are based on file extended attributes (= metadata attached to the files).

Preliminary

Before using ACL, we must make sure that :
  1. the kernel supports them : zgrep POSIX_ACL /boot/config* (used to be /proc/config.gz), which may output :
    CONFIG_EXT2_FS_POSIX_ACL=y
    CONFIG_EXT3_FS_POSIX_ACL=y
    CONFIG_EXT4_FS_POSIX_ACL=y
    CONFIG_REISERFS_FS_POSIX_ACL=y
    CONFIG_JFS_POSIX_ACL=y
    CONFIG_XFS_POSIX_ACL=y
    CONFIG_BTRFS_FS_POSIX_ACL=y
    CONFIG_FS_POSIX_ACL=y
    CONFIG_TMPFS_POSIX_ACL=y
    CONFIG_JFFS2_FS_POSIX_ACL=y
    CONFIG_9P_FS_POSIX_ACL=y
  2. the filesystem we're about to play with is mounted with the acl flag (which enables support of the ACL. Just in case : noacl does the opposite) :
    1. check the mount options :
      grep /home /etc/fstab
      /dev/mapper/vg-home	/home	ext4	defaults,noatime	0	2
    2. It's very likely that mount options will only mention defaults, which means use the default mount options as specified by the filesystem itself. So let's view these default mount options (source), as root :
      tune2fs -l $(awk -v filesystem='/home' '$0 ~ filesystem {print $1}' /etc/fstab) | grep 'Default mount options'
      Default mount options:	user_xattr acl

Different types of ACL

Minimal ACL
attributes : owner, group and other only, reflecting the Unix permissions
Extended ACL
  • attributes :
    • owner, group and other attributes (minimal ACL)
    • named user + named group + mask attributes. The named user and named group attributes hold the specific users / groups permissions.
  • Files with extended ACL are displayed with an additional + by ls :
    -rw-r--r--+	1 kevin users	343 2005-02-07 16:53 someFile
Since all files do have ACL (either minimal or extended), what is meant by saying the file foo.txt has an ACL is the file foo.txt has an extended ACL.
Default ACL (details : 1, 2)
  • exist for directories only : they apply to sub-items (directories and files), but only directories can have a default ACL
  • are access control entries that get inherited by sub-items of a directory :
  • imply extra notions :
    • default ACL (the kind of ACL I'm trying to define here ) :
      • files with no ACL abide by the default ACL
      • the corresponding permissions are prefixed with default: by getfacl
    • access ACL : ACL entries that define access permissions (i.e. everything else than default ACL).
Considering that :
  • access ACL only affect files that exist when running setfacl (i.e. no effect on files created afterwards)
  • default ACL only affect files created after running setfacl (i.e. no effect on existing files)
if you want to grant permissions to Bob on current and future files of someDirectory, you'll need something like (source) :
setfacl -Rm u:bob:rwX,d:u:bob:rwX someDirectory

Types of ACL Entries (source)

Entry type Text form
owner user::rwx
named user user:stuart:rwx
owning group group::rwx
named group group:admins:rwx
mask mask::rwx
others other::rwx

Group class permissions (source)

File permissions are usually displayed like :
- rwx rw- r--
where the highlighted bits (the 2nd triad) represent the group class permissions. The group class permissions represent the upper bound of the permissions granted by any entry in the group class :
  • with minimal ACL, the group class only refers to the group attribute, and basically represent the permissions granted to the owning group (traditional Unix permissions)
  • with extended ACL :
    • the group class
      • is the value of the mask attribute
      • works with the named user + named group attributes
    • the effective permissions a member of the group class (i.e. either a named user or a named group) gets
      • are those that are present both in the member permissions and in the mask
      • permissions that are absent from the mask are masked and thus do not take effect
      for a named user for a named group
      group class permissions user:bob:r-x group:developers:r--
      mask mask::rw-
      Effective permissions r-- r--
The owner and other entries are not in the group class : their permissions are always effective and never masked.

Precedence of permissions (sources : 1, 2)

The question of the precedence of the traditional Unix permissions vs ACL is irrelevant since traditional Unix permissions are actually embedded into extended ACL.
When a process requests access to a file system object, 2 actions are triggered :
  1. select the ACL entry that most closely matches the requesting process.
    • ACL entries are looked at in the following order:
      1. owner, based on the process's effective UID
      2. named user, based on the process's effective UID
      3. owning group, named group, based on the process's effective GID
      4. others
    • only a single entry determines access
  2. check if the matching entry contains sufficient permissions

Example

Read an ACL

getfacl someFile
# file: someFile
# owner: kevin
# group: users
user::rw-
group::r--
mask::rwx
other::r--

modify an ACL : grant user rights

setfacl -m u:bob:rw- file

Do default ACL affect existing files ?

Let's check it :
tmpDir=$(mktemp -d playingWithAcl.XXXX); otherUser='www-data'; mkdir -p "$tmpDir"
echo 'created BEFORE applying default ACL' > "$tmpDir/before"
setfacl -m u:$otherUser:rwx "$tmpDir"
setfacl -d -m u:$otherUser:rwx "$tmpDir"
echo 'created AFTER applying default ACL' > "$tmpDir/after"
getfacl "$tmpDir/"{before,,after}
rm "$tmpDir/"{before,after}; rmdir "$tmpDir"
# file: playingWithAcl.zFLo/before
# owner: bob
# group: developers
user::rw-
group::---
other::---

# file: playingWithAcl.zFLo/
# owner: bob
# group: developers
user::rwx
user:www-data:rwx		effect of setfacl -m u:
group::---
mask::rwx
other::---
default:user::rwx
default:user:www-data:rwx	effect of setfacl -d -m u:
default:group::---		the other default: entries have been copied from the access ACL
default:mask::rwx
default:other::---

# file: playingWithAcl.zFLo/after
# owner: bob
# group: developers
user::rw-
user:www-data:rwx		#effective:rw-	effect of the default ACL. This also displays the effective permissions.
group::---
mask::rw-
other::---
Answer : nope, existing files are not affected when setting default ACL.

Will grandchildren inherit from a default ACL ?

tmpDir=$(mktemp -d baseDirectory.XXXX); otherUser='www-data'; mkdir -p "$tmpDir"
setfacl -m u:$otherUser:rwx "$tmpDir"
setfacl -d -m u:$otherUser:rwx "$tmpDir"
mkdir -p "$tmpDir/child_dir/grandchild_dir"
touch "$tmpDir/child_file"
touch "$tmpDir/child_dir/grandchild_file"
touch "$tmpDir/child_dir/grandchild_dir/grandgrandchild_file"
getfacl "$tmpDir/"{,child_file,child_dir,child_dir/grandchild_file,child_dir/grandchild_dir,child_dir/grandchild_dir/grandgrandchild_file}
[ -d "$tmpDir" ] && rm -r "$tmpDir"
# file: baseDirectory.uA7J/
# owner: matth
# group: matth
user::rwx
user:www-data:rwx				effect of setfacl -m u:
group::---
mask::rwx
other::---
default:user::rwx
default:user:www-data:rwx			effect of setfacl -d -m u:
default:group::---
default:mask::rwx
default:other::---

# file: baseDirectory.uA7J/child_file
# owner: matth
# group: matth
user::rw-
user:www-data:rwx	#effective:rw-	access ACL inherited from baseDirectory.
group::---
mask::rw-
other::---

# file: baseDirectory.uA7J/child_dir
# owner: matth
# group: matth
user::rwx
user:www-data:rwx				access ACL inherited from baseDirectory.
group::---
mask::rwx
other::---
default:user::rwx
default:user:www-data:rwx			default ACL inherited from baseDirectory.
default:group::---
default:mask::rwx
default:other::---

# file: baseDirectory.uA7J/child_dir/grandchild_file
# owner: matth
# group: matth
user::rw-
user:www-data:rwx	#effective:rw-	access ACL inherited from baseDirectory./child_dir
group::---
mask::rw-
other::---

# file: baseDirectory.uA7J/child_dir/grandchild_dir
# owner: matth
# group: matth
user::rwx
user:www-data:rwx				access ACL inherited from baseDirectory./child_dir
group::---
mask::rwx
other::---
default:user::rwx
default:user:www-data:rwx			default ACL inherited from baseDirectory./child_dir
default:group::---
default:mask::rwx
default:other::---

# file: baseDirectory.uA7J/child_dir/grandchild_dir/grandgrandchild_file
# owner: matth
# group: matth
user::rw-
user:www-data:rwx	#effective:rw-	access ACL inherited from baseDirectory./child_dir/grandchild_dir
group::---
mask::rw-
other::---
Once a default ACL is set (to a directory ), it's transmitted :
  • as an access ACL to sub-files
  • as a default ACL to sub-directories, which become a new "source" and are able to transmit it again to their sub-elements.
Answer : yes, grandchildren inherit from a default ACL.