Commit 61c1b44a authored by Pavel Begunkov's avatar Pavel Begunkov Committed by Jens Axboe
Browse files

io_uring: fix deadlock on iowq file slot alloc



io_fixed_fd_install() can grab uring_lock in the slot allocation path
when called from io-wq, and then call into io_install_fixed_file(),
which will lock it again. Pull all locking out of
io_install_fixed_file() into io_fixed_fd_install().

Fixes: 1339f24b ("io_uring: allow allocated fixed files for openat/openat2")
Signed-off-by: default avatarPavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/64116172a9d0b85b85300346bb280f3657aafc26.1654087283.git.asml.silence@gmail.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent a7c41b46
Loading
Loading
Loading
Loading
+15 −21
Original line number Diff line number Diff line
@@ -5448,27 +5448,24 @@ static int io_fixed_fd_install(struct io_kiocb *req, unsigned int issue_flags,
	struct io_ring_ctx *ctx = req->ctx;
	int ret;

	if (alloc_slot) {
	io_ring_submit_lock(ctx, issue_flags);
		ret = io_file_bitmap_get(ctx);
		if (unlikely(ret < 0)) {
			io_ring_submit_unlock(ctx, issue_flags);
			fput(file);
			return ret;
		}

	if (alloc_slot) {
		ret = io_file_bitmap_get(ctx);
		if (unlikely(ret < 0))
			goto err;
		file_slot = ret;
	} else {
		file_slot--;
	}

	ret = io_install_fixed_file(req, file, issue_flags, file_slot);
	if (alloc_slot) {
	if (!ret && alloc_slot)
		ret = file_slot;
err:
	io_ring_submit_unlock(ctx, issue_flags);
		if (!ret)
			return file_slot;
	}

	if (unlikely(ret < 0))
		fput(file);
	return ret;
}

@@ -10179,21 +10176,19 @@ static int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx,

static int io_install_fixed_file(struct io_kiocb *req, struct file *file,
				 unsigned int issue_flags, u32 slot_index)
	__must_hold(&req->ctx->uring_lock)
{
	struct io_ring_ctx *ctx = req->ctx;
	bool needs_switch = false;
	struct io_fixed_file *file_slot;
	int ret = -EBADF;
	int ret;

	io_ring_submit_lock(ctx, issue_flags);
	if (file->f_op == &io_uring_fops)
		goto err;
	ret = -ENXIO;
		return -EBADF;
	if (!ctx->file_data)
		goto err;
	ret = -EINVAL;
		return -ENXIO;
	if (slot_index >= ctx->nr_user_files)
		goto err;
		return -EINVAL;

	slot_index = array_index_nospec(slot_index, ctx->nr_user_files);
	file_slot = io_fixed_file_slot(&ctx->file_table, slot_index);
@@ -10224,7 +10219,6 @@ static int io_install_fixed_file(struct io_kiocb *req, struct file *file,
err:
	if (needs_switch)
		io_rsrc_node_switch(ctx, ctx->file_data);
	io_ring_submit_unlock(ctx, issue_flags);
	if (ret)
		fput(file);
	return ret;