vfs_zfsacl: Add new parameter to stop automatic addition of special entries
authorAndrew Walker <awalker@ixsystems.com>
Thu, 24 Sep 2020 15:42:16 +0000 (11:42 -0400)
committerJeremy Allison <jra@samba.org>
Thu, 15 Oct 2020 19:07:40 +0000 (19:07 +0000)
Prevent ZFS from automatically adding NFSv4 special entries (owner@, group@,
everyone@). ZFS will automatically add these these entries when calculating the
inherited ACL of new files if the ACL of the parent directory lacks an
inheriting special entry. This may result in user confusion and unexpected
change in permissions of files and directories as the inherited ACL is
generated. Blocking this behavior is achieved by setting an inheriting
everyone@ that grants no permissions and not adding the entry to the file's
Security Descriptor.

This change also updates behavior so that the fd-based syscall facl() is
used where possible.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14470

Signed-off-by: Andrew Walker <awalker@ixsystems.com>
Reviewed-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
docs-xml/manpages/vfs_zfsacl.8.xml
source3/modules/vfs_zfsacl.c

index ae583409fe1f4e51eb4af7ef900f8135f72a3b38..1ac954b9429b10418a50f5a7ddebbfe40a68fd7c 100644 (file)
                </listitem>
                </varlistentry>
 
+               <varlistentry>
+               <term>zfsacl:block_special = [yes|no]</term>
+               <listitem>
+               <para>Prevent ZFS from automatically adding NFSv4 special
+               entries (owner@, group@, everyone@).  ZFS will automatically
+               generate these these entries when calculating the inherited ACL
+               of new files if the ACL of the parent directory lacks an
+               inheriting special entry. This may result in user confusion and
+               unexpected change in permissions of files and directories as the
+               inherited ACL is generated. Blocking this behavior is achieved
+               by setting an inheriting everyone@ that grants no permissions
+               and not adding the entry to the file's Security
+               Descriptor</para>
+               <itemizedlist>
+               <listitem><para><command>yes (default)</command></para></listitem>
+               <listitem><para><command>no</command></para></listitem>
+               </itemizedlist>
+               </listitem>
+               </varlistentry>
+
                <varlistentry>
                <term>zfsacl:map_dacl_protected = [yes|no]</term>
                <listitem>
index b0a93aa410eab17d80a22204d65dbc4743ce604b..c5c4718d6ce55eec283467d25b53d104ca7d2122 100644 (file)
@@ -40,6 +40,7 @@ struct zfsacl_config_data {
        struct smbacl4_vfs_params nfs4_params;
        bool zfsacl_map_dacl_protected;
        bool zfsacl_denymissingspecial;
+       bool zfsacl_block_special;
 };
 
 /* zfs_get_nt_acl()
@@ -57,6 +58,7 @@ static NTSTATUS zfs_get_nt_acl_common(struct connection_struct *conn,
        int i;
        struct SMB4ACL_T *pacl;
        SMB_STRUCT_STAT sbuf;
+       SMB_ACE4PROP_T blocking_ace;
        const SMB_STRUCT_STAT *psbuf = NULL;
        int ret;
        bool inherited_is_present = false;
@@ -91,6 +93,13 @@ static NTSTATUS zfs_get_nt_acl_common(struct connection_struct *conn,
                aceprop.aceMask  = (uint32_t) acebuf[i].a_access_mask;
                aceprop.who.id   = (uint32_t) acebuf[i].a_who;
 
+               if (config->zfsacl_block_special &&
+                   (aceprop.aceMask == 0) &&
+                   (aceprop.aceFlags & ACE_EVERYONE) &&
+                   (aceprop.aceFlags & ACE_INHERITED_ACE))
+               {
+                       continue;
+               }
                /*
                 * Windows clients expect SYNC on acls to correctly allow
                 * rename, cf bug #7909. But not on DENY ace entries, cf bug
@@ -147,12 +156,17 @@ static bool zfs_process_smbacl(vfs_handle_struct *handle, files_struct *fsp,
        struct SMB4ACE_T *smbace;
        TALLOC_CTX      *mem_ctx;
        bool have_special_id = false;
+       bool must_add_empty_ace = false;
        struct zfsacl_config_data *config = NULL;
 
        SMB_VFS_HANDLE_GET_DATA(handle, config,
                                struct zfsacl_config_data,
                                return False);
 
+       if (config->zfsacl_block_special && S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
+               naces++;
+               must_add_empty_ace = true;
+       }
        /* allocate the field of ZFS aces */
        mem_ctx = talloc_tos();
        acebuf = (ace_t *) talloc_size(mem_ctx, sizeof(ace_t)*naces);
@@ -192,6 +206,13 @@ static bool zfs_process_smbacl(vfs_handle_struct *handle, files_struct *fsp,
                        have_special_id = true;
                }
        }
+       if (must_add_empty_ace) {
+               acebuf[i].a_type = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE;
+               acebuf[i].a_flags = SMB_ACE4_DIRECTORY_INHERIT_ACE| \
+                                   SMB_ACE4_FILE_INHERIT_ACE|ACE_EVERYONE;
+               acebuf[i].a_access_mask = 0;
+               i++;
+       }
 
        if (!have_special_id && config->zfsacl_denymissingspecial) {
                errno = EACCES;
@@ -560,6 +581,9 @@ static int zfsacl_connect(struct vfs_handle_struct *handle,
        config->zfsacl_denymissingspecial = lp_parm_bool(SNUM(handle->conn),
                                "zfsacl", "denymissingspecial", false);
 
+       config->zfsacl_block_special = lp_parm_bool(SNUM(handle->conn),
+                               "zfsacl", "block_special", true);
+
        ret = smbacl4_get_vfs_params(handle->conn, &config->nfs4_params);
        if (ret < 0) {
                TALLOC_FREE(config);