提交 8a8bcc4b 编写于 作者: H Hyunchul Lee 提交者: Zhong Jinghua

ksmbd: set MAY_* flags together with open flags

mainline inclusion
from mainline-v5.15-rc1
commit 6c5e36d1
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I60T7G
CVE: NA

Reference: https://git.kernel.org/torvalds/linux/c/6c5e36d13e2a

set MAY_* flags together with open flags and
remove ksmbd_vfs_inode_permission().
Signed-off-by: NHyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: NNamjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: NSteve French <stfrench@microsoft.com>
Signed-off-by: NJason Yan <yanaijie@huawei.com>
Signed-off-by: NZhong Jinghua <zhongjinghua@huawei.com>
上级 73d90a12
...@@ -1836,21 +1836,27 @@ int smb2_tree_connect(struct ksmbd_work *work) ...@@ -1836,21 +1836,27 @@ int smb2_tree_connect(struct ksmbd_work *work)
* @file_present: is file already present * @file_present: is file already present
* @access: file access flags * @access: file access flags
* @disposition: file disposition flags * @disposition: file disposition flags
* @may_flags: set with MAY_ flags
* *
* Return: file open flags * Return: file open flags
*/ */
static int smb2_create_open_flags(bool file_present, __le32 access, static int smb2_create_open_flags(bool file_present, __le32 access,
__le32 disposition) __le32 disposition,
int *may_flags)
{ {
int oflags = O_NONBLOCK | O_LARGEFILE; int oflags = O_NONBLOCK | O_LARGEFILE;
if (access & FILE_READ_DESIRED_ACCESS_LE && if (access & FILE_READ_DESIRED_ACCESS_LE &&
access & FILE_WRITE_DESIRE_ACCESS_LE) access & FILE_WRITE_DESIRE_ACCESS_LE) {
oflags |= O_RDWR; 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; oflags |= O_WRONLY;
else *may_flags = MAY_OPEN | MAY_WRITE;
} else {
oflags |= O_RDONLY; oflags |= O_RDONLY;
*may_flags = MAY_OPEN | MAY_READ;
}
if (access == FILE_READ_ATTRIBUTES_LE) if (access == FILE_READ_ATTRIBUTES_LE)
oflags |= O_PATH; oflags |= O_PATH;
...@@ -1884,6 +1890,7 @@ static int smb2_create_open_flags(bool file_present, __le32 access, ...@@ -1884,6 +1890,7 @@ static int smb2_create_open_flags(bool file_present, __le32 access,
break; break;
} }
} }
return oflags; return oflags;
} }
...@@ -2355,7 +2362,7 @@ int smb2_open(struct ksmbd_work *work) ...@@ -2355,7 +2362,7 @@ int smb2_open(struct ksmbd_work *work)
struct create_ea_buf_req *ea_buf = NULL; struct create_ea_buf_req *ea_buf = NULL;
struct oplock_info *opinfo; struct oplock_info *opinfo;
__le32 *next_ptr = NULL; __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 rc = 0, len = 0;
int contxt_cnt = 0, query_disk_id = 0; int contxt_cnt = 0, query_disk_id = 0;
int maximal_access_ctxt = 0, posix_ctxt = 0; int maximal_access_ctxt = 0, posix_ctxt = 0;
...@@ -2696,7 +2703,8 @@ int smb2_open(struct ksmbd_work *work) ...@@ -2696,7 +2703,8 @@ int smb2_open(struct ksmbd_work *work)
} }
open_flags = smb2_create_open_flags(file_present, daccess, 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 (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
if (open_flags & O_CREAT) { if (open_flags & O_CREAT) {
...@@ -2723,21 +2731,23 @@ int smb2_open(struct ksmbd_work *work) ...@@ -2723,21 +2731,23 @@ int smb2_open(struct ksmbd_work *work)
goto err_out; goto err_out;
} }
} else if (!already_permitted) { } 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, /* FILE_READ_ATTRIBUTE is allowed without inode_permission,
* because execute(search) permission on a parent directory, * because execute(search) permission on a parent directory,
* is already granted. * is already granted.
*/ */
if (daccess & ~(FILE_READ_ATTRIBUTES_LE | FILE_READ_CONTROL_LE)) { if (daccess & ~(FILE_READ_ATTRIBUTES_LE | FILE_READ_CONTROL_LE)) {
rc = ksmbd_vfs_inode_permission(path.dentry, rc = inode_permission(&init_user_ns,
open_flags & O_ACCMODE, d_inode(path.dentry),
may_delete); may_flags);
if (rc) if (rc)
goto err_out; 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;
}
} }
} }
......
...@@ -95,39 +95,23 @@ static int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child) ...@@ -95,39 +95,23 @@ static int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child)
return ret; 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; struct dentry *parent;
int ret;
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;
inode_unlock(d_inode(parent)); parent = dget_parent(dentry);
ret = ksmbd_vfs_lock_parent(parent, dentry);
if (ret) {
dput(parent); 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; return ret;
} }
......
...@@ -192,8 +192,7 @@ struct ksmbd_kstat { ...@@ -192,8 +192,7 @@ struct ksmbd_kstat {
__le32 file_attributes; __le32 file_attributes;
}; };
int ksmbd_vfs_inode_permission(struct dentry *dentry, int acc_mode, int ksmbd_vfs_may_delete(struct dentry *dentry);
bool delete);
int ksmbd_vfs_query_maximal_access(struct dentry *dentry, __le32 *daccess); 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_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); int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册