From 709a19306038dfa6fdcbb12d0dae528204dca5e9 Mon Sep 17 00:00:00 2001 From: Boris Lechner Date: Tue, 10 Feb 2015 17:14:36 +0100 Subject: [PATCH] vfs_acl_xattr: propagate gid when container has sgid bit set Bug 8938 - When storing ACL blob, check if container has sgid bit set, and set the contents gid to the container's gid, instead of setting it to user's main gid. Boris Lechner --- source3/modules/vfs_acl_xattr.c | 98 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c index c1b0a60..7c39aa7 100644 --- a/source3/modules/vfs_acl_xattr.c +++ b/source3/modules/vfs_acl_xattr.c @@ -24,6 +24,7 @@ #include "librpc/gen_ndr/ndr_xattr.h" #include "../lib/crypto/crypto.h" #include "auth.h" +#include "../librpc/gen_ndr/idmap.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS @@ -92,6 +93,96 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx, } /******************************************************************* + Honor container sgid if any +*******************************************************************/ + +static int store_acl_blob_honor_sgid_fsp(vfs_handle_struct *handle, + files_struct *fsp) +{ + struct smb_filename parent = { 0, }; + int res; + struct security_descriptor *parent_desc = NULL; + NTSTATUS status = NT_STATUS_OK; + const struct dom_sid *group_sid = NULL; + struct unixid ids; + bool ok; + u_int32_t gid; + + + // Retrieve parent dir name + if (!parent_dirname(talloc_tos(), fsp->fsp_name->base_name, + &parent.base_name, NULL)) + { + DEBUG(5, ("unable to get parent_dirname\n")); + return -1; + } + + // Parent has sgid ? + res = SMB_VFS_NEXT_STAT(handle, &parent); + if (res == -1) { + DEBUG(5, ("SMB_VFS_NEXT_STAT(%s) failed: %s\n", + parent.base_name, strerror(errno))); + TALLOC_FREE(parent.base_name); + return -2; + } + + if ((parent.st.st_ex_mode & S_ISGID) == 0) { + DEBUG(10, ("Parent has no SGID\n")); + TALLOC_FREE(parent.base_name); + return 0; + } + + // Get parent group sid + status = SMB_VFS_GET_NT_ACL(handle->conn, + parent.base_name, + (SECINFO_GROUP), + talloc_tos(), + &parent_desc); + + TALLOC_FREE(parent.base_name); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5, ("SMB_VFS_GET_NT_ACL failed\n")); + return -3; + } + + group_sid = parent_desc->group_sid; + if (group_sid == NULL) { + DEBUG(5, ("Parent of '%s' has no group_sid\n", + fsp->fsp_name->base_name)); + TALLOC_FREE(parent_desc); + return -4; + } + + ZERO_STRUCT(ids); + ok = sids_to_unixids(group_sid, 1, &ids); + TALLOC_FREE(parent_desc); + + if (!(ok && (ids.type == ID_TYPE_BOTH || + ids.type == ID_TYPE_GID))) + { + DEBUG(5, ("Parent of '%s' is sgid but has no gid\n", + fsp->fsp_name->base_name)); + return -5; + } + gid = ids.id; + + // Doing chown for gid + become_root(); + res = SMB_VFS_NEXT_CHOWN(handle, fsp->fsp_name->base_name, + -1, gid); + unbecome_root(); + + if (res == -1) { + DEBUG(5, ("CHOWN(%s, -1; %u) failed: %s\n", + fsp->fsp_name->base_name, gid, + strerror(errno))); + return -6; + } + + return 0; +} + +/******************************************************************* Store a DATA_BLOB into an xattr given an fsp pointer. *******************************************************************/ @@ -104,6 +195,13 @@ static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle, DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n", (unsigned int)pblob->length, fsp_str_dbg(fsp))); + + // Check if container has sgid bit, and set its gid if necessary + ret = store_acl_blob_honor_sgid_fsp(handle, fsp); + if (ret < 0) { + DEBUG(5, ("store_acl_blob_sgid_check failed(%d)\n", + ret)); + } become_root(); if (fsp->fh->fd != -1) { -- 1.9.1