[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