summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2008-08-06 04:39:02 +0000
committerSteve French <sfrench@us.ibm.com>2008-08-06 04:39:02 +0000
commit95089910933e10768cfef1ab0bab0c55b962aacb (patch)
treec80dd73d46196aff3e6c12a12bfb6b6f20aac08c
parent2dd2dfa060650118661422d4e666ac804c388751 (diff)
downloadlinux-3.10-95089910933e10768cfef1ab0bab0c55b962aacb.tar.gz
linux-3.10-95089910933e10768cfef1ab0bab0c55b962aacb.tar.bz2
linux-3.10-95089910933e10768cfef1ab0bab0c55b962aacb.zip
[CIFS] cifs_mkdir and cifs_create should respect the setgid bit on parent dir
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>
-rw-r--r--fs/cifs/dir.c13
-rw-r--r--fs/cifs/inode.c18
2 files changed, 25 insertions, 6 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 634cf330fe0..e962e75e6f7 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 d952914dfc4..6d911896d74 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -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;
}
}
}