[Linux Kernel Bug] KASAN: use-after-free Read in gfs2_rgrp_go_instantiate

From: Jiaming Zhang

Date: Tue Sep 01 2026 - 03:53:24 EST


Dear Linux kernel developers and maintainers,

We are writing to report an issue discovered in the GFS2 subsystem. The
issue is reproducible on the latest version of linux (v7.3-rc1, commit
cee9395acd8043be0644b25c34bfa86623f2b935). Below is the kernel report:

gfs2: fsid=syz:syz.0: Corruption found in quota_change0file: duplicate
identifier in slot 224440
gfs2: fsid=syz:syz.0: found 1 quota changes
==================================================================
BUG: KASAN: use-after-free in gfs2_bit_search fs/gfs2/rgrp.c:188 [inline]
BUG: KASAN: use-after-free in gfs2_bitfit fs/gfs2/rgrp.c:249 [inline]
BUG: KASAN: use-after-free in count_unlinked fs/gfs2/rgrp.c:1159 [inline]
BUG: KASAN: use-after-free in gfs2_rgrp_go_instantiate+0xb0d/0x1340
fs/gfs2/rgrp.c:1238
Read of size 8 at addr ffff888027516000 by task syz-executor199/9470

CPU: 0 UID: 0 PID: 9470 Comm: syz-executor199 Not tainted 7.3.0-rc1
#35 PREEMPT(full)
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
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:94 [inline]
dump_stack_lvl+0x10e/0x190 lib/dump_stack.c:120
print_address_description mm/kasan/report.c:378 [inline]
print_report+0x153/0x7e0 mm/kasan/report.c:482
kasan_report+0x147/0x180 mm/kasan/report.c:595
gfs2_bit_search fs/gfs2/rgrp.c:188 [inline]
gfs2_bitfit fs/gfs2/rgrp.c:249 [inline]
count_unlinked fs/gfs2/rgrp.c:1159 [inline]
gfs2_rgrp_go_instantiate+0xb0d/0x1340 fs/gfs2/rgrp.c:1238
gfs2_instantiate+0x168/0x220 fs/gfs2/glock.c:415
gfs2_glock_holder_ready fs/gfs2/glock.c:1226 [inline]
gfs2_glock_wait+0x1d4/0x2a0 fs/gfs2/glock.c:1246
gfs2_glock_nq_init fs/gfs2/glock.h:253 [inline]
gfs2_inplace_reserve+0xc41/0x3330 fs/gfs2/rgrp.c:2093
do_sync+0x616/0xc60 fs/gfs2/quota.c:962
gfs2_quota_sync+0x359/0x460 fs/gfs2/quota.c:1372
gfs2_sync_fs+0x4c/0xb0 fs/gfs2/super.c:662
sync_filesystem+0xf1/0x240 fs/sync.c:56
generic_shutdown_super+0x77/0x2d0 fs/super.c:748
kill_block_super+0x44/0xa0 fs/super.c:1918
deactivate_locked_super+0xbc/0x110 fs/super.c:603
cleanup_mnt+0x425/0x4c0 fs/namespace.c:1317
task_work_run+0x1d4/0x260 kernel/task_work.c:233
exit_task_work include/linux/task_work.h:40 [inline]
do_exit+0x708/0x22a0 kernel/exit.c:1008
do_group_exit+0x21c/0x2d0 kernel/exit.c:1151
__do_sys_exit_group kernel/exit.c:1162 [inline]
__se_sys_exit_group kernel/exit.c:1160 [inline]
__x64_sys_exit_group+0x3f/0x40 kernel/exit.c:1160
x64_sys_call+0x18c6/0x18d0 arch/x86/include/generated/asm/syscalls_64.h:232
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x170/0x540 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f5c39c96f2d
Code: Unable to access opcode bytes at 0x7f5c39c96f03.
RSP: 002b:00007ffc5256c978 EFLAGS: 00000206 ORIG_RAX: 00000000000000e7
RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007f5c39c96f2d
RDX: 00000000000000e7 RSI: ffffffffffffffc0 RDI: 0000000000000001
RBP: 00007ffc5256c9d0 R08: 0000000000000000 R09: 000000000003b2e1
R10: 0000000000000000 R11: 0000000000000206 R12: 0000000000000000
R13: 0000000000000001 R14: 0000000000000001 R15: 00007f5c39d6a600
</TASK>

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x7effc363f
pfn:0x27516
flags: 0xfff00000000000(node=0|zone=1|lastcpupid=0x7ff)
raw: 00fff00000000000 ffffea00009d6108 ffffea00009d86c8 0000000000000000
raw: 00000007effc363f 0000000000000000 00000000ffffffff 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as freed
page last allocated via order 0, migratetype Movable, gfp_mask
0x140cca(GFP_HIGHUSER_MOVABLE|__GFP_COMP), pid 9361, tgid 9361
((udev-worker)), ts 96351902392
set_page_owner include/linux/page_owner.h:33 [inline]
post_alloc_hook+0x205/0x260 mm/page_alloc.c:1871
prep_new_page mm/page_alloc.c:1879 [inline]
get_page_from_freelist+0x235b/0x23e0 mm/page_alloc.c:3943
__alloc_frozen_pages_noprof+0x209/0x5a0 mm/page_alloc.c:5436
alloc_pages_mpol+0x241/0x4a0 mm/mempolicy.c:2486
folio_alloc_mpol_noprof+0x39/0x160 mm/mempolicy.c:2505
vma_alloc_folio_noprof+0xdb/0x1e0 mm/mempolicy.c:2540
folio_prealloc+0x30/0x180 mm/memory.c:-1
wp_page_copy mm/memory.c:4007 [inline]
do_wp_page+0x119f/0x4b00 mm/memory.c:4472
handle_pte_fault mm/memory.c:6582 [inline]
__handle_mm_fault mm/memory.c:6707 [inline]
handle_mm_fault+0x15a7/0x36d0 mm/memory.c:6876
do_user_addr_fault+0xa7e/0x1360 arch/x86/mm/fault.c:1343
handle_page_fault arch/x86/mm/fault.c:1483 [inline]
exc_page_fault+0x71/0xd0 arch/x86/mm/fault.c:1536
asm_exc_page_fault+0x26/0x30 arch/x86/include/asm/idtentry.h:595
page last free pid 9361 tgid 9361 ts 103418286503 stack trace:
reset_page_owner include/linux/page_owner.h:26 [inline]
__free_pages_prepare mm/page_alloc.c:1418 [inline]
free_unref_folios+0xd80/0x14c0 mm/page_alloc.c:3022
folios_put_refs+0x7b4/0x8a0 mm/folio.c:1034
free_pages_and_swap_cache+0x25e/0x440 mm/swap_state.c:592
__tlb_batch_free_encoded_pages mm/mmu_gather.c:138 [inline]
tlb_batch_pages_flush mm/mmu_gather.c:151 [inline]
tlb_flush_mmu_free mm/mmu_gather.c:417 [inline]
tlb_flush_mmu+0x3a2/0x680 mm/mmu_gather.c:424
tlb_finish_mmu+0xf9/0x230 mm/mmu_gather.c:549
exit_mmap+0x473/0x9c0 mm/mmap.c:1328
__mmput+0x118/0x430 kernel/fork.c:1193
exit_mm+0x214/0x2e0 kernel/exit.c:614
do_exit+0x69b/0x22a0 kernel/exit.c:996
do_group_exit+0x21c/0x2d0 kernel/exit.c:1151
__do_sys_exit_group kernel/exit.c:1162 [inline]
__se_sys_exit_group kernel/exit.c:1160 [inline]
__x64_sys_exit_group+0x3f/0x40 kernel/exit.c:1160
x64_sys_call+0x18c6/0x18d0 arch/x86/include/generated/asm/syscalls_64.h:232
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x170/0x540 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f

Memory state around the buggy address:
ffff888027515f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff888027515f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff888027516000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
^
ffff888027516080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff888027516100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
==================================================================

Following is the root cause analysis for this issue, note that the
analysis is performed with the assistance of LLM, but we try our best to
ensure the accuracy.

A rindex entry's ri_bitbytes is not checked against sb_bsize.
compute_bitstructs() splits ri_bitbytes across the blocks of the resource
group and gives the remainder to the last bitmap, whose length bi_bytes can
then exceed the size of the block that stores it. gfs2_bitfit() scans past
the end of that buffer, which KASAN reports as a use-after-free.

To fix this issue, a bitmap that does not fit in the block that holds it
should be rejected:

diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 5988a165a830..689ff5a4e0df 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -804,6 +804,12 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
bi->bi_blocks = bytes * GFS2_NBBY;
}

+ /* A bitmap must fit in the block that holds it */
+ if (bytes > sdp->sd_sb.sb_bsize - bi->bi_offset) {
+ gfs2_consist_rgrpd(rgd);
+ return -EIO;
+ }
+
bytes_left -= bytes;
}


The kernel console output, kernel config, syzkaller reproducer, and C
reproducer are available at google drive:
https://drive.google.com/drive/folders/11t4bHrvlPdnH0bQi0R1QTc6btCaoTZQE?usp=sharing

Please let us know if any further information is required.

Best Regards,
Jiaming Zhang