[PATCH v2] fs/jfs: fix NULL pointer dereference in metapage_read_folio

Sridhar Markonda <[email protected]>
Newsgroups org.kernel.vger.linux-fsdevel
Message-ID <[email protected]>
This patch fixes a NULL pointer dereference in JFS found during syzkaller
testing on PowerPC systems using large page sizes.

Full crash report:

BUG: KASAN: null-ptr-deref in instrument_atomic_read_write include/linux/instrumented.h:112 [inline]
BUG: KASAN: null-ptr-deref in atomic_inc include/linux/atomic/atomic-instrumented.h:435 [inline]
BUG: KASAN: null-ptr-deref in inc_io fs/jfs/jfs_metapage.c:140 [inline]
BUG: KASAN: null-ptr-deref in metapage_read_folio+0x238/0x7b4 fs/jfs/jfs_metapage.c:587
Write of size 4 at addr 0000000000000004 by task syz.6.4880/59986

CPU: 1 UID: 0 PID: 59986 Comm: syz.6.4880 Tainted: G             L      syzkaller #0 PREEMPT
Tainted: [L]=SOFTLOCKUP
Hardware name: IBM,9105-22A POWER10 (architected) 0x800200 0xf000006 of:IBM,FW1060.51 (NL1060_148) hv:phyp pSeries
Call Trace:
[c00000006e836e30] [c000000000bf948c] print_report mm/kasan/report.c:485 [inline]
[c00000006e836e30] [c000000000bf948c] print_report+0x444/0x9a0 mm/kasan/report.c:471
[c00000006e836f10] [c000000000bf9c10] kasan_report+0x12c/0x218 mm/kasan/report.c:595
[c00000006e837020] [c000000000bfc62c] check_region_inline mm/kasan/generic.c:186 [inline]
[c00000006e837020] [c000000000bfc62c] kasan_check_range+0x270/0x380 mm/kasan/generic.c:200
[c00000006e837060] [c000000000bfd664] __kasan_check_write+0x20/0x34 mm/kasan/shadow.c:37
[c00000006e837080] [c000000001acb808] instrument_atomic_read_write include/linux/instrumented.h:112 [inline]
[c00000006e837080] [c000000001acb808] atomic_inc include/linux/atomic/atomic-instrumented.h:435 [inline]
[c00000006e837080] [c000000001acb808] inc_io fs/jfs/jfs_metapage.c:140 [inline]
[c00000006e837080] [c000000001acb808] metapage_read_folio+0x238/0x7b4 fs/jfs/jfs_metapage.c:587
[c00000006e837130] [c000000000950df0] filemap_read_folio+0xa0/0x268 mm/filemap.c:2501
[c00000006e837180] [c00000000095c234] do_read_cache_folio+0x2d8/0x5c4 mm/filemap.c:4101
[c00000006e837200] [c000000001acd974] read_mapping_folio include/linux/pagemap.h:1028 [inline]
[c00000006e837200] [c000000001acd974] __get_metapage+0x1c4/0xd78 fs/jfs/jfs_metapage.c:729
[c00000006e8372e0] [c000000001a947c8] xtSplitRoot+0xd8/0x874 fs/jfs/jfs_xtree.c:1242
[c00000006e8373d0] [c000000001a97a4c] xtSplitUp+0xad0/0x1240 fs/jfs/jfs_xtree.c:785
[c00000006e837580] [c000000001a98ea0] xtInsert+0x7c0/0xa18 fs/jfs/jfs_xtree.c:608
[c00000006e837780] [c000000001ac851c] extAlloc+0x7bc/0xc74 fs/jfs/jfs_extent.c:150
[c00000006e8378b0] [c000000001a8a7a0] jfs_get_block+0x3c0/0x868 fs/jfs/inode.c:254
[c00000006e837950] [c000000000e1af2c] __block_write_begin_int+0x3c8/0x1318 fs/buffer.c:2142
[c00000006e837a60] [c000000000e1bf98] block_write_begin+0xac/0x230 fs/buffer.c:2253
[c00000006e837ab0] [c000000001a8c454] jfs_write_begin+0x58/0x114 fs/jfs/inode.c:306
[c00000006e837af0] [c000000000949a30] generic_perform_write+0x2e8/0x754 mm/filemap.c:4319
[c00000006e837bf0] [c000000000964174] __generic_file_write_iter+0x210/0x244 mm/filemap.c:4436
[c00000006e837c40] [c0000000009642a4] generic_file_write_iter+0xfc/0x35c mm/filemap.c:4462
[c00000006e837ca0] [c000000000cf9cfc] new_sync_write fs/read_write.c:595 [inline]
[c00000006e837ca0] [c000000000cf9cfc] vfs_write+0x530/0x95c fs/read_write.c:688
[c00000006e837d90] [c000000000cfa4c8] ksys_write+0xf0/0x230 fs/read_write.c:740
[c00000006e837df0] [c00000000004ebbc] system_call_exception+0x26c/0x760 arch/powerpc/kernel/syscall.c:153
[c00000006e837e50] [c00000000000d05c] system_call_vectored_common+0x15c/0x2ec

The crash occurs when insert_metapage() fails to allocate a meta_anchor
structure. The function returns an error code, but its return value was
ignored, leading to a NULL pointer dereference in inc_io().

Check the return value from insert_metapage() and stop processing the
folio when allocation fails.

Fixes: 7fab479bebb9 ("[PATCH] JFS: Support page sizes greater than 4K")

Signed-off-by: Sridhar Markonda <[email protected]>
---
Changes in v2:
- Keep insert_metapage() in its original location.
- Check and return errors from insert_metapage().
- Update the Fixes tag.
- Test with xfstests on ppc64le (64K pages); no regressions observed.
---
 fs/jfs/jfs_metapage.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 41fe12e641ce..ffbb186e850c 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -573,6 +573,7 @@ static int metapage_read_folio(struct file *fp, struct folio *folio)
 	int xlen;
 	unsigned int len;
 	int offset;
+	int ret = 0;
 
 	BUG_ON(!folio_test_locked(folio));
 	page_start = folio_pos(folio) >> inode->i_blkbits;
@@ -583,8 +584,11 @@ static int metapage_read_folio(struct file *fp, struct folio *folio)
 		pblock = metapage_get_blocks(inode, page_start + block_offset,
 					     &xlen);
 		if (pblock) {
-			if (!folio->private)
-				insert_metapage(folio, NULL);
+			if (!folio->private) {
+				ret = insert_metapage(folio, NULL);
+				if (ret)
+					break;
+			}
 			inc_io(folio);
 			if (bio)
 				submit_bio(bio);
@@ -607,7 +611,7 @@ static int metapage_read_folio(struct file *fp, struct folio *folio)
 	else
 		folio_unlock(folio);
 
-	return 0;
+	return ret;
 }
 
 static bool metapage_release_folio(struct folio *folio, gfp_t gfp_mask)
-- 
2.52.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.