From: Jens Axboe <axboe@kernel.dk>
To: "Jérémy Jean" <Jeremy.Jean@oss.cyber.gouv.fr>
Cc: io-uring@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] io_uring/sqpoll: pin task across task-work publication
Date: Thu, 24 Sep 2026 17:32:54 -0600 [thread overview]
Message-ID: <39b2bee2-84d1-498b-a5e0-1f2307bd31d3@kernel.dk> (raw)
In-Reply-To: <096d996d-3028-41ea-bf0c-f7eef1281fcb@kernel.dk>
On 9/24/26 4:59 PM, Jens Axboe wrote:
> On 9/24/26 2:50 PM, J?r?my Jean wrote:
>> SQPOLL can consume a request immediately after mpscq_push(). If this
>> drops the final ring reference, ctx and tctx may be freed before
>> io_req_normal_work_add() finishes using them. KASAN reports:
>>
>> BUG: KASAN: slab-use-after-free in io_req_normal_work_add+0x439/0x510
>> Read of size 4 at addr ff11000000ca0000 by task repro/55
>> (...)
>> BUG: KASAN: slab-use-after-free in queue_work_on+0x25/0x70
>> Write of size 8 at addr ff11000000c3bd00 by task repro/55
>>
>> Handle SQPOLL before publication. Pin tctx->task, publish the request,
>> then use only the pinned task so the publication tail cannot dereference
>> freed contexts.
>>
>> Fixes: af5d68f8892f ("io_uring/sqpoll: manage task_work privately")
>
> Was going to say this isn't correct, as the mpscq is newer than that.
> But I suppose this already existed before that, with the previous switch
> to private task work for SQPOLL? I'll dig into that a bit...
>
>> diff --git a/io_uring/tw.c b/io_uring/tw.c
>> index f573bcc3af6a..2e37a3fd7a33 100644
>> --- a/io_uring/tw.c
>> +++ b/io_uring/tw.c
>> @@ -210,6 +210,19 @@ void io_req_normal_work_add(struct io_kiocb *req)
>> struct io_uring_task *tctx = req->tctx;
>> struct io_ring_ctx *ctx = req->ctx;
>>
>> + /* SQPOLL may consume and retire the request immediately after push. */
>> + if (ctx->flags & IORING_SETUP_SQPOLL) {
>> + struct task_struct *task = tctx->task;
>> + bool first;
>> +
>> + get_task_struct(task);
>> + first = mpscq_push(&tctx->task_list, &req->io_task_work.node);
>> + if (first)
>> + __set_notify_signal(task);
>> + put_task_struct(task);
>> + return;
>> + }
>
> There's no point in having a 'first' variable. LLM's love bools...
>
> if (mpscq_push(&tctx->task_list, &req->io_task_work.node))
> __set_notify_signal(task);
>
> would be better.
Thinking about this a bit more, I think the following fix would be
better:
1) Add a guard(rcu)(); in io_req_normal_work_add() at the top, which is
how we handle this for DEFER_TASKRUN as well.
2) And similarly, expand the synchronize_rcu() run in
io_ring_exit_work() to also include IORING_SETUP_SQPOLL.
I think that's both a cleaner and more efficient fix, rather than fiddle
with task_struct references.
--
Jens Axboe
prev parent reply other threads:[~2026-09-24 23:32 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-24 20:50 [PATCH] io_uring/sqpoll: pin task across task-work publication Jérémy Jean
2026-09-24 22:59 ` Jens Axboe
2026-09-24 23:32 ` Jens Axboe [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=39b2bee2-84d1-498b-a5e0-1f2307bd31d3@kernel.dk \
--to=axboe@kernel.dk \
--cc=Jeremy.Jean@oss.cyber.gouv.fr \
--cc=io-uring@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.