From bcd91b165fa19eed27d64f9c687d07fe0394d15d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 11 Aug 2020 08:04:14 -0600 Subject: [PATCH 2091/2944] io_uring: hold 'ctx' reference around task_work queue + execute to #29998112 commit 6d816e088c359866f9867057e04f244c608c42fe upstream 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 Signed-off-by: Hao Xu Reviewed-by: Joseph Qi --- fs/io_uring.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fs/io_uring.c b/fs/io_uring.c index 7331315..02bcbdf 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2088,6 +2088,8 @@ static void io_rw_resubmit(struct callback_head *cb) refcount_inc(&req->refs); io_queue_async_work(req); } + + percpu_ref_put(&ctx->refs); } #endif @@ -2102,6 +2104,8 @@ static bool io_rw_reissue(struct io_kiocb *req, long res) tsk = req->task; init_task_work(&req->task_work, io_rw_resubmit); + percpu_ref_get(&req->ctx->refs); + ret = task_work_add(tsk, &req->task_work, true); if (!ret) return true; @@ -2814,6 +2818,8 @@ static void io_async_buf_retry(struct callback_head *cb) } else { __io_async_buf_error(req, -EFAULT); } + + percpu_ref_put(&ctx->refs); } static int io_async_buf_func(struct wait_queue_entry *wait, unsigned mode, @@ -2835,6 +2841,8 @@ static int io_async_buf_func(struct wait_queue_entry *wait, unsigned mode, list_del_init(&wait->entry); init_task_work(&rw->task_work, io_async_buf_retry); + percpu_ref_get(&req->ctx->refs); + /* submit ref gets dropped, acquire a new one */ refcount_inc(&req->refs); tsk = req->task; -- 1.8.3.1