[CIFS] cifs_mkdir and cifs_create should respect the setgid bit on parent dir
authorJeff Layton <jlayton@redhat.com>
Wed, 6 Aug 2008 04:39:02 +0000 (04:39 +0000)
committerSteve French <sfrench@us.ibm.com>
Wed, 6 Aug 2008 04:39:02 +0000 (04:39 +0000)
If a server supports unix extensions but does not support POSIX create
routines, then the client will create a new inode with a standard SMB
mkdir or create/open call and then will set the mode. When it does this,
it does not take the setgid bit on the parent directory into account.

This patch has CIFS flip on the setgid bit when the parent directory has
it. If the share is mounted with "setuids" then also change the group
owner to the gid of the parent.

This patch should apply cleanly on top of the setattr cleanup patches
that I sent a few weeks ago.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
fs/cifs/dir.c
fs/cifs/inode.c

index 634cf330fe04a4c746c60b9b57c652a19f6ab905..e962e75e6f7b1e8f3d8011488f2d4c08c490a43e 100644 (file)
@@ -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;
                                }
                        }
                }
index d952914dfc4ce4267753b95043629d105ed6d61a..6d911896d74cdb83d64c42ef4db8b431a517903e 100644 (file)
@@ -985,7 +985,12 @@ mkdir_get_info:
                  * 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 @@ mkdir_get_info:
                        };
                        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 @@ mkdir_get_info:
                                     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;
                                }
                        }
                }