[BUG] list corruption in __bpf_lru_node_move () 【 bug found and suggestions for fixing it】
From: Strforexc yn
Date: Wed Mar 05 2025 - 08:30:34 EST
Hi Maintainers,
When using our customized Syzkaller to fuzz the latest Linux kernel,
the following crash was triggered.
Kernel Config : https://github.com/Strforexc/LinuxKernelbug/blob/main/.config
A kernel BUG was reported due to list corruption during BPF LRU node movement.
The issue occurs when the node being moved is the sole element in its list and
also the next_inactive_rotation candidate. After moving, the list became empty,
but next_inactive_rotation incorrectly pointed to the moved node, causing later
operations to corrupt the list.
Here is my fix suggestion:
The fix checks if the node was the only element before adjusting
next_inactive_rotation. If so, it sets the pointer to NULL, preventing invalid
access.
diff --git a/kernel/bpf/bpf_lru_list.c b/kernel/bpf/bpf_lru_list.c
index XXXXXXX..XXXXXXX 100644
--- a/kernel/bpf/bpf_lru_list.c
+++ b/kernel/bpf/bpf_lru_list.c
@@ -119,8 +119,13 @@ static void __bpf_lru_node_move(struct bpf_lru_list *l,
* move the next_inactive_rotation pointer also.
*/
if (&node->list == l->next_inactive_rotation)
- l->next_inactive_rotation = l->next_inactive_rotation->prev;
-
+ {
+ if (l->next_inactive_rotation->prev == &node->list) {
+ l->next_inactive_rotation = NULL;
+ } else {
+ l->next_inactive_rotation = l->next_inactive_rotation->prev;
+ }
+ }
list_move(&node->list, &l->lists[tgt_type]);
}
--
2.34.1
Our knowledge of the kernel is somewhat limited, and we'd appreciate
it if you could determine if there is such an issue. If this issue
doesn't have an impact, please ignore it ☺.
If you fix this issue, please add the following tag to the commit:
Reported-by: Zhizhuo Tang strforexctzzchange@xxxxxxxxxxx, Jianzhou
Zhao xnxc22xnxc22@xxxxxx, Haoran Liu <cherest_san@xxxxxxx>
Last is my report:
vmalloc memory
list_add corruption. next->prev should be prev (ffffe8ffac433e40), but
was 50ffffe8ffac433e. (next=ffffe8ffac433e41).
------------[ cut here ]------------
kernel BUG at lib/list_debug.c:29!
Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN PTI
CPU: 0 UID: 0 PID: 14524 Comm: syz.0.285 Not tainted
6.14.0-rc5-00013-g99fa936e8e4f #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
RIP: 0010:__list_add_valid_or_report+0xfc/0x1a0 lib/list_debug.c:29
Code: 00 00 00 00 fc ff df 48 c1 ea 03 80 3c 02 00 0f 85 a6 00 00 00
49 8b 54 24 08 4c 89 e1 48 c7 c7 c0 1f f2 8b e8 55 54 d3 fc 90 <0f> 0b
48 89 f7 48 89 34 24 e8 16 54 33 fd 48 8b 34 24 48 b8 00 00
RSP: 0018:ffffc900033779b0 EFLAGS: 00010046
RAX: 0000000000000075 RBX: ffffc900035777c8 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: ffffe8ffac433e40 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: ffffe8ffac433e41
R13: ffffc900035777c8 R14: ffffe8ffac433e49 R15: ffffe8ffac433e50
FS: 00007fef15ddd640(0000) GS:ffff88802b600000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007ffd53abb238 CR3: 00000000296f4000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
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]
list_move include/linux/list.h:299 [inline]
__bpf_lru_node_move+0x21a/0x480 kernel/bpf/bpf_lru_list.c:126
__bpf_lru_list_rotate_inactive+0x20f/0x310 kernel/bpf/bpf_lru_list.c:196
__bpf_lru_list_rotate kernel/bpf/bpf_lru_list.c:247 [inline]
bpf_percpu_lru_pop_free kernel/bpf/bpf_lru_list.c:417 [inline]
bpf_lru_pop_free+0x157/0x370 kernel/bpf/bpf_lru_list.c:502
prealloc_lru_pop+0x23/0xf0 kernel/bpf/hashtab.c:308
htab_lru_map_update_elem+0x14c/0xbe0 kernel/bpf/hashtab.c:1251
bpf_map_update_value+0x675/0xf50 kernel/bpf/syscall.c:289
generic_map_update_batch+0x44a/0x5f0 kernel/bpf/syscall.c:1963
bpf_map_do_batch+0x4be/0x610 kernel/bpf/syscall.c:5303
__sys_bpf+0x1002/0x1630 kernel/bpf/syscall.c:5859
__do_sys_bpf kernel/bpf/syscall.c:5902 [inline]
__se_sys_bpf kernel/bpf/syscall.c:5900 [inline]
__x64_sys_bpf+0x78/0xc0 kernel/bpf/syscall.c:5900
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xcb/0x260 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fef14fb85ad
Code: 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48
89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d
01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fef15ddcf98 EFLAGS: 00000246 ORIG_RAX: 0000000000000141
RAX: ffffffffffffffda RBX: 00007fef15245fa0 RCX: 00007fef14fb85ad
RDX: 0000000000000038 RSI: 0000400000000000 RDI: 000000000000001a
RBP: 00007fef1506a8d6 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 0000000000000000 R14: 00007fef15245fa0 R15: 00007fef15dbd000
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:__list_add_valid_or_report+0xfc/0x1a0 lib/list_debug.c:29
Code: 00 00 00 00 fc ff df 48 c1 ea 03 80 3c 02 00 0f 85 a6 00 00 00
49 8b 54 24 08 4c 89 e1 48 c7 c7 c0 1f f2 8b e8 55 54 d3 fc 90 <0f> 0b
48 89 f7 48 89 34 24 e8 16 54 33 fd 48 8b 34 24 48 b8 00 00
RSP: 0018:ffffc900033779b0 EFLAGS: 00010046
RAX: 0000000000000075 RBX: ffffc900035777c8 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: ffffe8ffac433e40 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: ffffe8ffac433e41
R13: ffffc900035777c8 R14: ffffe8ffac433e49 R15: ffffe8ffac433e50
FS: 00007fef15ddd640(0000) GS:ffff88802b600000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007ffd53abb238 CR3: 00000000296f4000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Regards,
Strforexc