Commit d5f06f27 authored by Bing-Jhong Billy Jheng's avatar Bing-Jhong Billy Jheng Committed by Jialin Zhang
Browse files

io_uring: add missing lock in io_get_file_fixed

stable inclusion
from stable-v5.10.171
commit 08681391b84da27133deefaaddefd0acfa90c2be
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I6V7V1
CVE: CVE-2023-1872

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=08681391b84da27133deefaaddefd0acfa90c2be



--------------------------------

io_get_file_fixed will access io_uring's context. Lock it if it is
invoked unlocked (eg via io-wq) to avoid a race condition with fixed
files getting unregistered.

No single upstream patch exists for this issue, it was fixed as part
of the file assignment changes that went into the 5.18 cycle.

Signed-off-by: default avatarJheng, Bing-Jhong Billy <billy@starlabs.sg>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarZhaoLong Wang <wangzhaolong1@huawei.com>
Reviewed-by: default avatarZhang Yi <yi.zhang@huawei.com>
Reviewed-by: default avatarXiu Jianfeng <xiujianfeng@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parent 9895e9ad
Loading
Loading
Loading
Loading
+16 −9
Original line number Diff line number Diff line
@@ -1090,7 +1090,8 @@ static int __io_register_rsrc_update(struct io_ring_ctx *ctx, unsigned type,
				     unsigned nr_args);
static void io_clean_op(struct io_kiocb *req);
static struct file *io_file_get(struct io_ring_ctx *ctx,
				struct io_kiocb *req, int fd, bool fixed);
				struct io_kiocb *req, int fd, bool fixed,
				unsigned int issue_flags);
static void __io_queue_sqe(struct io_kiocb *req);
static void io_rsrc_put_work(struct work_struct *work);

@@ -3914,7 +3915,7 @@ static int io_tee(struct io_kiocb *req, unsigned int issue_flags)
		return -EAGAIN;

	in = io_file_get(req->ctx, req, sp->splice_fd_in,
				  (sp->flags & SPLICE_F_FD_IN_FIXED));
			 (sp->flags & SPLICE_F_FD_IN_FIXED), issue_flags);
	if (!in) {
		ret = -EBADF;
		goto done;
@@ -3954,7 +3955,7 @@ static int io_splice(struct io_kiocb *req, unsigned int issue_flags)
		return -EAGAIN;

	in = io_file_get(req->ctx, req, sp->splice_fd_in,
				  (sp->flags & SPLICE_F_FD_IN_FIXED));
			 (sp->flags & SPLICE_F_FD_IN_FIXED), issue_flags);
	if (!in) {
		ret = -EBADF;
		goto done;
@@ -6742,13 +6743,16 @@ static void io_fixed_file_set(struct io_fixed_file *file_slot, struct file *file
}

static inline struct file *io_file_get_fixed(struct io_ring_ctx *ctx,
					     struct io_kiocb *req, int fd)
					     struct io_kiocb *req, int fd,
					     unsigned int issue_flags)
{
	struct file *file;
	struct file *file = NULL;
	unsigned long file_ptr;

	io_ring_submit_lock(ctx, !(issue_flags & IO_URING_F_NONBLOCK));

	if (unlikely((unsigned int)fd >= ctx->nr_user_files))
		return NULL;
		goto out;
	fd = array_index_nospec(fd, ctx->nr_user_files);
	file_ptr = io_fixed_file_slot(&ctx->file_table, fd)->file_ptr;
	file = (struct file *) (file_ptr & FFS_MASK);
@@ -6756,6 +6760,8 @@ static inline struct file *io_file_get_fixed(struct io_ring_ctx *ctx,
	/* mask in overlapping REQ_F and FFS bits */
	req->flags |= (file_ptr << REQ_F_NOWAIT_READ_BIT);
	io_req_set_rsrc_node(req);
out:
	io_ring_submit_unlock(ctx, !(issue_flags & IO_URING_F_NONBLOCK));
	return file;
}

@@ -6773,10 +6779,11 @@ static struct file *io_file_get_normal(struct io_ring_ctx *ctx,
}

static inline struct file *io_file_get(struct io_ring_ctx *ctx,
				       struct io_kiocb *req, int fd, bool fixed)
				       struct io_kiocb *req, int fd, bool fixed,
				       unsigned int issue_flags)
{
	if (fixed)
		return io_file_get_fixed(ctx, req, fd);
		return io_file_get_fixed(ctx, req, fd, issue_flags);
	else
		return io_file_get_normal(ctx, req, fd);
}
@@ -6998,7 +7005,7 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,

	if (io_op_defs[req->opcode].needs_file) {
		req->file = io_file_get(ctx, req, READ_ONCE(sqe->fd),
					(sqe_flags & IOSQE_FIXED_FILE));
					(sqe_flags & IOSQE_FIXED_FILE), 0);
		if (unlikely(!req->file))
			ret = -EBADF;
	}