[lvc-project] [PATCH] gfs2: validate rindex bitmap length before allocation

Makar Semyonov m.semenov at tssltd.ru
Wed Aug 12 16:04:50 MSK 2026


The ri_length field of a GFS2 rindex entry is used
directly as the number of bitmap descriptors
allocated by compute_bitstructs(), without
validating it against ri_bitbytes. A corrupted
rindex entry can therefore specify an excessively
large ri_length while describing only a small
amount of bitmap data. In the syzkalle reproducer,
the second rindex entry has ri_length=327680 and
ri_bitbytes=503, causing a large allocation
and a page allocator warning:

[    8.387580] ------------[ cut here ]------------
[    8.387959] WARNING: CPU: 1 PID: 294 at mm/page_alloc.c:5534 __alloc_pages+0x50d/0x24f0
[    8.388636] Modules linked in:
[    8.388898] CPU: 1 PID: 294 Comm: repro Not tainted 6.1.0 #42
[    8.389395] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[    8.390325] RIP: 0010:__alloc_pages+0x50d/0x24f0
[    8.390711] Code: fe ff ff 0a 0f 86 0b fc ff ff 0f b6 1d 1f a7 32 04 80 fb 01 0f 87 43 53 34 02 83 e3 01 0f 85 01 fd ff ff c6 05 06 a7 32 04 01 <0f> 0b e9 f3 fc ff ff a9 00 00 08 00 0f 85 1f 0a 00 00 44 89 fa 80
[    8.392234] RSP: 0018:ffff8880046a7248 EFLAGS: 00010246
[    8.392668] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[    8.393234] RDX: 0000000000000000 RSI: 000000000000000c RDI: 1ffff110008d4e61
[    8.393811] RBP: ffff8880046a7450 R08: 0000000000000001 R09: 0000000000000003
[    8.394392] R10: ffffed10008d4e3e R11: ffff8880046a7458 R12: 0000000000000000
[    8.394967] R13: 0000000000000d40 R14: ffff8880046a7428 R15: 0000000000040d40
[    8.395548] FS:  00007544de4b7740(0000) GS:ffff88805b700000(0000) knlGS:0000000000000000
[    8.396198] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[    8.396675] CR2: 000064d33b1aff40 CR3: 0000000007560004 CR4: 0000000000770ee0
[    8.397249] PKRU: 55555554
[    8.397479] Call Trace:
[    8.397684]  <TASK>
[    8.397861]  ? finish_wait+0x12b/0x1f0
[    8.398170]  ? find_insert_glock+0xa47/0x11a0
[    8.398536]  ? warn_alloc+0x1d0/0x1d0
[    8.398839]  ? glock_blocked_by_withdraw+0x1f0/0x1f0
[    8.399244]  ? __kasan_kmalloc+0xb6/0xc0
[    8.399575]  ? gfs2_glock_get+0x161/0x1000
[    8.399915]  __kmalloc_large_node+0x79/0xf0
[    8.400260]  ? read_rindex_entry+0x4a7/0x1410
[    8.400624]  __kmalloc+0xda/0x170
[    8.400901]  read_rindex_entry+0x4a7/0x1410
[    8.401247]  ? __rs_deltree+0x2c0/0x2c0
[    8.401569]  ? gfs2_instantiate+0x192/0x1f0
[    8.401913]  ? gfs2_glock_nq+0x4e7/0x1300
[    8.402241]  gfs2_ri_update+0x7d/0x4b0
[    8.402555]  gfs2_rindex_update+0x3f9/0x480
[    8.402900]  ? gfs2_ri_total+0x230/0x230
[    8.403222]  ? init_inodes+0x1be2/0x22b0
[    8.403548]  ? gfs2_rename2+0x90/0x90
[    8.403854]  ? _raw_spin_unlock_irqrestore+0xe/0x40
[    8.404253]  init_inodes+0x1be2/0x22b0
[    8.404568]  ? gfs2_parse_param+0xea0/0xea0
[    8.404913]  ? pointer+0xce0/0xce0
[    8.405197]  ? snprintf+0xc4/0x100
[    8.405488]  ? debugfs_create_file+0x5f/0x80
[    8.405844]  gfs2_fill_super+0x1952/0x2610
[    8.406179]  ? gfs2_reconfigure+0xf40/0xf40
[    8.406525]  ? pointer+0xce0/0xce0
[    8.406811]  ? gfs2_fill_super+0x1682/0x2610
[    8.407165]  ? __kasan_check_write+0x14/0x20
[    8.407521]  ? set_blocksize+0x288/0x320
[    8.407840]  get_tree_bdev+0x3d4/0x6d0
[    8.408145]  ? gfs2_reconfigure+0xf40/0xf40
[    8.408492]  gfs2_get_tree+0x50/0x260
[    8.408802]  vfs_get_tree+0x8d/0x2c0
[    8.409102]  path_mount+0x10da/0x1b00
[    8.409412]  ? putname+0xf3/0x140
[    8.409693]  ? finish_automount+0x6d0/0x6d0
[    8.409985]  ? putname+0xf8/0x140
[    8.410242]  __x64_sys_mount+0x270/0x310
[    8.410574]  ? path_mount+0x1b00/0x1b00
[    8.410894]  ? putname+0xf8/0x140
[    8.411171]  do_syscall_64+0x59/0x90
[    8.411474]  ? do_file_open_root+0x580/0x580
[    8.411828]  ? __kasan_check_read+0x11/0x20
[    8.412172]  ? fpregs_assert_state_consistent+0x75/0xd0
[    8.412607]  ? exit_to_user_mode_prepare+0x38/0x1e0
[    8.413013]  ? syscall_exit_to_user_mode+0x1b/0x40
[    8.413412]  ? do_syscall_64+0x68/0x90
[    8.413725]  ? irqentry_exit_to_user_mode+0x9/0x30
[    8.414115]  ? irqentry_exit+0x3b/0x50
[    8.414432]  ? exc_page_fault+0x71/0xe0
[    8.414750]  entry_SYSCALL_64_after_hwframe+0x63/0xcd
[    8.415160] RIP: 0033:0x7544de5b66ca
[    8.415461] Code: 48 8b 0d c9 17 0d 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 96 17 0d 00 f7 d8 64 89 01 48
[    8.416952] RSP: 002b:00007ffedd978778 EFLAGS: 00000206 ORIG_RAX: 00000000000000a5
[    8.417565] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007544de5b66ca
[    8.418137] RDX: 0000200000000240 RSI: 0000200000001c00 RDI: 00007ffedd9788c0
[    8.418721] RBP: 00007ffedd978950 R08: 00007ffedd9787c0 R09: 0000000000000000
[    8.419293] R10: 0000000000000804 R11: 0000000000000206 R12: 000056e5fc7ae1a0
[    8.419875] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[    8.420456]  </TASK>
[    8.420641] ---[ end trace 0000000000000000 ]---

Validate ri_length against ri_bitbytes before
allocating rd_bits. The first resource group
block can contain sb_bsize - sizeof(struct gfs2_rgrp)
bytes of bitmap data, while subsequent blocks can
contain sb_bsize - sizeof(struct gfs2_meta_header)
bytes. Reject an ri_length that exceeds the number
of blocks required by ri_bitbytes before calling kcalloc().

Fixes: feaa7bba026c1 ("[GFS2] Fix unlinked file handling")
Signed-off-by: Makar Semyonov <m.semenov at tssltd.ru>
---
 fs/gfs2/rgrp.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 5988a165a830..b3d5e2d475fa 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -763,6 +763,24 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
 	if (!length)
 		return -EINVAL;
 
+	if (length > 1) {
+		u32 first_block_bytes =
+			sdp->sd_sb.sb_bsize - sizeof(struct gfs2_rgrp);
+		u32 bitmap_bytes_per_block =
+			sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header);
+		u32 max_length;
+
+		if (rgd->rd_bitbytes < first_block_bytes)
+			max_length = 1;
+		else
+			max_length = 2 +
+				(rgd->rd_bitbytes - first_block_bytes) /
+				bitmap_bytes_per_block;
+
+		if (length > max_length)
+			return -EIO;
+	}
+
 	rgd->rd_bits = kzalloc_objs(struct gfs2_bitmap, length, GFP_NOFS);
 	if (!rgd->rd_bits)
 		return -ENOMEM;
-- 
2.43.0




More information about the lvc-project mailing list