This chapter provides information about using access control lists (ACLs) to protect your ZFS files. ACLs provide more granular permissions than the standard UNIX permissions.
The following sections are provided in this chapter:
Previous versions of the Solaris OS 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 follow:
The new ACL model is based on the NFSv4 specification and is similar to NT-style ACLs.
The new model provides a much more granular set of access privileges. For more information, see Table 8–2.
ACLs are set and displayed with the chmod and ls commands rather than the setfacl and getfacl commands.
The new model provides richer inheritance semantics for designating how access privileges are applied from a 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 based ACLs use a single entry to define which permissions are allowed and which 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 the permissions that weren't defined in that ACE are allowed or denied.
Translation between NFSv4 ACLs and POSIX-draft ACLs is as follows:
If you use an ACL-aware utility, such as the cp, mv, tar, cpio, or rcp command, to transfer UFS files with ACLs to a ZFS file system, the POSIX-draft ACLs are translated into the equivalent NFSv4 ACLs.
Some NFSv4 ACLs are translated into POSIX-draft ACLs. You see a message similar to the following if an NFSv4 ACL isn't translated into 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 or cpio archive with the preserve ACL option (tar -p or cpio -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. If the original data includes POSIX-draft ACLs, they are translated into to NFSv4 ACLs.
If you attempt to set an NFSv4 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-draft ACL on a ZFS file, you 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.
Syntax for Setting Trivial ACLs
An ACL is trivial in that it only represents the traditional UNIX owner/group/other entries.
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
Identifies the ACL-entry-type for trivial ACL syntax. For a description of ACL entry types, see Table 8–1.
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 Table 8–1.
Identifies the access permissions that are granted or denied. For a description of ACL access privileges, see Table 8–2.
Identifies an optional list of ACL inheritance flags. For a description of the ACL inheritance flags, see Table 8–3.
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 |
In this example, the 2, known as the index-ID designation, 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 in the chmod command syntax, 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.
Table 8–1 ACL Entry Types
ACL Entry Type |
Description |
---|---|
owner@ |
Specifies the access granted to the owner of the object. |
group@ |
Specifies the access granted to the owning group of the object. |
everyone@ |
Specifies the access granted to any user or group that does not match any other ACL entry. |
user |
With a user name, specifies the access granted to an additional user of the object. This entry 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. |
group |
With a group name, specifies the access granted to an additional group of the object. This entry 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.
Table 8–2 ACL Access Privileges
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 a 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 (ls). |
read_attributes |
a |
Permission to read the basic attributes (non-ACLs) of a file. Think of basic attributes as the stat-level attributes. Allowing this access mask bit means that the entity can execute ls(1) and stat(2). |
read_data |
r |
Permission to read the contents of a file. |
read_xattr |
R |
Permission to read the extended attributes of a file or to 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 time stamps associated with a file or directory to an arbitrary value. |
write_acl |
C |
Permission to write the ACL or to modify the ACL by using the chmod command. |
write_owner |
o |
Permission to change the file's owner or group. Or, the ability to execute the chown or chgrp command on the file. Permission to take ownership of a file or permission to change the group ownership of a 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 PRIV_FILE_CHOWN privilege is required. |
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 permissions on the parent directory.
By default, ACLs are not propagated. If you set a non-trivial ACL on a directory, it is not inherited by 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.
Table 8–3 ACL Inheritance Flags
Inheritance Flag |
Compact Inheritance Flag |
Description |
---|---|---|
file_inherit |
f |
Inherit the ACL from the parent directory but only applies to the directory's files. |
dir_inherit |
d |
Inherit the ACL from the parent directory but only applies 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 file_inherit flag, the dir_inherit flag, or both, to indicate what to inherit. |
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 file_inherit flag, the dir_inherit flag, or both, to indicate what to inherit. |
- |
N/A |
No permission granted. |
In addition, you can set a default ACL inheritance policy on a file system that is more strict or less strict by using the aclinherit file system property. For more information, see the next section.
A ZFS file system has two properties 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 new file or directory is equal to the permissions of the file or directory.
noallow – For new objects, only inheritable ACL entries that have an access type of deny are inherited.
restricted – For new objects, the write_owner and write_acl permissions are removed when an ACL entry is inherited.
passthrough – When the property value is set to passthrough, files are created with permissions determined by the inheritable ACEs. If no inheritable ACEs exist that affect the permissions, then the permissions are set in accordance to the requested permissions from the application.
passthrough-x – This property value has the same semantics as passthrough, except that when passthrough-x is enabled, files are created with the execute (x) permission, but only if the execute permission is set in the file creation mode and in an inheritable ACE that affects the mode.
The default value for the aclinherit property is restricted.
aclmode – This property modifies ACL behavior when a file is initially created or whenever a file or directory's permissions are modified by the chmod command. 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 permissions, 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 the owner permissions.
passthrough – During a chmod operation, ACEs other than owner@, group@, or everyone@ are not modified in any way. ACEs with owner@, group@, or everyone@ are disabled to set the file mode as requested by the chmod operation.
The default value for the aclmode property is groupmask.
As implemented with ZFS, ACLs are composed 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.
If you change the permissions of the file, a file's ACL is updated accordingly. In addition, if you remove a 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 a group or to 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 follow:
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.
After 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 a file is granted the write_acl permission unconditionally, even if the permission is explicitly denied. Otherwise, any permission left unspecified is denied.
In cases of deny permissions or when an access permission for a file 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 a non-trivial ACL on a directory, the ACL is not automatically inherited by the directory's children. If you set a non-trivial ACL and you want it to be inherited by the directory's children, you have to use the ACL inheritance flags. For more information, see Table 8–3 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 -rw-r--r-- 1 root root 206663 May 20 14:09 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 |
Note that each user category (owner@, group@, everyone@) has two ACL entries in this example. One entry is for deny permissions, and one entry is for allow permissions.
A description of this file ACL follows:
The owner is denied execute permission on the file (execute:deny).
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 time stamps, extended attributes, and ACLs (write_xattr/write_attributes /write_acl). In addition, the owner can modify the ownership of the file (write_owner:allow).
The group is denied modify and execute permissions on the file (write_data/append_data/execute:deny).
The group is granted read permissions to the file (read_data:allow).
Everyone who is not the owner of the file or a member of the owning group of the file 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).
Everyone who is not the owner of the file or a member of the owning group of the file is granted read permissions on the file and the file's attributes (read_data/read_xattr/read_attributes/read_acl/synchronize:allow). The synchronize access permission is not currently implemented.
When you create a new directory and depending on the umask value, a default directory ACL, similar to the following is applied:
$ ls -dv dir.1 drwxr-xr-x 2 root root 2 May 20 14:11 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 follows:
The owner deny list is empty for the directory (::deny).
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 directory's attributes such as time stamps, extended attributes, and ACLs (write_xattr/write_attributes/write_acl). In addition, the owner can modify the ownership of the directory (write_owner:allow).
The group cannot add to or modify the directory contents (add_file/write_data/add_subdirectory/append_data:deny).
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).
Everyone who is not the owner of the file or a member of the owning group of the file 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).
Everyone who is not the owner of the file or a member of the owning group of the file is granted read and execute permissions on the directory contents and the directory's attributes (list_directory/read_data/read_xattr/execute/read_attributes/read_acl/synchronize:allow). The synchronize access permission is not currently implemented.
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 A=acl-specification filename |
% chmod Aindex-ID=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 May 20 14:09 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 May 20 15:03 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 20 15:03 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 20 15:03 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 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 May 20 15:09 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 May 20 15:09 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 examples illustrate the interaction between setting ACLs and then changing the file or directory's permissions.
In the following example, a trivial ACL exists on file.2:
# ls -v file.2 -rw-r--r-- 1 root root 3103 May 20 15:23 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 3103 May 20 15:23 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 permissions are reset from 644 to 640. Read permissions for everyone@ are effectively removed from the file's permissions 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 6986 May 20 15:25 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. Because no owner@ or group@ ACL entry exists to override the permissions for owner and group, the permissions 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 6986 May 20 15:25 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 6986 May 20 15:25 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, thus restoring the trivial ACLs on the file or directory.
In the following example, two non-trivial ACEs exist on test5.dir:
# ls -dv test5.dir drwxr-xr-x+ 2 root root 2 May 20 15:32 test5.dir 0:user:lp:read_data:file_inherit:deny 1:user:gozer: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 May 20 15:32 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 |
You can specify whether and how ACLs are inherited on files and directories. By default, ACLs are not propagated. If you set a 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 can be set globally on file systems: aclinherit and aclmode. By default, aclinherit is set to restricted 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, a non-trivial ACE of read_data/write_data/execute is applied for user gozer on the test.dir directory:
# chmod A+user:gozer:read_data/write_data/execute:allow test.dir # ls -dv test.dir drwxr-xr-x+ 2 root root 2 May 20 15:41 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 the subdirectory if the permissions on the subdirectory granted him access as the file owner, group member, or everyone@. For example:
# mkdir test.dir/sub.dir # ls -dv test.dir/sub.dir drwxr-xr-x 2 root root 2 May 20 15:42 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 |
The following examples identify the file and directory ACEs that are applied when the file_inherit flag is set.
In this example, read_data/write_data permissions are added for files in the test2.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 May 20 15:50 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 this 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 that 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 May 20 15:51 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 property for this file is set to the default value, groupmask, user gozer does not have write_data permission on file.2 because the file's group permission does not allow it.
When using the inherit_only permission, which is applied when the file_inherit or dir_inherit flag is 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 file owner or a member of the file's group owner. For example:
# mkdir test2.dir/subdir.2 # ls -dv test2.dir/subdir.2 drwxr-xr-x+ 2 root root 2 May 20 15:52 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 examples identify the file and directory ACLs that are applied when both the file_inherit and dir_inherit flags are set.
In this 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 May 20 15:53 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 May 20 15:58 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 20 15:59 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 permissions of the parent directory for group@ and everyone@ deny write and execute permissions, user gozer is denied write and execute permissions. The default aclinherit property is restricted, which means that write_data and execute permissions are not inherited.
In this example, user gozer is granted read, write, and execute permissions that are inherited for newly created files. However, they 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 May 20 16:02 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 shows, when a new subdirectory is created, user gozer's read_data/write_data/execute permissions 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 May 20 16:03 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 shows, user gozer's read_data/write_data/execute permissions for files are 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 20 16:04 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 |
As the following example shows, when the aclmode property on the tank/cindys file system is set to passthrough, user gozer inherits the ACL applied on the test4.dir directory for the newly created file.4:
# zfs set aclmode=passthrough tank/cindys # touch test4.dir/file.4 # ls -v test4.dir/file.4 -rw-r--r--+ 1 root root 0 May 20 16:08 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 |
This output shows 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 permissions on a directory change. For example:
# zfs set aclmode=discard tank/cindys # 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 May 20 16:09 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 permissions 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 May 20 16:09 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 shows how you can specify two ACEs in the same chmod command.
# zfs set aclinherit=noallow tank/cindys # 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 20 16:11 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 20 16:13 test6.dir/file.6 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 |
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 Table 8–2 and Table 8–3.
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 Jun 17 10:07 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 |
This compact ACL output is described as follows:
The owner is denied execute permissions on the file (x=execute).
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 time stamps, extended attributes, and ACLs (A=write_xattr, W=write_attributes, and C=write_acl). In addition, the owner can modify the ownership of the file (o=write_owner).
The group is denied modify and execute permissions on the file (write_data, p=append_data, and x=execute).
The group is granted read permissions on the file (r=read_data).
Everyone who is not the owner of the file or a member of the owning group of the file 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, and o=write_owner).
Everyone who is not the owner of the file or a member of the owning group of the file on the file and the file's attributes (r=read_data, a=append_data, R=read_xattr, c=read_acl, and s=synchronize). The synchronize access permission is not currently implemented.
The compact ACL format provides the following advantages over the verbose ACL format:
Permissions can be specified as positional arguments to the chmod command.
The hyphen (-) characters, which identify no permissions, can be removed. 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--r-- 1 root root 206663 Jun 17 10:07 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 |
In the following example, read_data/execute permissions are added for user gozer on file.1:
# chmod A+user:gozer:rx:allow file.1 # ls -V file.1 -rw-r--r--+ 1 root root 206663 Jun 17 10:07 file.1 user:gozer:r-x-----------:------:allow 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 |
Another way to add the same permissions for user gozer is to insert a new ACL entry 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--r--+ 1 root root 206663 Jun 17 10:16 file.1 owner@:--x-----------:------:deny owner@:rw-p---A-W-Co-:------:allow group@:-wxp----------:------:deny group@:r-------------:------:allow user:gozer:r-x-----------:------:allow everyone@:-wxp---A-W-Co-:------:deny everyone@:r-----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.
# chmod A+user:gozer:rwx:fd:allow dir.2 # ls -dV dir.2 drwxr-xr-x+ 2 root root 2 Jun 17 10:19 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 the dir.2 directory for user gozer to user cindys on dir.2, copy and paste the permissions and inheritance flags (rwx-----------:fd----:allow) into your chmod command as follows:
# chmod A+user:cindys:rwx-----------:fd----:allow dir.2 # ls -dV dir.2 drwxr-xr-x+ 2 root root 2 Jun 17 10:19 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 |
A file system that has the aclinherit property set to passthrough inherits all inheritable ACL entries without any modifications made to the ACL entries when they are inherited. When this property is set to passthrough, files are created with a permissions that are determined by the inheritable ACEs. If no inheritable ACEs exist that affect the permissions, then the permissions are set in accordance to the requested permissions from the application.
The following examples use compact ACL syntax to show how to inherit permissions by setting the aclinherit property to passthrough.
In this example, an ACL is set on the test1.dir directory to force inheritance. The syntax creates an owner@, group@, and everyone@ ACL entry for newly created files. Newly created directories inherit an @owner, group@, and everyone@ ACL entry. Additionally, directories inherit six other ACEs that propagate the ACEs to the newly created directories and files.
# zfs set aclinherit=passthrough tank/cindys # pwd /tank/cindys # mkdir test1.dir |
# chmod A=owner@:rwxpcCosRrWaAdD:fd:allow,group@:rwxp:fd:allow,everyone@::fd:allow test1.dir # ls -Vd test1.dir drwxrwx---+ 2 root root 2 Jun 17 10:37 test1.dir owner@:rwxpdDaARWcCos:fd----:allow group@:rwxp----------:fd----:allow everyone@:--------------:fd----:allow |
In this example, a newly created file inherits the ACL that was specified to be inherited by the newly created files.
# cd test1.dir # touch file.1 # ls -V file.1 -rwxrwx---+ 1 root root 0 Jun 17 10:38 file.1 owner@:rwxpdDaARWcCos:------:allow group@:rwxp----------:------:allow everyone@:--------------:------:allow |
In this example, a newly created directory inherits both ACEs that control access to this directory as well as ACEs for future propagation to children of the newly created directory.
# mkdir subdir.1 # ls -dV subdir.1 drwxrwx---+ 2 root root 2 Jun 17 10:39 subdir.1 owner@:rwxpdDaARWcCos:fdi---:allow owner@:rwxpdDaARWcCos:------:allow group@:rwxp----------:fdi---:allow group@:rwxp----------:------:allow everyone@:--------------:fdi---:allow everyone@:--------------:------:allow |
The -di-- and f-i--- entries are for propagating inheritance and are not considered during access control. In this example, a file is created with a trivial ACL in another directory where inherited ACEs are not present.
# cd /tank/cindys # mkdir test2.dir # cd test2.dir # touch file.2 # ls -V file.2 -rw-r--r-- 1 root root 0 Jun 17 10:40 file.2 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 |
When aclinherit property is set to passthrough-x, files are created with the execute (x) permission for owner@, group@, or everyone@, but only if execute permission is set in file creation mode and in an inheritable ACE that affects the mode.
The following example shows how to inherit the execute permission by setting the aclinherit property to passthrough-x.
# zfs set aclinherit=passthrough-x tank/cindys |
The following ACL is set on /tank/cindys/test1.dir to provide executable ACL inheritance for files for owner@, group@, and everyone@.
# chmod A=owner@:rwxpcCosRrWaAdD:fd:allow,group@:rwxp:fd:allow,everyone@::fd:allow test1.dir # ls -Vd test1.dir drwxrwx---+ 2 root root 2 Jun 17 10:41 test1.dir owner@:rwxpdDaARWcCos:fd----:allow group@:rwxp----------:fd----:allow everyone@:--------------:fd----:allow |
A file (file1) is created with requested permissions 0666. The resulting permissions are 0660. The execution permission was not inherited because the creation mode did not request it.
# touch test1.dir/file1 # ls -V test1.dir/file1 -rw-rw----+ 1 root root 0 Jun 17 10:42 test1.dir/file1 owner@:rw-pdDaARWcCos:------:allow group@:rw-p----------:------:allow everyone@:--------------:------:allow |
Next, an executable called t is generated by using the cc compiler in the testdir directory.
# cc -o t t.c # ls -V t -rwxrwx---+ 1 root root 7396 Jun 17 10:50 t owner@:rwxpdDaARWcCos:------:allow group@:rwxp----------:------:allow everyone@:--------------:------:allow |
The resulting permissions are 0770 because cc requested permissions 0777, which caused the execute permission to be inherited from the owner@, group@, and everyone@ entries.