ksmbd: set MAY_* flags together with open flags
authorHyunchul Lee <hyc.lee@gmail.com>
Wed, 23 Jun 2021 04:48:24 +0000 (13:48 +0900)
committerNamjae Jeon <namjae.jeon@samsung.com>
Mon, 28 Jun 2021 07:28:41 +0000 (16:28 +0900)
set MAY_* flags together with open flags and
remove ksmbd_vfs_inode_permission().

Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/ksmbd/smb2pdu.c
fs/ksmbd/vfs.c
fs/ksmbd/vfs.h

index 1327ae8..25715d5 100644 (file)
@@ -1836,21 +1836,27 @@ out_err1:
  * @file_present:      is file already present
  * @access:            file access flags
  * @disposition:       file disposition flags
+ * @may_flags:         set with MAY_ flags
  *
  * Return:      file open flags
  */
 static int smb2_create_open_flags(bool file_present, __le32 access,
-                                 __le32 disposition)
+                                 __le32 disposition,
+                                 int *may_flags)
 {
        int oflags = O_NONBLOCK | O_LARGEFILE;
 
        if (access & FILE_READ_DESIRED_ACCESS_LE &&
-           access & FILE_WRITE_DESIRE_ACCESS_LE)
+           access & FILE_WRITE_DESIRE_ACCESS_LE) {
                oflags |= O_RDWR;
-       else if (access & FILE_WRITE_DESIRE_ACCESS_LE)
+               *may_flags = MAY_OPEN | MAY_READ | MAY_WRITE;
+       } else if (access & FILE_WRITE_DESIRE_ACCESS_LE) {
                oflags |= O_WRONLY;
-       else
+               *may_flags = MAY_OPEN | MAY_WRITE;
+       } else {
                oflags |= O_RDONLY;
+               *may_flags = MAY_OPEN | MAY_READ;
+       }
 
        if (access == FILE_READ_ATTRIBUTES_LE)
                oflags |= O_PATH;
@@ -1884,6 +1890,7 @@ static int smb2_create_open_flags(bool file_present, __le32 access,
                        break;
                }
        }
+
        return oflags;
 }
 
@@ -2355,7 +2362,7 @@ int smb2_open(struct ksmbd_work *work)
        struct create_ea_buf_req *ea_buf = NULL;
        struct oplock_info *opinfo;
        __le32 *next_ptr = NULL;
-       int req_op_level = 0, open_flags = 0, file_info = 0;
+       int req_op_level = 0, open_flags = 0, may_flags = 0, file_info = 0;
        int rc = 0, len = 0;
        int contxt_cnt = 0, query_disk_id = 0;
        int maximal_access_ctxt = 0, posix_ctxt = 0;
@@ -2696,7 +2703,8 @@ int smb2_open(struct ksmbd_work *work)
        }
 
        open_flags = smb2_create_open_flags(file_present, daccess,
-                                           req->CreateDisposition);
+                                           req->CreateDisposition,
+                                           &may_flags);
 
        if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
                if (open_flags & O_CREAT) {
@@ -2723,21 +2731,23 @@ int smb2_open(struct ksmbd_work *work)
                                goto err_out;
                }
        } else if (!already_permitted) {
-               bool may_delete;
-
-               may_delete = daccess & FILE_DELETE_LE ||
-                       req->CreateOptions & FILE_DELETE_ON_CLOSE_LE;
-
                /* FILE_READ_ATTRIBUTE is allowed without inode_permission,
                 * because execute(search) permission on a parent directory,
                 * is already granted.
                 */
                if (daccess & ~(FILE_READ_ATTRIBUTES_LE | FILE_READ_CONTROL_LE)) {
-                       rc = ksmbd_vfs_inode_permission(path.dentry,
-                                                       open_flags & O_ACCMODE,
-                                                       may_delete);
+                       rc = inode_permission(&init_user_ns,
+                                             d_inode(path.dentry),
+                                             may_flags);
                        if (rc)
                                goto err_out;
+
+                       if ((daccess & FILE_DELETE_LE) ||
+                           (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
+                               rc = ksmbd_vfs_may_delete(path.dentry);
+                               if (rc)
+                                       goto err_out;
+                       }
                }
        }
 
index e64eab7..6181a58 100644 (file)
@@ -95,39 +95,23 @@ out_err:
        return ret;
 }
 
-int ksmbd_vfs_inode_permission(struct dentry *dentry, int acc_mode, bool delete)
+int ksmbd_vfs_may_delete(struct dentry *dentry)
 {
-       int mask, ret = 0;
-
-       mask = 0;
-       acc_mode &= O_ACCMODE;
-
-       if (acc_mode == O_RDONLY)
-               mask = MAY_READ;
-       else if (acc_mode == O_WRONLY)
-               mask = MAY_WRITE;
-       else if (acc_mode == O_RDWR)
-               mask = MAY_READ | MAY_WRITE;
-
-       if (inode_permission(&init_user_ns, d_inode(dentry), mask | MAY_OPEN))
-               return -EACCES;
-
-       if (delete) {
-               struct dentry *parent;
-
-               parent = dget_parent(dentry);
-               ret = ksmbd_vfs_lock_parent(parent, dentry);
-               if (ret) {
-                       dput(parent);
-                       return ret;
-               }
-
-               if (inode_permission(&init_user_ns, d_inode(parent), MAY_EXEC | MAY_WRITE))
-                       ret = -EACCES;
+       struct dentry *parent;
+       int ret;
 
-               inode_unlock(d_inode(parent));
+       parent = dget_parent(dentry);
+       ret = ksmbd_vfs_lock_parent(parent, dentry);
+       if (ret) {
                dput(parent);
+               return ret;
        }
+
+       ret = inode_permission(&init_user_ns, d_inode(parent),
+                              MAY_EXEC | MAY_WRITE);
+
+       inode_unlock(d_inode(parent));
+       dput(parent);
        return ret;
 }
 
index 49f0558..ae8eff1 100644 (file)
@@ -192,8 +192,7 @@ struct ksmbd_kstat {
        __le32                  file_attributes;
 };
 
-int ksmbd_vfs_inode_permission(struct dentry *dentry, int acc_mode,
-                              bool delete);
+int ksmbd_vfs_may_delete(struct dentry *dentry);
 int ksmbd_vfs_query_maximal_access(struct dentry *dentry, __le32 *daccess);
 int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode);
 int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode);