[BUG] fuse: KASAN null-ptr-deref in fuse_readpages_end after aborted splice read reply
From: 김민서
Date: Tue Jun 09 2026 - 17:34:09 EST
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