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 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.