From: Ralph Boehme Date: Thu, 20 Aug 2020 14:18:35 +0000 (+0200) Subject: vfs_zfsacl: use handle based facl() call to query ZFS filesytem ACL X-Git-Tag: samba-4.12.10~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=78d843f43626a876557d3c6738329282adeb4dab;p=thirdparty%2Fsamba.git 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 Signed-off-by: Ralph Boehme Signed-off-by: Andrew Walker Reviewed-by: Jeremy Allison (backported from commit f763b1e43640082af80c855a4a519f7747a6c87c) [slow@samba.org: conflict in zfs_get_nt_acl_common() due to *AT changes in 4.13] --- diff --git a/source3/modules/vfs_zfsacl.c b/source3/modules/vfs_zfsacl.c index 524881ab4af..d3da7257838 100644 --- a/source3/modules/vfs_zfsacl.c +++ b/source3/modules/vfs_zfsacl.c @@ -49,11 +49,12 @@ 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; const SMB_STRUCT_STAT *psbuf = NULL; @@ -76,30 +77,8 @@ 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; @@ -163,7 +142,7 @@ 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; @@ -222,7 +201,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 +216,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 +244,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 +328,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 +337,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 +357,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); @@ -310,14 +384,18 @@ static NTSTATUS zfsacl_get_nt_acl(struct vfs_handle_struct *handle, struct SMB4ACL_T *pacl; NTSTATUS status; struct zfsacl_config_data *config = NULL; + int naces; + ace_t *acebuf = NULL; + SMB_VFS_HANDLE_GET_DATA(handle, config, struct zfsacl_config_data, return NT_STATUS_INTERNAL_ERROR); TALLOC_CTX *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; @@ -341,6 +419,18 @@ static NTSTATUS zfsacl_get_nt_acl(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,