mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 1/2] fuse: copy request headers via a stack buffer for io-uring
@ 2026-07-06 19:13 Xiang Mei
  2026-07-06 19:13 ` [PATCH 2/2] fuse: reject oversized payload_sz in fuse_uring_copy_from_ring() Xiang Mei
  2026-07-06 21:17 ` [PATCH 1/2] fuse: copy request headers via a stack buffer for io-uring Joanne Koong
  0 siblings, 2 replies; 7+ messages in thread
From: Xiang Mei @ 2026-07-06 19:13 UTC (permalink / raw)
  To: Bernd Schubert, Joanne Koong, Miklos Szeredi, Kees Cook,
	Gustavo A . R . Silva
  Cc: fuse-devel, linux-kernel, Pavel Begunkov, Luis Henriques,
	Weiming Shi, Xiang Mei

The fuse-io-uring transport copies req->in.h out to the ring in
fuse_uring_copy_to_ring() and req->out.h back in fuse_uring_commit().
Both headers live inside the fuse_request slab object, whose cache
(fuse_req_cachep) is created without a usercopy whitelist, so copying
them directly to/from userspace trips CONFIG_HARDENED_USERCOPY and
panics:

  usercopy: Kernel memory exposure attempt detected from SLUB object
  'fuse_request' (offset 56, size 40)!
  kernel BUG at mm/usercopy.c:102!
  RIP: 0010:usercopy_abort+0x6c/0x80
  Call Trace:
   __check_heap_object
   __check_object_size
   copy_header_to_ring          fs/fuse/dev_uring.c:618
   fuse_uring_prepare_send
   fuse_uring_send_in_task
   ...
   __do_sys_io_uring_enter
   entry_SYSCALL_64_after_hwframe

Bounce both headers through an on-stack copy so the usercopy touches
stack memory, not the slab object.

Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Xiang Mei <xmei5@asu.edu>
---
 fs/fuse/dev_uring.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
index 77c8cec43d9c..0814681eb04b 100644
--- a/fs/fuse/dev_uring.c
+++ b/fs/fuse/dev_uring.c
@@ -744,6 +744,7 @@ static int fuse_uring_copy_to_ring(struct fuse_ring_ent *ent,
 {
 	struct fuse_ring_queue *queue = ent->queue;
 	struct fuse_ring *ring = queue->ring;
+	struct fuse_in_header in_header;
 	int err;
 
 	err = -EIO;
@@ -765,8 +766,9 @@ static int fuse_uring_copy_to_ring(struct fuse_ring_ent *ent,
 	}
 
 	/* copy fuse_in_header */
-	return copy_header_to_ring(ent, FUSE_URING_HEADER_IN_OUT, &req->in.h,
-				   sizeof(req->in.h));
+	in_header = req->in.h;
+	return copy_header_to_ring(ent, FUSE_URING_HEADER_IN_OUT, &in_header,
+				   sizeof(in_header));
 }
 
 static int fuse_uring_prepare_send(struct fuse_ring_ent *ent,
@@ -871,11 +873,13 @@ static void fuse_uring_commit(struct fuse_ring_ent *ent, struct fuse_req *req,
 			      unsigned int issue_flags)
 {
 	struct fuse_ring *ring = ent->queue->ring;
+	struct fuse_out_header out_header;
 	ssize_t err = -EFAULT;
 
-	if (copy_header_from_ring(ent, FUSE_URING_HEADER_IN_OUT, &req->out.h,
-				  sizeof(req->out.h)))
+	if (copy_header_from_ring(ent, FUSE_URING_HEADER_IN_OUT, &out_header,
+				  sizeof(out_header)))
 		goto out;
+	req->out.h = out_header;
 
 	err = fuse_uring_out_header_has_err(&req->out.h, req);
 	if (err) {
-- 
2.43.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/2] fuse: reject oversized payload_sz in fuse_uring_copy_from_ring()
  2026-07-06 19:13 [PATCH 1/2] fuse: copy request headers via a stack buffer for io-uring Xiang Mei
@ 2026-07-06 19:13 ` Xiang Mei
  2026-07-06 21:28   ` Joanne Koong
  2026-07-06 21:17 ` [PATCH 1/2] fuse: copy request headers via a stack buffer for io-uring Joanne Koong
  1 sibling, 1 reply; 7+ messages in thread
From: Xiang Mei @ 2026-07-06 19:13 UTC (permalink / raw)
  To: Bernd Schubert, Joanne Koong, Miklos Szeredi, Kees Cook,
	Gustavo A . R . Silva
  Cc: fuse-devel, linux-kernel, Pavel Begunkov, Luis Henriques,
	Weiming Shi, Xiang Mei

fuse_uring_copy_from_ring() imports the payload buffer with length
ring->max_payload_sz but passes the server-controlled payload_sz to
fuse_copy_out_args() unchecked.  A larger payload_sz drains the iterator
to exhaustion and fuse_copy_fill() hits BUG_ON(!err), panicking the
kernel.  Reject replies whose payload_sz exceeds the imported buffer.

  kernel BUG at fs/fuse/dev.c:1053!
  RIP: 0010:fuse_copy_fill+0x6c6/0x7e0
  Call Trace:
   fuse_copy_args
   fuse_uring_copy_from_ring     fs/fuse/dev_uring.c:686
   fuse_uring_cmd
   io_uring_cmd
   __io_issue_sqe
   io_submit_sqes
   __do_sys_io_uring_enter
   entry_SYSCALL_64_after_hwframe

Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Xiang Mei <xmei5@asu.edu>
---
 fs/fuse/dev_uring.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
index 0814681eb04b..f6127c230dd9 100644
--- a/fs/fuse/dev_uring.c
+++ b/fs/fuse/dev_uring.c
@@ -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 > ring->max_payload_sz)
+		return -EINVAL;
+
 	err = setup_fuse_copy_state(&cs, ring, req, ent, ITER_SOURCE, &iter);
 	if (err)
 		return err;
-- 
2.43.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] fuse: copy request headers via a stack buffer for io-uring
  2026-07-06 19:13 [PATCH 1/2] fuse: copy request headers via a stack buffer for io-uring Xiang Mei
  2026-07-06 19:13 ` [PATCH 2/2] fuse: reject oversized payload_sz in fuse_uring_copy_from_ring() Xiang Mei
@ 2026-07-06 21:17 ` Joanne Koong
  2026-07-07  5:40   ` Darrick J. Wong
  1 sibling, 1 reply; 7+ messages in thread
From: Joanne Koong @ 2026-07-06 21:17 UTC (permalink / raw)
  To: Xiang Mei
  Cc: Bernd Schubert, Miklos Szeredi, Kees Cook, Gustavo A . R . Silva,
	fuse-devel, linux-kernel, Pavel Begunkov, Luis Henriques,
	Weiming Shi, stable

On Mon, Jul 6, 2026 at 12:13 PM Xiang Mei <xmei5@asu.edu> wrote:
>
> The fuse-io-uring transport copies req->in.h out to the ring in
> fuse_uring_copy_to_ring() and req->out.h back in fuse_uring_commit().
> Both headers live inside the fuse_request slab object, whose cache
> (fuse_req_cachep) is created without a usercopy whitelist, so copying
> them directly to/from userspace trips CONFIG_HARDENED_USERCOPY and
> panics:
>
>   usercopy: Kernel memory exposure attempt detected from SLUB object
>   'fuse_request' (offset 56, size 40)!
>   kernel BUG at mm/usercopy.c:102!
>   RIP: 0010:usercopy_abort+0x6c/0x80
>   Call Trace:
>    __check_heap_object
>    __check_object_size
>    copy_header_to_ring          fs/fuse/dev_uring.c:618
>    fuse_uring_prepare_send
>    fuse_uring_send_in_task
>    ...
>    __do_sys_io_uring_enter
>    entry_SYSCALL_64_after_hwframe
>
> Bounce both headers through an on-stack copy so the usercopy touches
> stack memory, not the slab object.
>
> Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support")
> Reported-by: Weiming Shi <bestswngs@gmail.com>
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Xiang Mei <xmei5@asu.edu>

Reviewed-by: Joanne Koong <joannelkoong@gmail.com>

I think the cc stable@vger.kernel.org tag is missing here. I added
stable@ to the cc list on this email, but I'm not sure if they require
the tag being explicitly in the commit message to get it backported.

Thanks,
Joanne

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] fuse: reject oversized payload_sz in fuse_uring_copy_from_ring()
  2026-07-06 19:13 ` [PATCH 2/2] fuse: reject oversized payload_sz in fuse_uring_copy_from_ring() Xiang Mei
@ 2026-07-06 21:28   ` Joanne Koong
  2026-07-07 18:35     ` Xiang Mei
  0 siblings, 1 reply; 7+ messages in thread
From: Joanne Koong @ 2026-07-06 21:28 UTC (permalink / raw)
  To: Xiang Mei
  Cc: Bernd Schubert, Miklos Szeredi, Kees Cook, Gustavo A . R . Silva,
	fuse-devel, linux-kernel, Pavel Begunkov, Luis Henriques,
	Weiming Shi, stable

On Mon, Jul 6, 2026 at 12:13 PM Xiang Mei <xmei5@asu.edu> wrote:
>
> fuse_uring_copy_from_ring() imports the payload buffer with length
> ring->max_payload_sz but passes the server-controlled payload_sz to
> fuse_copy_out_args() unchecked.  A larger payload_sz drains the iterator
> to exhaustion and fuse_copy_fill() hits BUG_ON(!err), panicking the
> kernel.  Reject replies whose payload_sz exceeds the imported buffer.
>
>   kernel BUG at fs/fuse/dev.c:1053!
>   RIP: 0010:fuse_copy_fill+0x6c6/0x7e0
>   Call Trace:
>    fuse_copy_args
>    fuse_uring_copy_from_ring     fs/fuse/dev_uring.c:686
>    fuse_uring_cmd
>    io_uring_cmd
>    __io_issue_sqe
>    io_submit_sqes
>    __do_sys_io_uring_enter
>    entry_SYSCALL_64_after_hwframe
>
> Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support")
> Reported-by: Weiming Shi <bestswngs@gmail.com>
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Xiang Mei <xmei5@asu.edu>
> ---
>  fs/fuse/dev_uring.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
> index 0814681eb04b..f6127c230dd9 100644
> --- a/fs/fuse/dev_uring.c
> +++ b/fs/fuse/dev_uring.c
> @@ -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 > ring->max_payload_sz)
> +               return -EINVAL;
> +
>         err = setup_fuse_copy_state(&cs, ring, req, ent, ITER_SOURCE, &iter);
>         if (err)
>                 return err;
> --
> 2.43.0
>

Makes sense to me. Thanks for including the stack trace in the commit message.

Reviewed-by: Joanne Koong <joannelkoong@gmail.com>

Same comment about stable@ as in the other patch - not sure if the
commit message has to explicitly include the tag.

Thanks,
Joanne

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] fuse: copy request headers via a stack buffer for io-uring
  2026-07-06 21:17 ` [PATCH 1/2] fuse: copy request headers via a stack buffer for io-uring Joanne Koong
@ 2026-07-07  5:40   ` Darrick J. Wong
  2026-07-07 18:29     ` Xiang Mei
  0 siblings, 1 reply; 7+ messages in thread
From: Darrick J. Wong @ 2026-07-07  5:40 UTC (permalink / raw)
  To: Joanne Koong
  Cc: Xiang Mei, Bernd Schubert, Miklos Szeredi, Kees Cook,
	Gustavo A . R . Silva, fuse-devel, linux-kernel, Pavel Begunkov,
	Luis Henriques, Weiming Shi, stable

On Mon, Jul 06, 2026 at 02:17:12PM -0700, Joanne Koong wrote:
> On Mon, Jul 6, 2026 at 12:13 PM Xiang Mei <xmei5@asu.edu> wrote:
> >
> > The fuse-io-uring transport copies req->in.h out to the ring in
> > fuse_uring_copy_to_ring() and req->out.h back in fuse_uring_commit().
> > Both headers live inside the fuse_request slab object, whose cache
> > (fuse_req_cachep) is created without a usercopy whitelist, so copying
> > them directly to/from userspace trips CONFIG_HARDENED_USERCOPY and
> > panics:
> >
> >   usercopy: Kernel memory exposure attempt detected from SLUB object
> >   'fuse_request' (offset 56, size 40)!
> >   kernel BUG at mm/usercopy.c:102!
> >   RIP: 0010:usercopy_abort+0x6c/0x80
> >   Call Trace:
> >    __check_heap_object
> >    __check_object_size
> >    copy_header_to_ring          fs/fuse/dev_uring.c:618
> >    fuse_uring_prepare_send
> >    fuse_uring_send_in_task
> >    ...
> >    __do_sys_io_uring_enter
> >    entry_SYSCALL_64_after_hwframe
> >
> > Bounce both headers through an on-stack copy so the usercopy touches
> > stack memory, not the slab object.
> >
> > Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support")
> > Reported-by: Weiming Shi <bestswngs@gmail.com>
> > Assisted-by: Claude:claude-opus-4-8
> > Signed-off-by: Xiang Mei <xmei5@asu.edu>
> 
> Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
> 
> I think the cc stable@vger.kernel.org tag is missing here. I added
> stable@ to the cc list on this email, but I'm not sure if they require
> the tag being explicitly in the commit message to get it backported.

I used to like it for XFS once upon a time when we did manual reviews
and QA of LTS branches, because it was a headsup for something that I
should actually watch to make sure it actually showed up in stable-rc.

--D

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] fuse: copy request headers via a stack buffer for io-uring
  2026-07-07  5:40   ` Darrick J. Wong
@ 2026-07-07 18:29     ` Xiang Mei
  0 siblings, 0 replies; 7+ messages in thread
From: Xiang Mei @ 2026-07-07 18:29 UTC (permalink / raw)
  To: Darrick J. Wong
  Cc: Joanne Koong, Bernd Schubert, Miklos Szeredi, Kees Cook,
	Gustavo A . R . Silva, fuse-devel, linux-kernel, Pavel Begunkov,
	Luis Henriques, Weiming Shi, stable

On Mon, Jul 6, 2026 at 10:40 PM Darrick J. Wong <djwong@kernel.org> wrote:
>
> On Mon, Jul 06, 2026 at 02:17:12PM -0700, Joanne Koong wrote:
> > On Mon, Jul 6, 2026 at 12:13 PM Xiang Mei <xmei5@asu.edu> wrote:
> > >
> > > The fuse-io-uring transport copies req->in.h out to the ring in
> > > fuse_uring_copy_to_ring() and req->out.h back in fuse_uring_commit().
> > > Both headers live inside the fuse_request slab object, whose cache
> > > (fuse_req_cachep) is created without a usercopy whitelist, so copying
> > > them directly to/from userspace trips CONFIG_HARDENED_USERCOPY and
> > > panics:
> > >
> > >   usercopy: Kernel memory exposure attempt detected from SLUB object
> > >   'fuse_request' (offset 56, size 40)!
> > >   kernel BUG at mm/usercopy.c:102!
> > >   RIP: 0010:usercopy_abort+0x6c/0x80
> > >   Call Trace:
> > >    __check_heap_object
> > >    __check_object_size
> > >    copy_header_to_ring          fs/fuse/dev_uring.c:618
> > >    fuse_uring_prepare_send
> > >    fuse_uring_send_in_task
> > >    ...
> > >    __do_sys_io_uring_enter
> > >    entry_SYSCALL_64_after_hwframe
> > >
> > > Bounce both headers through an on-stack copy so the usercopy touches
> > > stack memory, not the slab object.
> > >
> > > Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support")
> > > Reported-by: Weiming Shi <bestswngs@gmail.com>
> > > Assisted-by: Claude:claude-opus-4-8
> > > Signed-off-by: Xiang Mei <xmei5@asu.edu>
> >
> > Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
> >
> > I think the cc stable@vger.kernel.org tag is missing here. I added
> > stable@ to the cc list on this email, but I'm not sure if they require
> > the tag being explicitly in the commit message to get it backported.
>
> I used to like it for XFS once upon a time when we did manual reviews
> and QA of LTS branches, because it was a headsup for something that I
> should actually watch to make sure it actually showed up in stable-rc.
>
> --D

Hi Joanne, Darrick,

Thanks for the review!

From what I've observed, the "Fixes:" tag alone is often enough to get
a patch backported, though I'm not certain that's guaranteed.  Adding
the explicit "Cc: stable@vger.kernel.org" tag makes it reliable either
way; feel free to let me know if we need a v2.

Xiang

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] fuse: reject oversized payload_sz in fuse_uring_copy_from_ring()
  2026-07-06 21:28   ` Joanne Koong
@ 2026-07-07 18:35     ` Xiang Mei
  0 siblings, 0 replies; 7+ messages in thread
From: Xiang Mei @ 2026-07-07 18:35 UTC (permalink / raw)
  To: Joanne Koong
  Cc: Bernd Schubert, Miklos Szeredi, Kees Cook, Gustavo A . R . Silva,
	fuse-devel, linux-kernel, Pavel Begunkov, Luis Henriques,
	Weiming Shi, stable

On Mon, Jul 6, 2026 at 2:29 PM Joanne Koong <joannelkoong@gmail.com> wrote:
>
> On Mon, Jul 6, 2026 at 12:13 PM Xiang Mei <xmei5@asu.edu> wrote:
> >
> > fuse_uring_copy_from_ring() imports the payload buffer with length
> > ring->max_payload_sz but passes the server-controlled payload_sz to
> > fuse_copy_out_args() unchecked.  A larger payload_sz drains the iterator
> > to exhaustion and fuse_copy_fill() hits BUG_ON(!err), panicking the
> > kernel.  Reject replies whose payload_sz exceeds the imported buffer.
> >
> >   kernel BUG at fs/fuse/dev.c:1053!
> >   RIP: 0010:fuse_copy_fill+0x6c6/0x7e0
> >   Call Trace:
> >    fuse_copy_args
> >    fuse_uring_copy_from_ring     fs/fuse/dev_uring.c:686
> >    fuse_uring_cmd
> >    io_uring_cmd
> >    __io_issue_sqe
> >    io_submit_sqes
> >    __do_sys_io_uring_enter
> >    entry_SYSCALL_64_after_hwframe
> >
> > Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support")
> > Reported-by: Weiming Shi <bestswngs@gmail.com>
> > Assisted-by: Claude:claude-opus-4-8
> > Signed-off-by: Xiang Mei <xmei5@asu.edu>
> > ---
> >  fs/fuse/dev_uring.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
> > index 0814681eb04b..f6127c230dd9 100644
> > --- a/fs/fuse/dev_uring.c
> > +++ b/fs/fuse/dev_uring.c
> > @@ -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 > ring->max_payload_sz)
> > +               return -EINVAL;
> > +
> >         err = setup_fuse_copy_state(&cs, ring, req, ent, ITER_SOURCE, &iter);
> >         if (err)
> >                 return err;
> > --
> > 2.43.0
> >
>
> Makes sense to me. Thanks for including the stack trace in the commit message.
>
> Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
>
> Same comment about stable@ as in the other patch - not sure if the
> commit message has to explicitly include the tag.
>
Thanks for your review. To ensure it's backported, I'll send a v2 with
cc'ing stable.

Xiang
> Thanks,
> Joanne

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-07-07 18:35 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-06 19:13 [PATCH 1/2] fuse: copy request headers via a stack buffer for io-uring Xiang Mei
2026-07-06 19:13 ` [PATCH 2/2] fuse: reject oversized payload_sz in fuse_uring_copy_from_ring() Xiang Mei
2026-07-06 21:28   ` Joanne Koong
2026-07-07 18:35     ` Xiang Mei
2026-07-06 21:17 ` [PATCH 1/2] fuse: copy request headers via a stack buffer for io-uring Joanne Koong
2026-07-07  5:40   ` Darrick J. Wong
2026-07-07 18:29     ` Xiang Mei

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox