From c4a9e8a6ef15aea2a6a6ba65577e4ab90a0f24a5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 31 Mar 2011 10:49:22 -0700 Subject: [PATCH] Fix bug #7996 - sgid bit lost on folder rename. Refuse to set dos attributes into unix mode bits on such a folder. --- source3/include/proto.h | 1 + source3/smbd/dosmode.c | 22 ++++++++++++++++++++++ source3/smbd/posix_acls.c | 2 +- 3 files changed, 24 insertions(+), 1 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index a261310..6ff0882 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -6752,6 +6752,7 @@ uint32_t map_canon_ace_perms(int snum, mode_t perms, bool directory_ace); NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, const SEC_DESC *psd); +bool current_user_in_group(gid_t gid); SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T the_acl); NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info, SEC_DESC **ppdesc); diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 74f54a0..94caaf6 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -793,6 +793,28 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, unixmode |= (smb_fname->st.st_ex_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } + /* + * From the chmod 2 man page: + * + * "If the calling process is not privileged, and the group of the file + * does not match the effective group ID of the process or one of its + * supplementary group IDs, the S_ISGID bit will be turned off, but + * this will not cause an error to be returned." + * + * Simply refuse to do the chmod in this case. + */ + + if (S_ISDIR(smb_fname->st.st_ex_mode) && (unixmode & S_ISGID) && + geteuid() != sec_initial_uid() && + !current_user_in_group(smb_fname->st.st_ex_gid)) { + DEBUG(3,("file_set_dosmode: setgid bit cannot be " + "set for directory %s\n", + smb_fname_str_dbg(smb_fname))); + errno = EPERM; + return -1; + } + + ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode); if (ret == 0) { if(!newfile || (lret != -1)) { diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index aaca9f4..714a4d3 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2644,7 +2644,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn, Check if the current user group list contains a given group. ****************************************************************************/ -static bool current_user_in_group(gid_t gid) +bool current_user_in_group(gid_t gid) { int i; -- 1.7.3.1