diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 634cf330fe04a4c746c60b9b57c652a19f6ab905..e962e75e6f7b1e8f3d8011488f2d4c08c490a43e 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -236,12 +236,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { args.uid = (__u64) current->fsuid; - args.gid = (__u64) current->fsgid; + if (inode->i_mode & S_ISGID) + args.gid = (__u64) inode->i_gid; + else + args.gid = (__u64) current->fsgid; } else { args.uid = NO_CHANGE_64; args.gid = NO_CHANGE_64; } - CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & @@ -270,7 +272,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { newinode->i_uid = current->fsuid; - newinode->i_gid = current->fsgid; + if (inode->i_mode & S_ISGID) + newinode->i_gid = + inode->i_gid; + else + newinode->i_gid = + current->fsgid; } } } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index d952914dfc4ce4267753b95043629d105ed6d61a..6d911896d74cdb83d64c42ef4db8b431a517903e 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -985,7 +985,12 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) * failed to get it from the server or was set bogus */ if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) direntry->d_inode->i_nlink = 2; + mode &= ~current->fs->umask; + /* must turn on setgid bit if parent dir has it */ + if (inode->i_mode & S_ISGID) + mode |= S_ISGID; + if (pTcon->unix_ext) { struct cifs_unix_set_info_args args = { .mode = mode, @@ -996,7 +1001,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) }; if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { args.uid = (__u64)current->fsuid; - args.gid = (__u64)current->fsgid; + if (inode->i_mode & S_ISGID) + args.gid = (__u64)inode->i_gid; + else + args.gid = (__u64)current->fsgid; } else { args.uid = NO_CHANGE_64; args.gid = NO_CHANGE_64; @@ -1026,8 +1034,12 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) CIFS_MOUNT_SET_UID) { direntry->d_inode->i_uid = current->fsuid; - direntry->d_inode->i_gid = - current->fsgid; + if (inode->i_mode & S_ISGID) + direntry->d_inode->i_gid = + inode->i_gid; + else + direntry->d_inode->i_gid = + current->fsgid; } } }