[PATCH] fuse: avoid null pointer member access in fuse_iomap_writeback_range()

From: Shunbo Shi

Date: Mon Nov 02 2026 - 22:22:27 EST


In fuse_iomap_writeback_range() 'ap' is initialized to '&wpa->ia.ap'
unconditionally, but 'wpa' (== data->wpa) is NULL when the writeback
of the first folio of a batch starts: 'data' is zero-initialized in
fuse_writepages() and fuse_launder_folio(), and fuse_writepages_send()
resets data->wpa to NULL after every batch.

Taking the address of a member of a NULL pointer is undefined
behavior. The bogus initial value of 'ap' is never actually
dereferenced: all uses are either guarded by 'if (wpa)' or run after
'ap' has been reassigned in the 'data->wpa == NULL' branch, where a
new 'wpa' is allocated first. Still, the expression lets the
compiler assume that 'wpa' is non-NULL for the whole function, which
could break the 'if (wpa)' check below and turn the latent UB into a
real NULL pointer dereference.

This can be observed with a kernel built with -fsanitize=null (not
part of the default CONFIG_UBSAN flag set) when writeback of an mmap
dirty region is triggered, e.g. via msync()/fsync():

UBSAN: member access within null pointer of type
'struct fuse_writepage_args'
Call Trace:
__ubsan_handle_type_mismatch_v1+0x3f/0x50
fuse_iomap_writeback_range+0x79c/0xbd0
iomap_writepages+0x64/0x140
fuse_writepages+0xe0/0x260
do_writepages+0xaa/0x360

Initialize 'ap' to NULL when 'wpa' is NULL. With this change the
warning above is gone while the writeback path is exercised
identically.

Signed-off-by: Shunbo Shi <shishunbo@xxxxxxxxxxxxxxxxxxxx>
---
fs/fuse/file.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index d5e1cb53d86a..e89fdbeb7d04 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2257,7 +2257,7 @@ static ssize_t fuse_iomap_writeback_range(struct iomap_writepage_ctx *wpc,
{
struct fuse_fill_wb_data *data = wpc->wb_ctx;
struct fuse_writepage_args *wpa = data->wpa;
- struct fuse_args_pages *ap = &wpa->ia.ap;
+ struct fuse_args_pages *ap = wpa ? &wpa->ia.ap : NULL;
struct inode *inode = wpc->inode;
struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_conn *fc = get_fuse_conn(inode);
--
2.53.0