Re: [PATCH v3 2/2] fuse: bound io-uring payload copies to the registered buffer size

Xiang Mei <[email protected]>
Newsgroups org.kernel.vger.linux-hardening,dev.linux.lists.fuse-devel,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <CAPpSM+QQ0BRuVizUePYBj9+UJC0Sxsg1RpEa_u1woShg-TkRhg@mail.gmail.com>
On Mon, Jul 13, 2026 at 10:24 AM Joanne Koong <[email protected]> wrote:
>
> On Thu, Jul 9, 2026 at 2:11 PM Xiang Mei <[email protected]> wrote:
> >
> > The fuse-io-uring transport imports each ring entry's payload buffer at
> > ring->max_payload_sz and bounds both copy directions against that value,
> > ignoring the buffer length the server actually registered.  Both the
> > server-supplied reply payload_sz (fuse_uring_copy_from_ring) and an
> > oversized request payload such as a large FUSE_SETXATTR value
> > (fuse_uring_args_to_ring) can then overrun the imported iterator and hit
> > fuse_copy_fill()'s BUG_ON(!err):
> >
> >   kernel BUG at fs/fuse/dev.c:1053!
> >   Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
> >   RIP: 0010:fuse_copy_fill (fs/fuse/dev.c:1022)
> >   Call Trace:
> >    fuse_copy_args (fs/fuse/dev.c:1329 fs/fuse/dev.c:1351)
> >    fuse_uring_copy_from_ring (fs/fuse/dev_uring.c:686)
> >    fuse_uring_cmd (fs/fuse/dev_uring.c:1226)
> >    io_uring_cmd (io_uring/uring_cmd.c:271)
> >    __io_issue_sqe (io_uring/io_uring.c:1395)
> >    io_issue_sqe (io_uring/io_uring.c:1418)
> >    io_submit_sqes (io_uring/io_uring.c:1649 io_uring/io_uring.c:1934 io_uring/io_uring.c:2057)
> >    __do_sys_io_uring_enter (io_uring/io_uring.c:2646)
> >    do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94)
> >    entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
> >
> > The request path overruns the same way, via fuse_copy_args() ->
> > fuse_uring_args_to_ring().
> >
> > Store the registered payload length (payload->iov_len) in the ring entry
> > and use it for the import and both bounds checks, so the buffer the
> > server provided is honoured and an oversized reply/request is rejected
> > (-EINVAL for a reply, and -E2BIG/-EIO for a request, matching
> > fuse_dev_do_read()) instead of panicking.
> >
> > Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support")
> > Cc: [email protected]
> > Reported-by: Weiming Shi <[email protected]>
> > Assisted-by: Claude:claude-opus-4-8
> > Signed-off-by: Xiang Mei <[email protected]>
> > ---
> > v3: propose the patch fixing another issue found by Bernd by Joanne suggested way
> >
> >  fs/fuse/dev_uring.c   | 9 ++++++++-
> >  fs/fuse/dev_uring_i.h | 1 +
> >  2 files changed, 9 insertions(+), 1 deletion(-)
> >
> > diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
> > index 0814681eb04b..248e5a3e340e 100644
> > --- a/fs/fuse/dev_uring.c
> > +++ b/fs/fuse/dev_uring.c
> > @@ -650,7 +650,7 @@ static int setup_fuse_copy_state(struct fuse_copy_state *cs,
> >  {
> >         int err;
> >
> > -       err = import_ubuf(dir, ent->payload, ring->max_payload_sz, iter);
> > +       err = import_ubuf(dir, ent->payload, ent->payload_sz, iter);
> >         if (err) {
> >                 pr_info_ratelimited("fuse: Import of user buffer failed\n");
> >                 return err;
> > @@ -679,6 +679,9 @@ static int fuse_uring_copy_from_ring(struct fuse_ring *ring,
> >         if (err)
> >                 return err;
> >
> > +       if (ring_in_out.payload_sz > ent->payload_sz)
> > +               return -EINVAL;
> > +
> >         err = setup_fuse_copy_state(&cs, ring, req, ent, ITER_SOURCE, &iter);
> >         if (err)
> >                 return err;
> > @@ -725,6 +728,9 @@ static int fuse_uring_args_to_ring(struct fuse_ring *ring, struct fuse_req *req,
> >                 num_args--;
> >         }
> >
> > +       if (fuse_len_args(num_args, (struct fuse_arg *)in_args) > ent->payload_sz)
> > +               return args->opcode == FUSE_SETXATTR ? -E2BIG : -EIO;
>
> Reviewed-by: Joanne Koong <[email protected]>
>
> Not saying you have to do this, but if you wanted to, I think it'd be
> nice to have a separate cleanup patch that deduplicates this setxattr
> special casing logic between the /dev/fuse path and here.
>
> Thanks,
> Joanne

Thanks for your review. I updated my 1/2 to make it an elegant patch
and added your suggested cleanup as 3/3.
1/3: drop previous tags; reserve the fields for user copy
https://lore.kernel.org/fuse-devel/[email protected]/T/#t
2/3: no change
https://lore.kernel.org/fuse-devel/[email protected]/T/#t
3/3: add a helper to return the correct error code
https://lore.kernel.org/fuse-devel/[email protected]/T/#t

Xiang
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.