Using ACLs to Protect ZFS Files
This chapter provides information about using access control lists (ACLs) to protect your ZFS files by providing more granular permissions than the standard UNIX permissions.
The following sections are provided in this chapter:
7.1. The NFSv4 ACL Model
Older versions of Solaris supported an ACL implementation that was primarily based on the POSIX-draft ACL specification. The POSIX-draft based ACLs are used to protect UFS files and are translated by versions of NFS prior to NFSv4.
With the introduction of NFSv4, a new ACL model fully supports the interoperability that NFSv4 offers between UNIX and non-UNIX clients. The new ACL implementation, as defined in the NFSv4 specification, provides much richer semantics that are based on NT-style ACLs.
The main differences of the new ACL model are as follows:
-
Based on the NFSv4 specification and similar to NT-style ACLs.
-
Provide much more granular set of access privileges. For more information, see ACL Access Privileges.
-
Set and displayed with the
chmod
andls
commands rather than thesetfacl
andgetfacl
commands. -
Provide richer inheritance semantics for designating how access privileges are applied from directory to subdirectories, and so on. For more information, see ACL Inheritance.
Both ACL models provide more fine-grained access control than is available with the standard file permissions. Much like POSIX-draft ACLs, the new ACLs are composed of multiple Access Control Entries (ACEs).
POSIX-draft style ACLs use a single entry to define what permissions
are allowed and what permissions are denied. The new ACL model has two types
of ACEs that affect access checking: ALLOW
and DENY
.
As such, you cannot infer from any single ACE that defines a set of permissions
whether or not the permissions that weren't defined in that ACE are allowed
or denied.
Translation between NFSv4-style ACLs and POSIX-draft ACLs is as follows:
-
If you use any ACL-aware utility, such as the
cp
,mv
,tar
,cpio
, orrcp
commands, to transfer UFS files with ACLs to a ZFS file system, the POSIX-draft ACLs are translated into the equivalent NFSv4-style ACLs. -
Some NFSv4-style ACLs are translated to POSIX-draft ACLs. You see a message similar to the following if an NFSv4–style ACL isn't translated to a POSIX-draft ACL:
# cp -p filea /var/tmp cp: failed to set acl entries on /var/tmp/filea
-
If you create a UFS
tar
orcpio
archive with the preserve ACL option (tar
-p
orcpio
-P
) on a system that runs a current Solaris release, you will lose the ACLs when the archive is extracted on a system that runs a previous Solaris release.All of the files are extracted with the correct file modes, but the ACL entries are ignored.
-
You can use the
ufsrestore
command to restore data into a ZFS file system, but the ACLs will be lost. -
If you attempt to set an NFSv4-style ACL on a UFS file, you see a message similar to the following:
chmod: ERROR: ACL type's are different
-
If you attempt to set a POSIX-style ACL on a ZFS file, you will see messages similar to the following:
# getfacl filea File system doesn't support aclent_t style ACL's. See acl(5) for more information on Solaris ACL support.
For information about other limitations with ACLs and backup products, see Saving ZFS Data With Other Backup Products.
7.1.1. Syntax Descriptions for Setting ACLs
Two basic ACL formats are provided as follows:
Syntax for Setting Trivial ACLs
chmod [options] A[index]{+|=}owner@ |group@ |everyone@:
access-permissions/...[:inheritance-flags]:deny | allow
file
chmod [options] A-owner@, group@, everyone@:
access-permissions/...[:inheritance-flags]:deny | allow
file ...
chmod [options] A[index]-
file
Syntax for Setting Non-Trivial ACLs
chmod [options] A[index]{+|=}user|group:name:
access-permissions/...[:inheritance-flags]:deny | allow
file
chmod [options] A-user|group:name:
access-permissions/...[:inheritance-flags]:deny | allow
file ...
chmod [options] A[index]-
file
- owner@, group@, everyone@
-
Identifies the ACL-entry-type for trivial ACL syntax. For a description of ACL-entry-types, see ACL Entry Types.
- user or group:ACL-entry-ID=username or groupname
-
Identifies the ACL-entry-type for explicit ACL syntax. The user and group ACL-entry-type must also contain the ACL-entry-ID, username or groupname. For a description of ACL-entry-types, see ACL Entry Types.
- access-permissions/.../
-
Identifies the access permissions that are granted or denied. For a description of ACL access privileges, see ACL Access Privileges.
- inheritance-flags
-
Identifies an optional list of ACL inheritance flags. For a description of the ACL inheritance flags, see ACL Inheritance Flags.
deny
|allow
-
Identifies whether the access permissions are granted or denied.
In the following example, the ACL-entry-ID value is not relevant:
group@:write_data/append_data/execute:deny
The following example includes an ACL-entry-ID because a specific user (ACL-entry-type) is included in the ACL.
0:user:gozer:list_directory/read_data/execute:allow
When an ACL entry is displayed, it looks similar to the following:
2:group@:write_data/append_data/execute:deny
The 2 or the index-ID designation in this example identifies the ACL entry in the larger ACL, which might
have multiple entries for owner, specific UIDs, group, and everyone. You can specify
the index-ID with the chmod
command to identify which part of the ACL you want to modify. For example, you can
identify index ID 3 as A3
to the chmod
command, similar to the following:
chmod A3=user:venkman:read_acl:allow filename
ACL entry types, which are the ACL representations of owner, group, and other, are described in the following table.
ACL Entry Type |
Description |
---|---|
|
Specifies the access granted to the owner of the object. |
|
Specifies the access granted to the owning group of the object. |
|
Specifies the access granted to any user or group that does not match any other ACL entry. |
|
With a user name, specifies the access granted to an additional user of the object. Must include the ACL-entry-ID, which contains a username or userID. If the value is not a valid numeric UID or username, the ACL entry type is invalid. |
|
With a group name, specifies the access granted to an additional group of the object. Must include the ACL-entry-ID, which contains a groupname or groupID. If the value is not a valid numeric GID or groupname, the ACL entry type is invalid. |
ACL access privileges are described in the following table.
Access Privilege |
Compact Access Privilege |
Description |
---|---|---|
add_file |
w |
Permission to add a new file to a directory. |
add_subdirectory |
p |
On a directory, permission to create a subdirectory. |
append_data |
p |
Placeholder. Not currently implemented. |
delete |
d |
Permission to delete a file. |
delete_child |
D |
Permission to delete a file or directory within a directory. |
execute |
x |
Permission to execute a file or search the contents of a directory. |
list_directory |
r |
Permission to list the contents of a directory. |
read_acl |
c |
Permission to read the ACL ( |
read_attributes |
a |
Permission to read basic attributes (non-ACLs) of a file. Think of basic attributes as the stat level attributes. Allowing this access mask bit means the entity can execute ls(1) and stat(2). |
read_data |
r |
Permission to read the contents of the file. |
read_xattr |
R |
Permission to read the extended attributes of a file or perform a lookup in the file's extended attributes directory. |
synchronize |
s |
Placeholder. Not currently implemented. |
write_xattr |
W |
Permission to create extended attributes or write to the extended attributes directory. Granting this permission to a user means that the user can create an extended attribute directory for a file. The attribute file's permissions control the user's access to the attribute. |
write_data |
w |
Permission to modify or replace the contents of a file. |
write_attributes |
A |
Permission to change the times associated with a file or directory to an arbitrary value. |
write_acl |
C |
Permission to write the ACL or the ability to modify the ACL by using the |
write_owner |
o |
Permission to change the file's owner or group. Or, the ability to execute the Permission to take ownership of a file or permission to change the group ownership
of the file to a group of which the user is a member. If you want to change the file
or group ownership to an arbitrary user or group, then the |
7.1.2. ACL Inheritance
The purpose of using ACL inheritance is so that a newly created file or directory can inherit the ACLs they are intended to inherit, but without disregarding the existing permission bits on the parent directory.
By default, ACLs are not propagated. If you set an non-trivial ACL on a directory, it is not inherited to any subsequent directory. You must specify the inheritance of an ACL on a file or directory.
The optional inheritance flags are described in the following table.
Inheritance Flag |
Compact Inheritance Flag |
Description |
---|---|---|
file_inherit |
f |
Only inherit the ACL from the parent directory to the directory's files. |
dir_inherit |
d |
Only inherit the ACL from the parent directory to the directory's subdirectories. |
inherit_only |
i |
Inherit the ACL from the parent directory but applies only to newly created files
or subdirectories and not the directory itself. This flag requires the |
no_propagate |
n |
Only inherit the ACL from the parent directory to the first-level contents of the
directory, not the second-level or subsequent contents. This flag requires the |
In addition, you can set a default ACL inheritance policy on the file system that
is more strict or less strict by using the aclinherit
file system property. For more information, see the next section.
7.1.3. ACL Property Modes
The ZFS file system includes two property modes related to ACLs:
-
aclinherit
– This property determines the behavior of ACL inheritance. Values include the following:-
discard
– For new objects, no ACL entries are inherited when a file or directory is created. The ACL on the file or directory is equal to the permission mode of the file or directory. -
noallow
– For new objects, only inheritable ACL entries that have an access type ofdeny
are inherited. -
secure
– For new objects, thewrite_owner
andwrite_acl
permissions are removed when an ACL entry is inherited. -
passthrough
– For new objects, the inheritable ACL entries are inherited with no changes made to them. This mode, in effect, disablessecure
mode.
The default mode for the
aclinherit
issecure
. -
-
aclmode
– This property modifies ACL behavior whenever a file or directory's mode is modified by thechmod
command or when a file is initially created. Values include the following:-
discard
– All ACL entries are removed except for the entries needed to define the mode of the file or directory. -
groupmask
– User or group ACL permissions are reduced so that they are no greater than the group permission bits, unless it is a user entry that has the same UID as the owner of the file or directory. Then, the ACL permissions are reduced so that they are no greater than owner permission bits. -
passthrough
– For new objects, the inheritable ACL entries are inherited with no changes made to the them.
The default mode for the
aclmode
property isgroupmask
. -
7.2. Setting ACLs on ZFS Files
As implemented with ZFS, ACLs are composed of an array of ACL entries.
ZFS provides a pure ACL model, where all files have
an ACL. Typically, the ACL is trivial in that it only
represents the traditional UNIX owner/group/other
entries.
ZFS files still have permission bits and a mode, but these values are more of a cache of what the ACL represents. As such, if you change the permissions of the file, the file's ACL is updated accordingly. In addition, if you remove an non-trivial ACL that granted a user access to a file or directory, that user could still have access to the file or directory because of the file or directory's permission bits that grant access to group or everyone. All access control decisions are governed by the permissions represented in a file or directory's ACL.
The primary rules of ACL access on a ZFS file are as follows:
-
ZFS processes ACL entries in the order they are listed in the ACL, from the top down.
-
Only ACL entries that have a “who” that matches the requester of the access are processed.
-
Once an allow permission has been granted, it cannot be denied by a subsequent ACL deny entry in the same ACL permission set.
-
The owner of the file is granted the
write_acl
permission unconditionally, even if the permission is explicitly denied. Otherwise, any permission left unspecified is denied.In the cases of deny permissions or when an access permission is missing, the privilege subsystem determines what access request is granted for the owner of the file or for superuser. This mechanism prevents owners of files from getting locked out of their files and enables superuser to modify files for recovery purposes.
If you set an non-trivial ACL on a directory, the ACL is not automatically inherited by the directory's children. If you set an non-trivial ACL and you want it inherited to the directory's children, you have to use the ACL inheritance flags. For more information, see ACL Inheritance Flags and Setting ACL Inheritance on ZFS Files in Verbose Format.
When you create a new file and depending on the umask
value, a default trivial ACL, similar to the following, is applied:
$ ls -v file.1 -r--r--r-- 1 root root 206663 May 4 11:52 file.1 0:owner@:write_data/append_data/execute:deny 1:owner@:read_data/write_xattr/write_attributes/write_acl/write_owner :allow 2:group@:write_data/append_data/execute:deny 3:group@:read_data:allow 4:everyone@:write_data/append_data/write_xattr/execute/write_attributes /write_acl/write_owner:deny 5:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize :allow
Note that each user category (owner@
, group@
, everyone@
) in this example has two ACL entries. One entry for deny
permissions, and one entry is for allow
permissions.
A description of this file ACL is as follows:
0:owner@
-
The owner is denied execute permissions to the file (
execute:deny
). 1:owner@
-
The owner can read and modify the contents of the file (
read_data/write_data/append_data
). The owner can also modify the file's attributes such as timestamps, extended attributes, and ACLs (write_xattr/write_attributes /write_acl
). In addition, the owner can modify the ownership of the file (write_owner:allow
) 2:group@
-
The group is denied modify and execute permissions to the file (
write_data/append_data/execute:deny
). 3:group@
-
The group is granted read permissions to the file (
read_data:allow
). 4:everyone@
-
Everyone who is not user or group is denied permission to execute or modify the contents of the file and to modify any attributes of the file (
write_data/append_data/write_xattr/execute/write_attributes/write_acl/write_owner:deny
). 5:everyone@
-
Everyone who is not user or group is granted read permissions to the file, and the file's attributes (
read_data/read_xattr/read_attributes/read_acl/synchronize:allow
). Thesynchronize
access permission is not currently implemented.
When a new directory is created and depending on the umask
value, a default directory ACL is similar to the following:
$ ls -dv dir.1 drwxr-xr-x 2 root root 2 Feb 23 10:37 dir.1 0:owner@::deny 1:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 2:group@:add_file/write_data/add_subdirectory/append_data:deny 3:group@:list_directory/read_data/execute:allow 4:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 5:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
A description of this directory ACL is as follows:
0:owner@
-
The owner deny list is empty for the directory (
::deny
). 1:owner@
-
The owner can read and modify the directory contents (
list_directory/read_data/add_file/write_data/add_subdirectory/append_data
), search the contents (execute
), and modify the file's attributes such as timestamps, extended attributes, and ACLs (write_xattr/write_attributes/write_acl
). In addition, the owner can modify the ownership of the directory (write_owner:allow
). 2:group@
-
The group cannot add to or modify the directory contents (
add_file/write_data/add_subdirectory/append_data:deny
). 3:group@
-
The group can list and read the directory contents. In addition, the group has execute permission to search the directory contents (
list_directory/read_data/execute:allow
). 4:everyone@
-
Everyone who is not user or group is denied permission to add to or modify the contents of the directory (
add_file/write_data/add_subdirectory/append_data
). In addition, the permission to modify any attributes of the directory is denied. (write_xattr /write_attributes/write_acl/write_owner:deny
). 5:everyone@
-
Everyone who is not user or group is granted read and execute permissions to the directory contents and the directory's attributes (
list_directory/read_data/read_xattr/execute/read_attributes/read_acl/synchronize:allow
). Thesynchronize
access permission is not currently implemented.
7.3. Setting and Displaying ACLs on ZFS Files in Verbose Format
You can use the chmod
command to modify ACLs on ZFS files. The following chmod
syntax for modifying ACLs uses acl-specification to identify the format of the ACL. For a description of acl-specification, see Syntax Descriptions for Setting ACLs.
-
Adding ACL entries
-
Adding an ACL entry for a user
% chmod A+acl-specification filename
-
Adding an ACL entry by index-ID
% chmod Aindex-ID+acl-specification filename
This syntax inserts the new ACL entry at the specified index-ID location.
-
-
Replacing an ACL entry
% chmod Aindex-ID=acl-specification filename
% chmod A=acl-specification filename
-
Removing ACL entries
-
Removing an ACL entry by index-ID
% chmod Aindex-ID- filename
-
Removing an ACL entry by user
% chmod A-acl-specification filename
-
Removing all non-trivial ACEs from a file
% chmod A- filename
-
Verbose ACL information is displayed by using the ls
-v
command. For example:
# ls -v file.1 -rw-r--r-- 1 root root 206663 Feb 16 11:00 file.1 0:owner@:execute:deny 1:owner@:read_data/write_data/append_data/write_xattr/write_attributes /write_acl/write_owner:allow 2:group@:write_data/append_data/execute:deny 3:group@:read_data:allow 4:everyone@:write_data/append_data/write_xattr/execute/write_attributes /write_acl/write_owner:deny 5:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize :allow
For information about using the compact ACL format, see Setting and Displaying ACLs on ZFS Files in Compact Format.
This section provides examples of setting and displaying trivial ACLs.
In the following example, a trivial ACL exists on file.1:
# ls -v file.1 -rw-r--r-- 1 root root 206663 Feb 16 11:00 file.1 0:owner@:execute:deny 1:owner@:read_data/write_data/append_data/write_xattr/write_attributes /write_acl/write_owner:allow 2:group@:write_data/append_data/execute:deny 3:group@:read_data:allow 4:everyone@:write_data/append_data/write_xattr/execute/write_attributes /write_acl/write_owner:deny 5:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize :allow
In the following example, write_data
permissions are granted for group@
.
# chmod A2=group@:append_data/execute:deny file.1 # chmod A3=group@:read_data/write_data:allow file.1 # ls -v file.1 -rw-rw-r-- 1 root root 206663 May 3 16:36 file.1 0:owner@:execute:deny 1:owner@:read_data/write_data/append_data/write_xattr/write_attributes /write_acl/write_owner:allow 2:group@:append_data/execute:deny 3:group@:read_data/write_data:allow 4:everyone@:write_data/append_data/write_xattr/execute/write_attributes /write_acl/write_owner:deny 5:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize :allow
In the following example, permissions on file.1 are set back to 644.
# chmod 644 file.1 # ls -v file.1 -rw-r--r-- 1 root root 206663 May 3 16:36 file.1 0:owner@:execute:deny 1:owner@:read_data/write_data/append_data/write_xattr/write_attributes /write_acl/write_owner:allow 2:group@:write_data/append_data/execute:deny 3:group@:read_data:allow 4:everyone@:write_data/append_data/write_xattr/execute/write_attributes /write_acl/write_owner:deny 5:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize :allow
This section provides examples of setting and displaying non-trivial ACLs.
In the following example, read_data/execute
permissions are added for the user gozer
on the test.dir directory.
# chmod A+user:gozer:read_data/execute:allow test.dir # ls -dv test.dir drwxr-xr-x+ 2 root root 2 Feb 16 11:12 test.dir 0:user:gozer:list_directory/read_data/execute:allow 1:owner@::deny 2:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 3:group@:add_file/write_data/add_subdirectory/append_data:deny 4:group@:list_directory/read_data/execute:allow 5:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 6:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
In the following example, read_data/execute
permissions are removed for user gozer
.
# chmod A0- test.dir # ls -dv test.dir drwxr-xr-x 2 root root 2 Feb 16 11:12 test.dir 0:owner@::deny 1:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 2:group@:add_file/write_data/add_subdirectory/append_data:deny 3:group@:list_directory/read_data/execute:allow 4:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 5:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
These ACL examples illustrate the interaction between setting ACLs and then changing the file or directory's permission bits.
In the following example, a trivial ACL exists on file.2:
# ls -v file.2 -rw-r--r-- 1 root root 2703 Feb 16 11:16 file.2 0:owner@:execute:deny 1:owner@:read_data/write_data/append_data/write_xattr/write_attributes /write_acl/write_owner:allow 2:group@:write_data/append_data/execute:deny 3:group@:read_data:allow 4:everyone@:write_data/append_data/write_xattr/execute/write_attributes /write_acl/write_owner:deny 5:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize :allow
In the following example, ACL allow permissions are removed from everyone@
.
# chmod A5- file.2 # ls -v file.2 -rw-r----- 1 root root 2703 Feb 16 11:16 file.2 0:owner@:execute:deny 1:owner@:read_data/write_data/append_data/write_xattr/write_attributes /write_acl/write_owner:allow 2:group@:write_data/append_data/execute:deny 3:group@:read_data:allow 4:everyone@:write_data/append_data/write_xattr/execute/write_attributes /write_acl/write_owner:deny
In this output, the file's permission bits are reset from 655 to 650. Read permissions
for everyone@
have been effectively removed from the file's permissions bits when the ACL allow
permissions are removed for everyone@
.
In the following example, the existing ACL is replaced with read_data/write_data
permissions for everyone@
.
# chmod A=everyone@:read_data/write_data:allow file.3 # ls -v file.3 -rw-rw-rw-+ 1 root root 1532 Feb 16 11:18 file.3 0:everyone@:read_data/write_data:allow
In this output, the chmod
syntax effectively replaces
the existing ACL with read_data/write_data:allow
permissions
to read/write permissions for owner, group, and everyone@
.
In this model, everyone@
specifies access to any user or
group. Since no owner@
or group@
ACL
entry exists to override the permissions for owner and group, the permission
bits are set to 666.
In the following example, the existing ACL is replaced with read permissions for user
gozer
.
# chmod A=user:gozer:read_data:allow file.3 # ls -v file.3 ----------+ 1 root root 1532 Feb 16 11:18 file.3 0:user:gozer:read_data:allow
In this output, the file permissions are computed to be 000 because
no ACL entries exist for owner@
, group@
,
or everyone@
, which represent the traditional permission
components of a file. The owner of the file can resolve this problem by resetting
the permissions (and the ACL) as follows:
# chmod 655 file.3 # ls -v file.3 -rw-r-xr-x+ 1 root root 0 Mar 8 13:24 file.3 0:user:gozer::deny 1:user:gozer:read_data:allow 2:owner@:execute:deny 3:owner@:read_data/write_data/append_data/write_xattr/write_attributes /write_acl/write_owner:allow 4:group@:write_data/append_data:deny 5:group@:read_data/execute:allow 6:everyone@:write_data/append_data/write_xattr/write_attributes /write_acl/write_owner:deny 7:everyone@:read_data/read_xattr/execute/read_attributes/read_acl /synchronize:allow
You can use the chmod
command to remove all non-trivial ACLs on a file or directory.
In the following example, 2 non-trivial ACEs exist on test5.dir
.
# ls -dv test5.dir drwxr-xr-x+ 2 root root 2 Feb 16 11:23 test5.dir 0:user:gozer:read_data:file_inherit:deny 1:user:lp:read_data:file_inherit:deny 2:owner@::deny 3:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 4:group@:add_file/write_data/add_subdirectory/append_data:deny 5:group@:list_directory/read_data/execute:allow 6:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 7:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
In the following example, the non-trivial ACLs for users gozer
and lp
are removed. The remaining ACL contains the six default values for owner@
, group@
, and everyone@
.
# chmod A- test5.dir # ls -dv test5.dir drwxr-xr-x 2 root root 2 Feb 16 11:23 test5.dir 0:owner@::deny 1:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 2:group@:add_file/write_data/add_subdirectory/append_data:deny 3:group@:list_directory/read_data/execute:allow 4:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 5:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
7.3.1. Setting ACL Inheritance on ZFS Files in Verbose Format
You can determine how ACLs are inherited or not inherited on files and directories. By default, ACLs are not propagated. If you set an non-trivial ACL on a directory, the ACL is not inherited by any subsequent directory. You must specify the inheritance of an ACL on a file or directory.
In addition, two ACL properties are provided that can be set globally
on file systems: aclinherit
and aclmode
.
By default, aclinherit
is set to secure
and aclmode
is set to groupmask
.
For more information, see ACL Inheritance.
By default, ACLs are not propagated through a directory structure.
In the following example, an non-trivial ACE of read_data/write_data/execute
is applied for user gozer
on test.dir
.
# chmod A+user:gozer:read_data/write_data/execute:allow test.dir # ls -dv test.dir drwxr-xr-x+ 2 root root 2 Feb 17 14:45 test.dir 0:user:gozer:list_directory/read_data/add_file/write_data/execute:allow 1:owner@::deny 2:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 3:group@:add_file/write_data/add_subdirectory/append_data:deny 4:group@:list_directory/read_data/execute:allow 5:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 6:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
If a test.dir subdirectory is created, the ACE
for user gozer
is not propagated. User gozer
would
only have access to sub.dir if the permissions on sub.dir granted him access as the file owner, group member, or everyone@
.
# mkdir test.dir/sub.dir # ls -dv test.dir/sub.dir drwxr-xr-x 2 root root 2 Feb 17 14:46 test.dir/sub.dir 0:owner@::deny 1:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 2:group@:add_file/write_data/add_subdirectory/append_data:deny 3:group@:list_directory/read_data/execute:allow 4:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 5:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
This series of examples identify the file and directory ACEs that are
applied when the file_inherit
flag is set.
In the following example, read_data/write_data
permissions
are added for files in the test.dir directory for user gozer
so that he has read access on any newly created files.
# chmod A+user:gozer:read_data/write_data:file_inherit:allow test2.dir # ls -dv test2.dir drwxr-xr-x+ 2 root root 2 Feb 17 14:47 test2.dir 0:user:gozer:read_data/write_data:file_inherit:allow 1:owner@::deny 2:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 3:group@:add_file/write_data/add_subdirectory/append_data:deny 4:group@:list_directory/read_data/execute:allow 5:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 6:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
In the following example, user gozer's permissions are applied on the
newly created test2.dir/file.2 file. The ACL inheritance
granted, read_data:file_inherit:allow, means user gozer
can read the contents of any newly created file.
# touch test2.dir/file.2 # ls -v test2.dir/file.2 -rw-r--r--+ 1 root root 0 Feb 17 14:49 test2.dir/file.2 0:user:gozer:write_data:deny 1:user:gozer:read_data/write_data:allow 2:owner@:execute:deny 3:owner@:read_data/write_data/append_data/write_xattr/write_attributes+ /write_acl/write_owner:allow 4:group@:write_data/append_data/execute:deny 5:group@:read_data:allow 6:everyone@:write_data/append_data/write_xattr/execute/write_attributes /write_acl/write_owner:deny 7:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize :allow
Because the aclmode
for this file is set to the
default mode, groupmask
, user gozer
does
not have write_data
permission on file.2 because
the group permission of the file does not allow it.
Note the inherit_only
permission, which is applied
when the file_inherit
or dir_inherit
flags
are set, is used to propagate the ACL through the directory structure. As
such, user gozer
is only granted or denied permission from everyone@
permissions unless he is the owner of the file or a member
of the owning group of the file. For example:
# mkdir test2.dir/subdir.2 # ls -dv test2.dir/subdir.2 drwxr-xr-x+ 2 root root 2 Feb 17 14:50 test2.dir/subdir.2 0:user:gozer:list_directory/read_data/add_file/write_data:file_inherit /inherit_only:allow 1:owner@::deny 2:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 3:group@:add_file/write_data/add_subdirectory/append_data:deny 4:group@:list_directory/read_data/execute:allow 5:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 6:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
The following series of examples identify the file and directory ACLs
that are applied when both the file_inherit
and dir_inherit
flags are set.
In the following example, user gozer
is granted read,
write, and execute permissions that are inherited for newly created files
and directories.
# chmod A+user:gozer:read_data/write_data/execute:file_inherit/dir_inherit:allow test3.dir # ls -dv test3.dir drwxr-xr-x+ 2 root root 2 Feb 17 14:51 test3.dir 0:user:gozer:list_directory/read_data/add_file/write_data/execute :file_inherit/dir_inherit:allow 1:owner@::deny 2:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 3:group@:add_file/write_data/add_subdirectory/append_data:deny 4:group@:list_directory/read_data/execute:allow 5:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 6:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
# touch test3.dir/file.3 # ls -v test3.dir/file.3 -rw-r--r--+ 1 root root 0 Feb 17 14:53 test3.dir/file.3 0:user:gozer:write_data/execute:deny 1:user:gozer:read_data/write_data/execute:allow 2:owner@:execute:deny 3:owner@:read_data/write_data/append_data/write_xattr/write_attributes /write_acl/write_owner:allow 4:group@:write_data/append_data/execute:deny 5:group@:read_data:allow 6:everyone@:write_data/append_data/write_xattr/execute/write_attributes /write_acl/write_owner:deny 7:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize :allow
# mkdir test3.dir/subdir.1 # ls -dv test3.dir/subdir.1 drwxr-xr-x+ 2 root root 2 May 4 15:00 test3.dir/subdir.1 0:user:gozer:list_directory/read_data/add_file/write_data/execute :file_inherit/dir_inherit/inherit_only:allow 1:user:gozer:add_file/write_data:deny 2:user:gozer:list_directory/read_data/add_file/write_data/execute:allow 3:owner@::deny 4:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 5:group@:add_file/write_data/add_subdirectory/append_data:deny 6:group@:list_directory/read_data/execute:allow 7:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 8:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
In these examples, because the permission bits of the parent directory
for group@
and everyone@
deny write
and execute permissions, user gozer
is denied write and
execute permissions. The default aclmode
property is secure
, which means that write_data
and execute
permissions are not inherited.
In the following example, user gozer
is granted
read, write, and execute permissions that are inherited for newly created
files, but are not propagated to subsequent contents of the directory.
# chmod A+user:gozer:read_data/write_data/execute:file_inherit/no_propagate:allow test4.dir # ls -dv test4.dir drwxr-xr-x+ 2 root root 2 Feb 17 14:54 test4.dir 0:user:gozer:list_directory/read_data/add_file/write_data/execute :file_inherit/no_propagate:allow 1:owner@::deny 2:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 3:group@:add_file/write_data/add_subdirectory/append_data:deny 4:group@:list_directory/read_data/execute:allow 5:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 6:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
As the following example illustrates, when a new subdirectory is created,
user gozer
's read_data/write_data/execute
permission
for files are not propagated to the new sub4.dir
directory.
# mkdir test4.dir/sub4.dir # ls -dv test4.dir/sub4.dir drwxr-xr-x 2 root root 2 Feb 17 14:57 test4.dir/sub4.dir 0:owner@::deny 1:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 2:group@:add_file/write_data/add_subdirectory/append_data:deny 3:group@:list_directory/read_data/execute:allow 4:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 5:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
As the following example illustrates, gozer
's read_data/write_data/execute
permission for files is propagated to the newly created file.
# touch test4.dir/file.4 # ls -v test4.dir/file.4 -rw-r--r--+ 1 root root 0 May 4 15:02 test4.dir/file.4 0:user:gozer:write_data/execute:deny 1:user:gozer:read_data/write_data/execute:allow 2:owner@:execute:deny 3:owner@:read_data/write_data/append_data/write_xattr/write_attributes /write_acl/write_owner:allow 4:group@:write_data/append_data/execute:deny 5:group@:read_data:allow 6:everyone@:write_data/append_data/write_xattr/execute/write_attributes /write_acl/write_owner:deny 7:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize :allow
If the aclmode
property on the tank/cindy file
system is set to passthrough
, then user gozer
would
inherit the ACL applied on test4.dir for the newly created file.4 as follows:
# zfs set aclmode=passthrough tank/cindy # touch test4.dir/file.4 # ls -v test4.dir/file.4 -rw-r--r--+ 1 root root 0 Feb 17 15:15 test4.dir/file.4 0:user:gozer:read_data/write_data/execute:allow 1:owner@:execute:deny 2:owner@:read_data/write_data/append_data/write_xattr/write_attributes /write_acl/write_owner:allow 3:group@:write_data/append_data/execute:deny 4:group@:read_data:allow 5:everyone@:write_data/append_data/write_xattr/execute/write_attributes /write_acl/write_owner:deny 6:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize :allow
This output illustrates that the read_data/write_data/execute:allow:file_inherit/dir_inherit
ACL that was set on the parent directory, test4.dir,
is passed through to user gozer
.
If the aclmode
property on a file system is set
to discard
, then ACLs can potentially be discarded when
the permission bits on a directory change. For example:
# zfs set aclmode=discard tank/cindy # chmod A+user:gozer:read_data/write_data/execute:dir_inherit:allow test5.dir # ls -dv test5.dir drwxr-xr-x+ 2 root root 2 Feb 16 11:23 test5.dir 0:user:gozer:list_directory/read_data/add_file/write_data/execute :dir_inherit:allow 1:owner@::deny 2:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 3:group@:add_file/write_data/add_subdirectory/append_data:deny 4:group@:list_directory/read_data/execute:allow 5:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 6:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
If, at a later time, you decide to tighten the permission bits on a directory, the non-trivial ACL is discarded. For example:
# chmod 744 test5.dir # ls -dv test5.dir drwxr--r-- 2 root root 2 Feb 16 11:23 test5.dir 0:owner@::deny 1:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 2:group@:add_file/write_data/add_subdirectory/append_data/execute:deny 3:group@:list_directory/read_data:allow 4:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /execute/write_attributes/write_acl/write_owner:deny 5:everyone@:list_directory/read_data/read_xattr/read_attributes/read_acl /synchronize:allow
In the following example, two non-trivial ACLs with file inheritance
are set. One ACL allows read_data
permission, and one ACL
denies read_data
permission. This example also illustrates
how you can specify two ACEs in the same chmod
command.
# zfs set aclinherit=nonallow tank/cindy # chmod A+user:gozer:read_data:file_inherit:deny,user:lp:read_data:file_inherit:allow test6.dir # ls -dv test6.dir drwxr-xr-x+ 2 root root 2 May 4 14:23 test6.dir 0:user:gozer:read_data:file_inherit:deny 1:user:lp:read_data:file_inherit:allow 2:owner@::deny 3:owner@:list_directory/read_data/add_file/write_data/add_subdirectory /append_data/write_xattr/execute/write_attributes/write_acl /write_owner:allow 4:group@:add_file/write_data/add_subdirectory/append_data:deny 5:group@:list_directory/read_data/execute:allow 6:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr /write_attributes/write_acl/write_owner:deny 7:everyone@:list_directory/read_data/read_xattr/execute/read_attributes /read_acl/synchronize:allow
As the following example shows, when a new file is created, the ACL
that allows read_data
permission is discarded.
# touch test6.dir/file.6 # ls -v test6.dir/file.6 -rw-r--r--+ 1 root root 0 May 4 13:44 test6.dir/file.6 0:user:gozer:read_data:deny 1:owner@:execute:deny 2:owner@:read_data/write_data/append_data/write_xattr/write_attributes /write_acl/write_owner:allow 3:group@:write_data/append_data/execute:deny 4:group@:read_data:allow 5:everyone@:write_data/append_data/write_xattr/execute/write_attributes /write_acl/write_owner:deny 6:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize :allow
7.4. Setting and Displaying ACLs on ZFS Files in Compact Format
You can set and display permissions on ZFS files in a compact format that uses 14 unique letters to represent the permissions. The letters that represent the compact permissions are listed in ACL Access Privileges and ACL Inheritance Flags.
You can display compact ACL listings for files and directories by using
the ls
-V
command. For example:
# ls -V file.1 -rw-r--r-- 1 root root 206663 Feb 16 11:00 file.1 owner@:--x-----------:------:deny owner@:rw-p---A-W-Co-:------:allow group@:-wxp----------:------:deny group@:r-------------:------:allow everyone@:-wxp---A-W-Co-:------:deny everyone@:r-----a-R-c--s:------:allow
The compact ACL output is described as follows:
owner@
-
The owner is denied execute permissions to the file (
x
=execute
). owner@
-
The owner can read and modify the contents of the file (
rw
=read_data/write_data
), (p
=append_data
). The owner can also modify the file's attributes such as timestamps, extended attributes, and ACLs (A
=write_xattr
,W
=write_attributes
,C
=write_acl
). In addition, the owner can modify the ownership of the file (O
=write_owner
). group@
-
The group is denied modify and execute permissions to the file (
rw
=read_data/write_data
,p
=append_data
, andx
=execute
). group@
-
The group is granted read permissions to the file (
r
=read_data
). everyone@
-
Everyone who is not user or group is denied permission to execute or modify the contents of the file, and to modify any attributes of the file (
w
=write_data
,x
=execute
,p
=append_data
,A
=write_xattr
,W
=write_attributes
,C
=write_acl
, ando
=write_owner
). everyone@
-
Everyone who is not user or group is granted read permissions to the file and the file's attributes (
r
=read_data
,a
=append_data
,R
=read_xattr
,c
=read_acl
, ands
=synchronize
). Thesynchronize
access permission is not currently implemented.
Compact ACL format provides the following advantages over verbose ACL format:
-
Permissions can be specified as positional arguments to the
chmod
command. -
The hyphen (-) characters, which identify no permissions, can be removed and only the required letters need to be specified.
-
Both permissions and inheritance flags are set in the same fashion.
For information about using the verbose ACL format, see Setting and Displaying ACLs on ZFS Files in Verbose Format.
In the following example, a trivial ACL exists on file.1:
# ls -V file.1 -rw-r-xr-x 1 root root 206663 Feb 16 11:00 file.1 owner@:--x-----------:------:deny owner@:rw-p---A-W-Co-:------:allow group@:-w-p----------:------:deny group@:r-x-----------:------:allow everyone@:-w-p---A-W-Co-:------:deny everyone@:r-x---a-R-c--s:------:allow
In this example, read_data/execute permissions are added for the user gozer
on file.1.
# chmod A+user:gozer:rx:allow file.1 # ls -V file.1 -rw-r-xr-x+ 1 root root 206663 Feb 16 11:00 file.1 user:gozer:r-x-----------:------:allow owner@:--x-----------:------:deny owner@:rw-p---A-W-Co-:------:allow group@:-w-p----------:------:deny group@:r-x-----------:------:allow everyone@:-w-p---A-W-Co-:------:deny everyone@:r-x---a-R-c--s:------:allow
Another way to add the same permissions for user gozer
is
to insert a new ACL at a specific position, 4, for example. As such, the existing
ACLs at positions 4–6 are pushed down. For example:
# chmod A4+user:gozer:rx:allow file.1 # ls -V file.1 -rw-r-xr-x+ 1 root root 206663 Feb 16 11:00 file.1 owner@:--x-----------:------:deny owner@:rw-p---A-W-Co-:------:allow group@:-w-p----------:------:deny group@:r-x-----------:------:allow user:gozer:r-x-----------:------:allow everyone@:-w-p---A-W-Co-:------:deny everyone@:r-x---a-R-c--s:------:allow
In the following example, user gozer
is granted read,
write, and execute permissions that are inherited for newly created files
and directories by using the compact ACL format.
# chmod A+user:gozer:rwx:fd:allow dir.2 # ls -dV dir.2 drwxr-xr-x+ 2 root root 2 Aug 28 13:21 dir.2 user:gozer:rwx-----------:fd----:allow owner@:--------------:------:deny owner@:rwxp---A-W-Co-:------:allow group@:-w-p----------:------:deny group@:r-x-----------:------:allow everyone@:-w-p---A-W-Co-:------:deny everyone@:r-x---a-R-c--s:------:allow
You can also cut and paste permissions and inheritance flags from the ls
-V
output into the compact chmod
format.
For example, to duplicate the permissions and inheritance flags on dir.1 for user gozer
to user cindys
,
copy and paste the permission and inheritance flags (rwx-----------:f-----:allow
) into your chmod
command. For example:
# chmod A+user:cindys:rwx-----------:fd----:allow dir.2 # ls -dv dir.2 drwxr-xr-x+ 2 root root 2 Aug 28 14:12 dir.2 user:cindys:rwx-----------:fd----:allow user:gozer:rwx-----------:fd----:allow owner@:--------------:------:deny owner@:rwxp---A-W-Co-:------:allow group@:-w-p----------:------:deny group@:r-x-----------:------:allow everyone@:-w-p---A-W-Co-:------:deny everyone@:r-x---a-R-c--s:------:allow