kernel bug found and suggestions for fixing it
From: =?gb18030?b?ZmZoZ2Z2?=
Date: Wed Mar 05 2025 - 09:55:44 EST
Hello, I found a bug titled " BUG: corrupted list in fix_fullness_group " with modified syzkaller in the lasted upstream related to ZSMALLOC.
If you fix this issue, please add the following tag to the commit: Reported-by: Jianzhou Zhao <xnxc22xnxc22@xxxxxx>, xingwei lee <xrivendell7@xxxxxxxxx>, Zhizhuo Tang <strforexctzzchange@xxxxxxxxxxx>
------------[ cut here ]-----------------------------------------
BUG: corrupted list in fix_fullness_group
==================================================================
list_add corruption. next->prev should be prev (ffff8880436a4020), but was ffff8881436a4020. (next=ffff8880436a4020).
------------[ cut here ]------------
kernel BUG at lib/list_debug.c:29!
invalid opcode: 0000 [#1] PREEMPT SMP KASAN NOPTI
CPU: 0 PID: 86 Comm: kswapd0 Not tainted 6.9.0-rc7 #51
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
RIP: 0010:__list_add_valid_or_report+0xb7/0x110 lib/list_debug.c:29
Code: 02 bd 8a e8 7b f3 22 fd 90 0f 0b 48 c7 c7 60 03 bd 8a e8 6c f3 22 fd 90 0f 0b 4c 89 e1 48 c7 c7 c0 03 bd 8a e8 5a f3 22 fd 90 <0f> 0b 48 89 f1 48 c7 c7 40 04 bd 8a 4c 89 e6 e8 45 f3 22 fd 90 0f
RSP: 0018:ffff888011886c88 EFLAGS: 00010282
RAX: 0000000000000075 RBX: ffff88802348c688 RCX: ffffffff8164b313
RDX: 0000000000000000 RSI: ffffffff81652eae RDI: 0000000000000001
RBP: ffff888011886ca0 R08: ffff888011890000 R09: ffffed1002310d51
R10: ffffed1002310d50 R11: ffff888011886a87 R12: ffff8880436a4020
R13: ffff88802348c6a0 R14: ffff8880436a4020 R15: ffff88802348c6a0
FS: 0000000000000000(0000) GS:ffff88802d000000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fd266fc6018 CR3: 000000001fc46000 CR4: 0000000000750ef0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
PKRU: 55555554
Call Trace:
<task>
__list_add_valid include/linux/list.h:88 [inline]
__list_add include/linux/list.h:150 [inline]
list_add include/linux/list.h:169 [inline]
insert_zspage mm/zsmalloc.c:672 [inline]
fix_fullness_group+0x3f8/0x540 mm/zsmalloc.c:708
zs_malloc+0x588/0x13b0 mm/zsmalloc.c:1355
zs_zpool_malloc+0x35/0xa0 mm/zsmalloc.c:366
zpool_malloc+0x8b/0xc0 mm/zpool.c:258
zswap_compress mm/zswap.c:1049 [inline]
zswap_store+0xaaa/0x26c0 mm/zswap.c:1580
swap_writepage+0x99/0x2b0 mm/page_io.c:198
pageout+0x384/0x810 mm/vmscan.c:660
shrink_folio_list+0x12f3/0x3bd0 mm/vmscan.c:1323
evict_folios+0x753/0x1890 mm/vmscan.c:4537
try_to_shrink_lruvec+0x6be/0xa20 mm/vmscan.c:4733
shrink_one+0x41e/0x7d0 mm/vmscan.c:4772
shrink_many mm/vmscan.c:4835 [inline]
lru_gen_shrink_node+0x6f6/0xe60 mm/vmscan.c:4935
shrink_node+0x1a70/0x23a0 mm/vmscan.c:5894
kswapd_shrink_node mm/vmscan.c:6704 [inline]
balance_pgdat+0x974/0x15d0 mm/vmscan.c:6895
kswapd+0x513/0xaf0 mm/vmscan.c:7164
kthread+0x313/0x410 kernel/kthread.c:388
ret_from_fork+0x56/0x90 arch/x86/kernel/process.c:147
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
</task>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:__list_add_valid_or_report+0xb7/0x110 lib/list_debug.c:29
Code: 02 bd 8a e8 7b f3 22 fd 90 0f 0b 48 c7 c7 60 03 bd 8a e8 6c f3 22 fd 90 0f 0b 4c 89 e1 48 c7 c7 c0 03 bd 8a e8 5a f3 22 fd 90 <0f> 0b 48 89 f1 48 c7 c7 40 04 bd 8a 4c 89 e6 e8 45 f3 22 fd 90 0f
RSP: 0018:ffff888011886c88 EFLAGS: 00010282
RAX: 0000000000000075 RBX: ffff88802348c688 RCX: ffffffff8164b313
RDX: 0000000000000000 RSI: ffffffff81652eae RDI: 0000000000000001
RBP: ffff888011886ca0 R08: ffff888011890000 R09: ffffed1002310d51
R10: ffffed1002310d50 R11: ffff888011886a87 R12: ffff8880436a4020
R13: ffff88802348c6a0 R14: ffff8880436a4020 R15: ffff88802348c6a0
FS: 0000000000000000(0000) GS:ffff88802d000000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fd266fc6018 CR3: 000000001fc46000 CR4: 0000000000750ef0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
PKRU: 55555554
==================================================================
I use the same kernel as syzbot instance upstream: 7eb172143d5508b4da468ed59ee857c6e5e01da6
kernel config: https://syzkaller.appspot.com/text?tag=KernelConfig&x=da4b04ae798b7ef6
compiler: gcc version 11.4.0
===============================================================================
Unfortunately, the modified syzkaller does not generate an effective repeat program.
The following is my analysis of the bug and repair suggestions, hoping to help with the repair of the bug:
## Root cause analysis
The crash was caused by a list node corruption while the zsmalloc memory allocator was adjusting the memory page's fullness list. The specific cause could be:
Concurrent access is not synchronized correctly. The fix_fullness_group() did not hold the zspool lock correctly when manipulating the class->fullness_list linked list, causing multiple CPU cores (such as kswapd and memory allocation threads) to modify the linked list node simultaneously.
Memory overreach /UAF (Use-After-Free).In the zs_malloc path, the linked list pointer may be abnormal because the object metadata is overwritten.
### Repair suggestions
Hardening lock mechanism. Ensure that the correct pool locks are held in zs_malloc and page migration paths.
Patch example:
mm/zsmalloc.c:
static int fix_fullness_group(struct size_class *class, struct zspage *zspage)
{
int newfg;
newfg = get_fullness_group(class, zspage);
if (newfg == zspage->fullness)
goto out;
++ spin_lock(&class->lock);
remove_zspage(class, zspage);
insert_zspage(class, zspage, newfg);
++ spin_unlock(&class->lock);
out:
return newfg;
}
=========================================================================
I hope it helps.
Best regards
Jianzhou Zhao
xingwei lee
Zhizhuo Tang
ÉÏÒ»·â ÏÂÒ»·â</strforexctzzchange@xxxxxxxxxxx></xrivendell7@xxxxxxxxx></xnxc22xnxc22@xxxxxx>