Skip to content

Commit

Permalink
io_uring/msg_ring: fix missing lock on overflow for IOPOLL
Browse files Browse the repository at this point in the history
If the target ring is configured with IOPOLL, then we always need to hold
the target ring uring_lock before posting CQEs. We could just grab it
unconditionally, but since we don't expect many target rings to be of this
type, make grabbing the uring_lock conditional on the ring type.

Link: https://lore.kernel.org/io-uring/Y8krlYa52%2F0YGqkg@ip-172-31-85-199.ec2.internal/
Reported-by: Xingyuan Mo <hdthky0@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
  • Loading branch information
Jens Axboe committed Jan 19, 2023
1 parent 423d508 commit e12d7a4
Showing 1 changed file with 30 additions and 9 deletions.
39 changes: 30 additions & 9 deletions io_uring/msg_ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,33 @@ static void io_msg_tw_complete(struct callback_head *head)
struct io_ring_ctx *target_ctx = req->file->private_data;
int ret = 0;

if (current->flags & PF_EXITING)
if (current->flags & PF_EXITING) {
ret = -EOWNERDEAD;
else if (!io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
ret = -EOVERFLOW;
} else {
/*
* If the target ring is using IOPOLL mode, then we need to be
* holding the uring_lock for posting completions. Other ring
* types rely on the regular completion locking, which is
* handled while posting.
*/
if (target_ctx->flags & IORING_SETUP_IOPOLL)
mutex_lock(&target_ctx->uring_lock);
if (!io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
ret = -EOVERFLOW;
if (target_ctx->flags & IORING_SETUP_IOPOLL)
mutex_unlock(&target_ctx->uring_lock);
}

if (ret < 0)
req_set_fail(req);
io_req_queue_tw_complete(req, ret);
}

static int io_msg_ring_data(struct io_kiocb *req)
static int io_msg_ring_data(struct io_kiocb *req, unsigned int issue_flags)
{
struct io_ring_ctx *target_ctx = req->file->private_data;
struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg);
int ret;

if (msg->src_fd || msg->dst_fd || msg->flags)
return -EINVAL;
Expand All @@ -93,10 +106,18 @@ static int io_msg_ring_data(struct io_kiocb *req)
return IOU_ISSUE_SKIP_COMPLETE;
}

if (io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
return 0;

return -EOVERFLOW;
ret = -EOVERFLOW;
if (target_ctx->flags & IORING_SETUP_IOPOLL) {
if (unlikely(io_double_lock_ctx(target_ctx, issue_flags)))
return -EAGAIN;
if (io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
ret = 0;
io_double_unlock_ctx(target_ctx);
} else {
if (io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
ret = 0;
}
return ret;
}

static struct file *io_msg_grab_file(struct io_kiocb *req, unsigned int issue_flags)
Expand Down Expand Up @@ -223,7 +244,7 @@ int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags)

switch (msg->cmd) {
case IORING_MSG_DATA:
ret = io_msg_ring_data(req);
ret = io_msg_ring_data(req, issue_flags);
break;
case IORING_MSG_SEND_FD:
ret = io_msg_send_fd(req, issue_flags);
Expand Down

0 comments on commit e12d7a4

Please sign in to comment.