Re: [PATCH v4 1/3] fuse: whitelist the request headers for usercopy
From: Xiang Mei
Date: Mon Jul 27 2026 - 19:41:27 EST
On Wed, Jul 15, 2026 at 2:59 PM Bernd Schubert <bernd@xxxxxxxxxxx> wrote:
>
>
>
> On 7/15/26 20:13, Joanne Koong wrote:
> > On Tue, Jul 14, 2026 at 4:54 PM Xiang Mei <xmei5@xxxxxxx> 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!
> >> Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
> >> RIP: 0010:usercopy_abort (mm/usercopy.c:90)
> >> Call Trace:
> >> __check_heap_object (mm/slub.c:8268)
> >> __check_object_size (mm/usercopy.c:197 mm/usercopy.c:258 mm/usercopy.c:223)
> >> copy_header_to_ring (fs/fuse/dev_uring.c:618)
> >> fuse_uring_prepare_send (fs/fuse/dev_uring.c:776 fs/fuse/dev_uring.c:785)
> >> fuse_uring_send_in_task (fs/fuse/dev_uring.c:1306)
> >> tctx_task_work_run (io_uring/tw.c:96)
> >> task_work_run (kernel/task_work.c:233)
> >> io_run_task_work (io_uring/tw.h:84)
> >> io_cqring_wait (io_uring/wait.c:278)
> >> __do_sys_io_uring_enter (io_uring/io_uring.c:2685)
> >> entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
> >>
> >> in.h and out.h are adjacent in struct fuse_req, so a single usercopy
> >> region starting at in.h covers both and nothing else. Create the cache
> >> with that region whitelisted.
> >>
> >> Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support")
> >> Cc: stable@xxxxxxxxxxxxxxx
> >> Reported-by: Weiming Shi <bestswngs@xxxxxxxxx>
> >> Suggested-by: Baokun Li <libaokun@xxxxxxxxxxxxxxxxx>
> >> Assisted-by: Claude:claude-opus-4-8
> >> Signed-off-by: Xiang Mei <xmei5@xxxxxxx>
> >> ---
> >> v3: no context change; add Bernd's Reviewed-by
> >> v4: drop previous tags; use kmem_cache_args to reserve usercopy area
> >>
> >> fs/fuse/dev.c | 9 +++++++--
> >> fs/fuse/fuse_dev_i.h | 5 +++++
> >> 2 files changed, 12 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
> >> index 5763a7cd3b37..b8e43e374b35 100644
> >> --- a/fs/fuse/dev.c
> >> +++ b/fs/fuse/dev.c
> >> @@ -2404,10 +2404,15 @@ static struct miscdevice fuse_miscdevice = {
> >>
> >> int __init fuse_dev_init(void)
> >> {
> >> + struct kmem_cache_args args = {
> >> + .useroffset = offsetof(struct fuse_req, in.h),
> >> + .usersize = sizeof_field(struct fuse_req, in.h) +
> >> + sizeof_field(struct fuse_req, out.h),
> >> + };
> >> int err = -ENOMEM;
> >> +
> >> fuse_req_cachep = kmem_cache_create("fuse_request",
> >> - sizeof(struct fuse_req),
> >> - 0, 0, NULL);
> >> + sizeof(struct fuse_req), &args, 0);
> >> if (!fuse_req_cachep)
> >> goto out;
> >>
> >> diff --git a/fs/fuse/fuse_dev_i.h b/fs/fuse/fuse_dev_i.h
> >> index 668c8391d61c..b511aaab6bfc 100644
> >> --- a/fs/fuse/fuse_dev_i.h
> >> +++ b/fs/fuse/fuse_dev_i.h
> >> @@ -81,6 +81,11 @@ struct fuse_req {
> >> /** @flags: Request flags, updated with test/set/clear_bit() */
> >> unsigned long flags;
> >>
> >> + /*
> >> + * @in and @out are the usercopy region of this cache (see
> >> + * fuse_dev_init()); keep them adjacent.
> >> + */
> >> +
> >> /** @in: The request input header */
> >> struct {
> >> /** @in.h: The request input header */
> >> --
> >> 2.43.0
> >>
> >
> > I think this is more a matter of preference as they're both
> > functionally correct but imo the previous approach seemed cleaner,
> > given that only the io-uring path needs this. The extra hop goes
> > through a tmp stack variable whose memory is already in the L1 cache
> > and the memcpys are small (~40 bytes), so I think the cost is
> > essentially negligible. Not sure if Bernd or Miklos or Amir have a
> > preference here.
>
> Sorry for late replies, currently on vacation and reviews only when
> everyone else is asleep.
>
> I don't have a strong opinion, I wondered the same if the stack copy was
> avoidable, but then came to the same conclusion as Joanne - negligible
> overhead.
>
>
> Thanks,
> Bernd
Sorry for the late reply. I just got some free time to continue the
patch. Thanks for all of your review and advice. I'll keep the code
simple and just use the stack var to fix it for 1/3 and add Joanne's
suggested comment to 3/3.
The v5 has been sent:
https://lore.kernel.org/fuse-devel/20260727233706.218446-1-xmei5@xxxxxxx/T/#t
Thanks so much!
Xiang
Xiang