Commit 6c5e36d1 authored by Hyunchul Lee's avatar Hyunchul Lee Committed by Namjae Jeon
Browse files

ksmbd: set MAY_* flags together with open flags



set MAY_* flags together with open flags and
remove ksmbd_vfs_inode_permission().

Signed-off-by: default avatarHyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: default avatarNamjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 333111a6
Loading
Loading
Loading
Loading
+24 −14
Original line number Diff line number Diff line
@@ -1836,21 +1836,27 @@ int smb2_tree_connect(struct ksmbd_work *work)
 * @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;
			}
		}
	}

+13 −29
Original line number Diff line number Diff line
@@ -95,25 +95,10 @@ static int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child)
	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;
	int ret;

	parent = dget_parent(dentry);
	ret = ksmbd_vfs_lock_parent(parent, dentry);
@@ -122,12 +107,11 @@ int ksmbd_vfs_inode_permission(struct dentry *dentry, int acc_mode, bool delete)
		return ret;
	}

		if (inode_permission(&init_user_ns, d_inode(parent), MAY_EXEC | MAY_WRITE))
			ret = -EACCES;
	ret = inode_permission(&init_user_ns, d_inode(parent),
			       MAY_EXEC | MAY_WRITE);

	inode_unlock(d_inode(parent));
	dput(parent);
	}
	return ret;
}

+1 −2
Original line number Diff line number Diff line
@@ -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);