[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