From: Gabriel Krisman Bertazi <krisman@suse.de>
To: Doruk Tan Ozturk <doruk@0sec.ai>, axboe@kernel.dk
Cc: io-uring@vger.kernel.org, Doruk Tan Ozturk <doruk@0sec.ai>
Subject: Re: [PATCH] io_uring/kbuf: free the old cached iovec, not the returned one, on bundle grow
Date: Tue, 14 Jul 2026 10:02:11 -0400 [thread overview]
Message-ID: <87ik6h4ql8.fsf@mailhost.krisman.be> (raw)
In-Reply-To: <20260713183124.4217-1-doruk@0sec.ai>
Doruk Tan Ozturk <doruk@0sec.ai> writes:
> Commit cd053d788c3f ("io_uring: fix dangling iovec after provided-buffer
> bundle grow failure") moved the KBUF_MODE_FREE kfree() out of the expand
> branch to after the validation loop, so the old cached iovec is only
> released once the new buffers have been validated. However, by the time
> control reaches the post-loop free, arg->iovs has already been reassigned
> in the expand branch to the freshly allocated array that is about to be
> returned to the caller:
>
> iov = kmalloc_objs(struct iovec, nr_avail);
> ...
> arg->iovs = iov; /* now the array we return */
> ...
> if (arg->mode & KBUF_MODE_FREE)
> kfree(arg->iovs); /* ... but this frees it */
>
> On a successful grow, io_ring_buffers_peek() therefore frees the very
> iovec array it returns. io_recv_buf_select() then builds an iov_iter over
> that freed array and caches it in kmsg->vec.iovec, giving a
> slab-use-after-free read during the recv copy and a later double free of
> the iovec array on request cleanup. The array is a kmalloc() whose size is
> controlled by the number of ring buffers the caller commits, so the freed
> object lands in an attacker-influenced kmalloc cache.
>
> KBUF_MODE_FREE is meant to release the *old* cached iovec once it has been
> replaced by a larger one. Free the captured org_iovs instead, and only
> when a grow actually happened (arg->iovs != org_iovs) so the no-grow case
> still returns the reused array. The -EFAULT failure path already frees the
> new array and leaves org_iovs for the caller, so it is unaffected.
>
> Reproduced on next-20260710 with KASAN by an unprivileged IORING_OP_RECV
> using IORING_RECVSEND_BUNDLE over a provided-buffer ring: a first
> (expanding) bundle caches a small iovec, and an in-request bundle retry
> grows again under KBUF_MODE_FREE, triggering both the UAF read and the
> double free. The change eliminates the KASAN splat.
>
> Fixes: cd053d788c3f ("io_uring: fix dangling iovec after provided-buffer bundle grow failure")
> Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
Already fixed here
https://lore.kernel.org/io-uring/20260712142612.188695595-iostreampy@proton.me/T/#u
here:
https://lore.kernel.org/io-uring/OS3PR01MB8810F38D613E37FBD684DC4D83FB2@OS3PR01MB8810.jpnprd01.prod.outlook.com/T/#t
and here:
https://lore.kernel.org/io-uring/20260713-io_uring_dangling-v1-1-b9bdc0f0e776@debian.org/T/#u
Aren't LLMs fun?
--
Gabriel Krisman Bertazi
next prev parent reply other threads:[~2026-07-14 14:02 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-13 18:31 [PATCH] io_uring/kbuf: free the old cached iovec, not the returned one, on bundle grow Doruk Tan Ozturk
2026-07-14 14:02 ` Gabriel Krisman Bertazi [this message]
-- strict thread matches above, loose matches on Subject: below --
2026-07-14 14:14 Doruk Tan Ozturk
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=87ik6h4ql8.fsf@mailhost.krisman.be \
--to=krisman@suse.de \
--cc=axboe@kernel.dk \
--cc=doruk@0sec.ai \
--cc=io-uring@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox