Re: [BUG] fuse: KASAN null-ptr-deref in fuse_readpages_end after aborted splice read reply
From: Joanne Koong
Date: Tue Jun 09 2026 - 17:40:59 EST
On Tue, Jun 9, 2026 at 2:36 PM 김민서 <neck3922@xxxxxxxxx> wrote:
>
> Hello,
>
> I am reporting a FUSE read-reply bug reproduced on upstream v7.1-rc7
> with KASAN enabled. The bug was found with a local syzkaller setup and
> was also reproduced with a standalone C reproducer.
>
> Target files:
> fs/fuse/file.c
> fs/fuse/dev.c
> Subsystem: FUSE
> Git tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
> Git head: 4549871118cf616eecdd2d939f78e3b9e1dddc48
> Kernel release: v7.1-rc7
>
> Observed crash:
>
> KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
> RIP: fuse_readpages_end+0xe5/0x650
>
> The same reproducer may also sometimes surface later as:
>
> RIP: iomap_finish_folio_read+0x163/0x230
>
> Call Trace:
> fuse_readpages_end
> fuse_request_end
> fuse_dev_do_write
> fuse_dev_splice_write
> do_splice
> __do_splice
> __x64_sys_splice
> do_syscall_64
>
> Root cause analysis:
>
> The crash appears to involve the FUSE splice read reply path replacing a
> page cache folio while or shortly after the corresponding FUSE request is
> aborted.
>
> In fs/fuse/dev.c, fuse_try_move_folio() does:
>
> replace_page_cache_folio(oldfolio, newfolio);
> ...
> if (test_bit(FR_ABORTED, &cs->req->flags))
> err = -ENOENT;
> else
> *foliop = newfolio;
>
> My current understanding is that replace_page_cache_folio() can detach
> the old folio from its mapping. If FR_ABORTED is observed after that
> replacement but before *foliop is updated, the completion path can still
> keep the old folio in ap->folios[]. Then fs/fuse/file.c later does:
>
> mapping = ap->folios[0]->mapping;
> inode = mapping->host;
>
> and faults because mapping is NULL.
>
> Reproducer:
>
> C reproducer:
> https://raw.githubusercontent.com/neck392/linux-kernel-bug-reports/main/fuse-readpages-end-v7.1-rc7/repro_fuse_readpages_end_rc7_userns.c
>
> Symbolized KASAN report:
> https://raw.githubusercontent.com/neck392/linux-kernel-bug-reports/main/fuse-readpages-end-v7.1-rc7/clean_c_userns_report_rc7_fuse_readpages_end.txt
>
> Kernel config:
> https://raw.githubusercontent.com/neck392/linux-kernel-bug-reports/main/fuse-readpages-end-v7.1-rc7/kernel-config-v7.1-rc7.config
>
> Key config options:
>
> CONFIG_FUSE_FS=y
> CONFIG_KASAN=y
> CONFIG_KASAN_GENERIC=y
> CONFIG_KASAN_VMALLOC=y
> CONFIG_KASAN_EXTRA_INFO=y
> CONFIG_USER_NS=y
>
> Runtime conditions:
>
> fuse.enable_uring=0
> unprivileged user namespaces enabled
> /dev/fuse accessible to the reproducer
>
> I verified the C reproducer by starting it from uid 1000; it then creates a
> user namespace before mounting FUSE.
>
> Brief KASAN excerpt:
>
> Oops: general protection fault, probably for non-canonical address
> 0xdffffc0000000000
> KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
> CPU: 1 UID: 1000 PID: 399 Comm: repro_fuse_read Not tainted 7.1.0-rc7
> RIP: 0010:fuse_readpages_end+0xe5/0x650
>
> Call Trace:
> fuse_request_end
> fuse_dev_do_write
> fuse_dev_splice_write
> do_splice
> __do_splice
> __x64_sys_splice
> do_syscall_64
>
> If you fix this issue, please add the following tag to the commit:
>
> Reported-by: Minseo Kim <neck3922@xxxxxxxxx>
>
> If you need anything else, please let me know.
>
> Best regards,
> Minseo Kim
>
Hi Minseo,
I believe this has already been fixed by [1]. Could you verify that
that patch fixes your issue?
Thanks,
Joanne
[1] https://lore.kernel.org/fuse-devel/20260519052807.1924269-1-joannelkoong@xxxxxxxxx/