Skip to content

Commit e0b245f

Browse files
Jiufei Xuecasparant
authored andcommitted
io_uring: hold 'ctx' reference around task_work queue + execute
fix #29820404 commit 6d816e0 linux-block/io_uring-5.9 branch. We're holding the request reference, but we need to go one higher to ensure that the ctx remains valid after the request has finished. If the ring is closed with pending task_work inflight, and the given io_kiocb finishes sync during issue, then we need a reference to the ring itself around the task_work execution cycle. Cc: stable@vger.kernel.org # v5.7+ Reported-by: syzbot+9b260fc33297966f5a8e@syzkaller.appspotmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Jiufei Xue <jiufei.xue@linux.alibaba.com> Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
1 parent 329479e commit e0b245f

1 file changed

Lines changed: 5 additions & 0 deletions

File tree

fs/io_uring.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4089,6 +4089,7 @@ static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll,
40894089

40904090
tsk = req->task;
40914091
req->result = mask;
4092+
percpu_ref_get(&req->ctx->refs);
40924093
init_task_work(&req->task_work, func);
40934094
/*
40944095
* If this fails, then the task is exiting. When a task exits, the
@@ -4174,6 +4175,7 @@ static void io_poll_task_handler(struct io_kiocb *req, struct io_kiocb **nxt)
41744175
static void io_poll_task_func(struct callback_head *cb)
41754176
{
41764177
struct io_kiocb *req = container_of(cb, struct io_kiocb, task_work);
4178+
struct io_ring_ctx *ctx = req->ctx;
41774179
struct io_kiocb *nxt = NULL;
41784180

41794181
io_poll_task_handler(req, &nxt);
@@ -4184,6 +4186,7 @@ static void io_poll_task_func(struct callback_head *cb)
41844186
__io_queue_sqe(nxt, NULL);
41854187
mutex_unlock(&ctx->uring_lock);
41864188
}
4189+
percpu_ref_put(&ctx->refs);
41874190
}
41884191

41894192
static int io_poll_double_wake(struct wait_queue_entry *wait, unsigned mode,
@@ -4298,6 +4301,7 @@ static void io_async_task_func(struct callback_head *cb)
42984301

42994302
if (io_poll_rewait(req, &apoll->poll)) {
43004303
spin_unlock_irq(&ctx->completion_lock);
4304+
percpu_ref_put(&ctx->refs);
43014305
return;
43024306
}
43034307

@@ -4336,6 +4340,7 @@ static void io_async_task_func(struct callback_head *cb)
43364340
req_set_fail_links(req);
43374341
io_double_put_req(req);
43384342
}
4343+
percpu_ref_put(&ctx->refs);
43394344
}
43404345

43414346
static int io_async_wake(struct wait_queue_entry *wait, unsigned mode, int sync,

0 commit comments

Comments
 (0)