do_cifs_create(): don't set ->i_mode of something we had not created
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 11 Feb 2021 20:04:35 +0000 (15:04 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 13 Mar 2021 03:15:19 +0000 (22:15 -0500)
If the file had existed before we'd called ->atomic_open() (without
O_EXCL, that is), we have no more business setting ->i_mode than
we would setting ->i_uid or ->i_gid.  We also have no business
doing either if another client has managed to get unlink+mkdir
between ->open() and cifs_inode_get_info().

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/cifs/dir.c

index a3fb81e..9d7ae93 100644 (file)
@@ -418,15 +418,16 @@ cifs_create_get_file_info:
                if (newinode) {
                        if (server->ops->set_lease_key)
                                server->ops->set_lease_key(newinode, fid);
-                       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
-                               newinode->i_mode = mode;
-                       if ((*oplock & CIFS_CREATE_ACTION) &&
-                           (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
-                               newinode->i_uid = current_fsuid();
-                               if (inode->i_mode & S_ISGID)
-                                       newinode->i_gid = inode->i_gid;
-                               else
-                                       newinode->i_gid = current_fsgid();
+                       if ((*oplock & CIFS_CREATE_ACTION) && S_ISREG(newinode->i_mode)) {
+                               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
+                                       newinode->i_mode = mode;
+                               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+                                       newinode->i_uid = current_fsuid();
+                                       if (inode->i_mode & S_ISGID)
+                                               newinode->i_gid = inode->i_gid;
+                                       else
+                                               newinode->i_gid = current_fsgid();
+                               }
                        }
                }
        }