aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2008-05-22 09:33:34 -0400
committerSteve French <sfrench@us.ibm.com>2008-05-23 14:17:16 -0400
commitb0fd30d3e7e768aad5e398caaea6ae5a5c814eab (patch)
tree2841fce1397664445adad84225486d40f8c8ba97
parent4468eb3fd102cad559e51594a01cbc65b994d264 (diff)
when creating new inodes, use file_mode/dir_mode exclusively on mount without unix extensions
When CIFS creates a new inode on a mount without unix extensions, it temporarily assigns the mode that was passed to it in the create/mkdir call. Eventually, when the inode is revalidated, it changes to have the file_mode or dir_mode for the mount. This is confusing to users who expect that the mode shouldn't change this way. It's also problematic since only the mode is treated this way, not the uid or gid. Suppose you have a CIFS mount that's mounted with: uid=0,gid=0,file_mode=0666,dir_mode=0777 ...if an unprivileged user comes along and does this on the mount: mkdir -m 0700 foo touch foo/bar ...there is a period of time where the touch will fail, since the dir will initially be owned by root and have mode 0700. If the user waits long enough, then "foo" will be revalidated and will get the correct dir_mode permissions. This patch changes cifs_mkdir and cifs_create to not overwrite the mode found by the initial cifs_get_inode_info call after the inode is created on the server. Legacy behavior can be reenabled with the new "dynperm" mount option. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r--fs/cifs/dir.c4
-rw-r--r--fs/cifs/inode.c7
2 files changed, 8 insertions, 3 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index f0b5b5f3dd2e..fb69c1fa85c9 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -260,7 +260,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
260 buf, inode->i_sb, xid, 260 buf, inode->i_sb, xid,
261 &fileHandle); 261 &fileHandle);
262 if (newinode) { 262 if (newinode) {
263 newinode->i_mode = mode; 263 if (cifs_sb->mnt_cifs_flags &
264 CIFS_MOUNT_DYNPERM)
265 newinode->i_mode = mode;
264 if ((oplock & CIFS_CREATE_ACTION) && 266 if ((oplock & CIFS_CREATE_ACTION) &&
265 (cifs_sb->mnt_cifs_flags & 267 (cifs_sb->mnt_cifs_flags &
266 CIFS_MOUNT_SET_UID)) { 268 CIFS_MOUNT_SET_UID)) {
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index ae5bcaf2031c..12667d6bf305 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1015,8 +1015,11 @@ mkdir_get_info:
1015 CIFS_MOUNT_MAP_SPECIAL_CHR); 1015 CIFS_MOUNT_MAP_SPECIAL_CHR);
1016 } 1016 }
1017 if (direntry->d_inode) { 1017 if (direntry->d_inode) {
1018 direntry->d_inode->i_mode = mode; 1018 if (cifs_sb->mnt_cifs_flags &
1019 direntry->d_inode->i_mode |= S_IFDIR; 1019 CIFS_MOUNT_DYNPERM)
1020 direntry->d_inode->i_mode =
1021 (mode | S_IFDIR);
1022
1020 if (cifs_sb->mnt_cifs_flags & 1023 if (cifs_sb->mnt_cifs_flags &
1021 CIFS_MOUNT_SET_UID) { 1024 CIFS_MOUNT_SET_UID) {
1022 direntry->d_inode->i_uid = 1025 direntry->d_inode->i_uid =