[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Thu Oct 15 20:28:04 UTC 2020


The branch, master has been updated
       via  2b8b0139fcc vfs_zfsacl: add zfs configuration guidance to manpage
       via  c1a37b4f31d vfs_zfsacl: only grant DELETE_CHILD if ACL tag is special
       via  13b4f913b06 vfs_zfsacl: use a helper variable in zfs_get_nt_acl_common()
       via  a182f2e6cdd vfs_zfsacl: README.Coding fix
       via  c10ae30c118 vfs_zfsacl: Add new parameter to stop automatic addition of special entries
       via  f763b1e4364 vfs_zfsacl: use handle based facl() call to query ZFS filesytem ACL
      from  6b9564c1084 s3:ctdbd_conn: simplify get_public_ips() / find_in_public_ips() API

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 2b8b0139fcc51a86a29879df220b6b8ca7eda66d
Author: Andrew Walker <awalker at ixsystems.com>
Date:   Thu Sep 24 16:57:59 2020 -0400

    vfs_zfsacl: add zfs configuration guidance to manpage
    
    Provide minimal background information on recommended ZFS settings
    for a samba share.
    
    Signed-off-by: Andrew Walker <awalker at ixsystems.com>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Thu Oct 15 20:27:34 UTC 2020 on sn-devel-184

commit c1a37b4f31d5252ce074d41f69e526aa84b0d3b3
Author: Andrew Walker <awalker at ixsystems.com>
Date:   Thu Sep 24 16:04:12 2020 -0400

    vfs_zfsacl: only grant DELETE_CHILD if ACL tag is special
    
    When ZFS aclmode is set to "passthrough" chmod(2)/fchmod(2) will result
    in special entries being modified in a way such that delete, delete_child,
    write_named_attr, write_attribute are stripped from the returned ACL entry,
    and the kernel / ZFS treats this as having rights equivalent to the desired
    POSIX mode. Historically, samba has added delete_child to the NFSv4 ACL, but
    this is only really called for in the case of special entries in this
    particular circumstance.
    
    Alter circumstances in which delete_child is granted so that it only
    is added to special entries. This preserves the intend post-chmod behavior,
    but avoids unnecessarily increasing permissions in cases where it's not
    intended. Further modification of this behavior may be required so that
    we grant a general read or general write permissions set in case of
    POSIX read / POSIX write on special entries.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14471
    
    Signed-off-by: Andrew Walker <awalker at ixsystems.com>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 13b4f913b06457d8e1f7cf71c85722bbecabd990
Author: Ralph Boehme <slow at samba.org>
Date:   Thu Aug 20 16:41:36 2020 +0200

    vfs_zfsacl: use a helper variable in zfs_get_nt_acl_common()
    
    No change in behaviour.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14471
    
    Pair-Programmed-With: Andrew Walker <awalker at ixsystems.com>
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Signed-off-by: Andrew Walker <awalker at ixsystems.com>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit a182f2e6cdded739812e209430d340097acc0031
Author: Ralph Boehme <slow at samba.org>
Date:   Thu Aug 20 16:42:17 2020 +0200

    vfs_zfsacl: README.Coding fix
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14471
    
    Pair-Programmed-With: Andrew Walker <awalker at ixsystems.com>
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Signed-off-by: Andrew Walker <awalker at ixsystems.com>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit c10ae30c1185463eb937f69c1fc9914558087167
Author: Andrew Walker <awalker at ixsystems.com>
Date:   Thu Sep 24 11:42:16 2020 -0400

    vfs_zfsacl: Add new parameter to stop automatic addition of special entries
    
    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 at ixsystems.com>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit f763b1e43640082af80c855a4a519f7747a6c87c
Author: Ralph Boehme <slow at samba.org>
Date:   Thu Aug 20 16:18:35 2020 +0200

    vfs_zfsacl: use handle based facl() call to query ZFS filesytem ACL
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14470
    
    Pair-Programmed-With: Andrew Walker <awalker at ixsystems.com>
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Signed-off-by: Andrew Walker <awalker at ixsystems.com>
    Reviewed-by: Jeremy Allison <jra at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 docs-xml/manpages/vfs_zfsacl.8.xml |  30 ++++++
 source3/modules/vfs_zfsacl.c       | 206 +++++++++++++++++++++++++++++--------
 2 files changed, 193 insertions(+), 43 deletions(-)


Changeset truncated at 500 lines:

diff --git a/docs-xml/manpages/vfs_zfsacl.8.xml b/docs-xml/manpages/vfs_zfsacl.8.xml
index ae583409fe1..9b3ba1b6bc7 100644
--- a/docs-xml/manpages/vfs_zfsacl.8.xml
+++ b/docs-xml/manpages/vfs_zfsacl.8.xml
@@ -56,6 +56,16 @@
 	with NFSv4 compatible ACLs.
 	</para>
 
+	<para>ZFS has mutiple dataset configuration parameters that determine ACL behavior.
+	Although the nuances of these parameters are outside the scope of this manpage, the
+	"aclmode" and "aclinherit" are of particular importance for samba shares.
+	For datasets that are intended solely as Samba shares, "aclmode = restricted"
+	and "aclinherit = passthrough" provide inheritance behavior most consistent with NTFS ACLs.
+	A "restricted" aclmode prevents chmod() on files that have a non-trivial ACL (one that
+	cannot be expressed as a POSIX mode without loss of information). Consult the relevant ZFS
+	manpages for further information.
+	</para>
+
 	<para>This module is stackable.</para>
 
 	<para>Since Samba 4.0 all options are per share options.</para>
@@ -140,6 +150,26 @@
 		</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>
diff --git a/source3/modules/vfs_zfsacl.c b/source3/modules/vfs_zfsacl.c
index 9142a07aadd..093eb5111e1 100644
--- a/source3/modules/vfs_zfsacl.c
+++ b/source3/modules/vfs_zfsacl.c
@@ -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()
@@ -49,13 +50,15 @@ struct zfsacl_config_data {
 static NTSTATUS zfs_get_nt_acl_common(struct connection_struct *conn,
 				      TALLOC_CTX *mem_ctx,
 				      const struct smb_filename *smb_fname,
+				      const ace_t *acebuf,
+				      int naces,
 				      struct SMB4ACL_T **ppacl,
 				      struct zfsacl_config_data *config)
 {
-	int naces, i;
-	ace_t *acebuf;
+	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;
@@ -76,42 +79,28 @@ static NTSTATUS zfs_get_nt_acl_common(struct connection_struct *conn,
 	}
 	is_dir = S_ISDIR(psbuf->st_ex_mode);
 
-	/* read the number of file aces */
-	if((naces = acl(smb_fname->base_name, ACE_GETACLCNT, 0, NULL)) == -1) {
-		if(errno == ENOSYS) {
-			DEBUG(9, ("acl(ACE_GETACLCNT, %s): Operation is not "
-				  "supported on the filesystem where the file "
-				  "reside\n", smb_fname->base_name));
-		} else {
-			DEBUG(9, ("acl(ACE_GETACLCNT, %s): %s ", smb_fname->base_name,
-					strerror(errno)));
-		}
-		return map_nt_error_from_unix(errno);
-	}
-	/* allocate the field of ZFS aces */
 	mem_ctx = talloc_tos();
-	acebuf = (ace_t *) talloc_size(mem_ctx, sizeof(ace_t)*naces);
-	if(acebuf == NULL) {
-		return NT_STATUS_NO_MEMORY;
-	}
-	/* read the aces into the field */
-	if(acl(smb_fname->base_name, ACE_GETACL, naces, acebuf) < 0) {
-		DEBUG(9, ("acl(ACE_GETACL, %s): %s ", smb_fname->base_name,
-				strerror(errno)));
-		return map_nt_error_from_unix(errno);
-	}
+
 	/* create SMB4ACL data */
 	if((pacl = smb_create_smb4acl(mem_ctx)) == NULL) {
 		return NT_STATUS_NO_MEMORY;
 	}
 	for(i=0; i<naces; i++) {
 		SMB_ACE4PROP_T aceprop;
+		uint16_t special = 0;
 
 		aceprop.aceType  = (uint32_t) acebuf[i].a_type;
 		aceprop.aceFlags = (uint32_t) acebuf[i].a_flags;
 		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
@@ -121,7 +110,12 @@ static NTSTATUS zfs_get_nt_acl_common(struct connection_struct *conn,
 			aceprop.aceMask |= SMB_ACE4_SYNCHRONIZE;
 		}
 
-		if (is_dir && (aceprop.aceMask & SMB_ACE4_ADD_FILE)) {
+		special = acebuf[i].a_flags & (ACE_OWNER|ACE_GROUP|ACE_EVERYONE);
+
+		if (is_dir &&
+		    (aceprop.aceMask & SMB_ACE4_ADD_FILE) &&
+		    (special != 0))
+		{
 			aceprop.aceMask |= SMB_ACE4_DELETE_CHILD;
 		}
 
@@ -130,20 +124,25 @@ static NTSTATUS zfs_get_nt_acl_common(struct connection_struct *conn,
 			inherited_is_present = true;
 		}
 #endif
-		if(aceprop.aceFlags & ACE_OWNER) {
+		switch(special) {
+		case(ACE_OWNER):
 			aceprop.flags = SMB_ACE4_ID_SPECIAL;
 			aceprop.who.special_id = SMB_ACE4_WHO_OWNER;
-		} else if(aceprop.aceFlags & ACE_GROUP) {
+			break;
+		case(ACE_GROUP):
 			aceprop.flags = SMB_ACE4_ID_SPECIAL;
 			aceprop.who.special_id = SMB_ACE4_WHO_GROUP;
-		} else if(aceprop.aceFlags & ACE_EVERYONE) {
+			break;
+		case(ACE_EVERYONE):
 			aceprop.flags = SMB_ACE4_ID_SPECIAL;
 			aceprop.who.special_id = SMB_ACE4_WHO_EVERYONE;
-		} else {
+			break;
+		default:
 			aceprop.flags	= 0;
 		}
-		if(smb_add_ace4(pacl, &aceprop) == NULL)
+		if (smb_add_ace4(pacl, &aceprop) == NULL) {
 			return NT_STATUS_NO_MEMORY;
+		}
 	}
 
 #ifdef ACE_INHERITED_ACE
@@ -163,17 +162,22 @@ static NTSTATUS zfs_get_nt_acl_common(struct connection_struct *conn,
 static bool zfs_process_smbacl(vfs_handle_struct *handle, files_struct *fsp,
 			       struct SMB4ACL_T *smbacl)
 {
-	int naces = smb_get_naces(smbacl), i;
+	int naces = smb_get_naces(smbacl), i, rv;
 	ace_t *acebuf;
 	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);
@@ -213,6 +217,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;
@@ -222,7 +233,13 @@ static bool zfs_process_smbacl(vfs_handle_struct *handle, files_struct *fsp,
 	SMB_ASSERT(i == naces);
 
 	/* store acl */
-	if(acl(fsp->fsp_name->base_name, ACE_SETACL, naces, acebuf)) {
+	if (fsp->fh->fd != -1) {
+		rv = facl(fsp->fh->fd, ACE_SETACL, naces, acebuf);
+	}
+	else {
+		rv = acl(fsp->fsp_name->base_name, ACE_SETACL, naces, acebuf);
+	}
+	if (rv != 0) {
 		if(errno == ENOSYS) {
 			DEBUG(9, ("acl(ACE_SETACL, %s): Operation is not "
 				  "supported on the filesystem where the file "
@@ -231,7 +248,7 @@ static bool zfs_process_smbacl(vfs_handle_struct *handle, files_struct *fsp,
 			DEBUG(9, ("acl(ACE_SETACL, %s): %s ", fsp_str_dbg(fsp),
 				  strerror(errno)));
 		}
-		return 0;
+		return false;
 	}
 
 	return True;
@@ -259,6 +276,81 @@ static NTSTATUS zfs_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
 				zfs_process_smbacl);
 }
 
+static int get_zfsacl(TALLOC_CTX *mem_ctx,
+		      const struct smb_filename *smb_fname,
+		      ace_t **outbuf)
+{
+	int naces, rv;
+	ace_t *acebuf = NULL;
+
+	naces = acl(smb_fname->base_name, ACE_GETACLCNT, 0, NULL);
+	if (naces == -1) {
+		int dbg_level = 10;
+
+		if (errno == ENOSYS) {
+			dbg_level = 1;
+		}
+		DEBUG(dbg_level, ("acl(ACE_GETACLCNT, %s): %s ",
+				  smb_fname->base_name, strerror(errno)));
+		return naces;
+	}
+	acebuf = talloc_size(mem_ctx, sizeof(ace_t)*naces);
+	if (acebuf == NULL) {
+		errno = ENOMEM;
+		return -1;
+	}
+
+	rv = acl(smb_fname->base_name, ACE_GETACL, naces, acebuf);
+	if (rv == -1) {
+		DBG_DEBUG("acl(ACE_GETACL, %s) failed: %s ",
+			  smb_fname->base_name, strerror(errno));
+		return -1;
+	}
+
+	*outbuf = acebuf;
+	return naces;
+}
+
+static int fget_zfsacl(TALLOC_CTX *mem_ctx,
+		       struct files_struct *fsp,
+		       ace_t **outbuf)
+{
+	int naces, rv;
+	ace_t *acebuf = NULL;
+
+	if (fsp->fh->fd == -1) {
+		return get_zfsacl(mem_ctx, fsp->fsp_name, outbuf);
+	}
+
+	naces = facl(fsp->fh->fd, ACE_GETACLCNT, 0, NULL);
+	if (naces == -1) {
+		int dbg_level = 10;
+
+		if (errno == ENOSYS) {
+			dbg_level = 1;
+		}
+		DEBUG(dbg_level, ("facl(ACE_GETACLCNT, %s): %s ",
+				  fsp_str_dbg(fsp), strerror(errno)));
+		return naces;
+	}
+
+	acebuf = talloc_size(mem_ctx, sizeof(ace_t)*naces);
+	if (acebuf == NULL) {
+		errno = ENOMEM;
+		return -1;
+	}
+
+	rv = facl(fsp->fh->fd, ACE_GETACL, naces, acebuf);
+	if (rv == -1) {
+		DBG_DEBUG("acl(ACE_GETACL, %s): %s ",
+			  fsp_str_dbg(fsp), strerror(errno));
+		return -1;
+	}
+
+	*outbuf = acebuf;
+	return naces;
+}
+
 static NTSTATUS zfsacl_fget_nt_acl(struct vfs_handle_struct *handle,
 				   struct files_struct *fsp,
 				   uint32_t security_info,
@@ -268,6 +360,8 @@ static NTSTATUS zfsacl_fget_nt_acl(struct vfs_handle_struct *handle,
 	struct SMB4ACL_T *pacl;
 	NTSTATUS status;
 	struct zfsacl_config_data *config = NULL;
+	ace_t *acebuf = NULL;
+	int naces;
 
 	SMB_VFS_HANDLE_GET_DATA(handle, config,
 				struct zfsacl_config_data,
@@ -275,9 +369,9 @@ static NTSTATUS zfsacl_fget_nt_acl(struct vfs_handle_struct *handle,
 
 	TALLOC_CTX *frame = talloc_stackframe();
 
-	status = zfs_get_nt_acl_common(handle->conn, frame,
-				       fsp->fsp_name, &pacl, config);
-	if (!NT_STATUS_IS_OK(status)) {
+	naces = fget_zfsacl(talloc_tos(), fsp, &acebuf);
+	if (naces == -1) {
+		status = map_nt_error_from_unix(errno);
 		TALLOC_FREE(frame);
 		if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
 			return status;
@@ -295,6 +389,18 @@ static NTSTATUS zfsacl_fget_nt_acl(struct vfs_handle_struct *handle,
 		return NT_STATUS_OK;
 	}
 
+	status = zfs_get_nt_acl_common(handle->conn,
+				       frame,
+				       fsp->fsp_name,
+				       acebuf,
+				       naces,
+				       &pacl,
+				       config);
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(frame);
+		return status;
+	}
+
 	status = smb_fget_nt_acl_nfs4(fsp, NULL, security_info, mem_ctx,
 				      ppdesc, pacl);
 	TALLOC_FREE(frame);
@@ -312,6 +418,8 @@ static NTSTATUS zfsacl_get_nt_acl_at(struct vfs_handle_struct *handle,
 	NTSTATUS status;
 	struct zfsacl_config_data *config = NULL;
 	TALLOC_CTX *frame = NULL;
+	int naces;
+	ace_t *acebuf = NULL;
 
 	SMB_ASSERT(dirfsp == handle->conn->cwd_fsp);
 
@@ -322,12 +430,9 @@ static NTSTATUS zfsacl_get_nt_acl_at(struct vfs_handle_struct *handle,
 
 	frame = talloc_stackframe();
 
-	status = zfs_get_nt_acl_common(handle->conn,
-				frame,
-				smb_fname,
-				&pacl,
-				config);
-	if (!NT_STATUS_IS_OK(status)) {
+	naces = get_zfsacl(frame, smb_fname, &acebuf);
+	if (naces == -1) {
+		status = map_nt_error_from_unix(errno);
 		TALLOC_FREE(frame);
 		if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
 			return status;
@@ -351,6 +456,18 @@ static NTSTATUS zfsacl_get_nt_acl_at(struct vfs_handle_struct *handle,
 		return NT_STATUS_OK;
 	}
 
+	status = zfs_get_nt_acl_common(handle->conn,
+				       frame,
+				       smb_fname,
+				       acebuf,
+				       naces,
+				       &pacl,
+				       config);
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(frame);
+		return status;
+	}
+
 	status = smb_get_nt_acl_nfs4(handle->conn,
 					smb_fname,
 					NULL,
@@ -475,6 +592,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);


-- 
Samba Shared Repository



More information about the samba-cvs mailing list