syzbot
general protection fault in mac80211_hwsim_tx_frame_no_nl (2)
Status:
moderation: reported on 2026/11/09 17:34
Subsystems:
wireless
Labels:
prio:high
[Documentation on labels]
Reported-by: syzbot+87abc552a237461a0cdf@syzkaller.appspotmail.com
First crash: 1h19m, last: 1h19m
✨ AI-generated root cause summary:
In mac80211_hwsim_tx_frame_no_nl, the driver iterates over virtual radios using list_for_each_entry(data2, &hwsim_radios, list) while holding hwsim_radio_lock. During iteration, the data2 pointer (held in %r14) evaluated to 0xffffffffffffffff (-1) due to list corruption of hwsim_radios.next or an entry's list.next. When initializing struct tx_iter_data tx_iter_data = { .hw = data2->hw, ... }, the kernel attempts to dereference data2->hw at offset 0x18 (evaluating to address 0x17), triggering a KASAN null-ptr-deref / non-canonical GPF in softirq context.
▶
▼
✨ Full AI root cause analysis
Technical Breakdown of the Root Cause
1. Context and Involved Components
- Source File:
drivers/net/wireless/virtual/mac80211_hwsim_main.c
- Functions:
mac80211_hwsim_tx_frame_no_nl() (line 1974)
mac80211_hwsim_beacon_tx() / __mac80211_hwsim_beacon_tx()
mac80211_hwsim_beacon() (hrtimer softirq handler)
- Data Structures and Fields:
struct mac80211_hwsim_data (drivers/net/wireless/virtual/mac80211_hwsim_i.h:51):
list (struct list_head, offset 0, size 16 bytes)
hw (struct ieee80211_hw *, offset 0x18 / 24 bytes)
struct tx_iter_data:
hw (struct ieee80211_hw *, offset 0x10)
- Global list head:
hwsim_radios (LIST_HEAD(hwsim_radios))
- Global spinlock:
hwsim_radio_lock
2. Crash Analysis & Mechanism
-
Triggering Context:
The crash occurred in softirq context when the high-resolution timer callback mac80211_hwsim_beacon() fired via hrtimer_run_softirq().
mac80211_hwsim_beacon() iterates through active wireless interfaces (ieee80211_iterate_active_interfaces_atomic) and invokes mac80211_hwsim_beacon_tx(), which delegates packet transmission to mac80211_hwsim_tx_frame() and mac80211_hwsim_tx_frame_no_nl().
-
Faulty Access:
In mac80211_hwsim_tx_frame_no_nl():
spin_lock(&hwsim_radio_lock);
list_for_each_entry(data2, &hwsim_radios, list) {
struct sk_buff *nskb;
struct tx_iter_data tx_iter_data = {
.receive = false,
.hw = data2->hw,
...
};
...
}
At line 1974, tx_iter_data unconditionally initializes .hw = data2->hw. In struct mac80211_hwsim_data, list is at offset 0x0, and hw is located at offset 0x18.
-
Disassembly & Register State:
49 8d 7e 18 lea 0x18(%r14),%rdi
...
48 89 f8 mov %rdi,%rax
48 c1 e8 03 shr $0x3,%rax
80 3c 18 00 cmpb $0x0,(%rax,%rbx,1) <-- GPF trapping instruction
...
49 8b 46 18 mov 0x18(%r14),%rax <-- data2->hw dereference
- Register
%r14 holds data2. Its value at the time of the crash was 0xffffffffffffffff ((void *)-1).
lea 0x18(%r14), %rdi computed address 0xffffffffffffffff + 0x18 = 0x17.
- The inline KASAN shadow address check computed
0xdffffc0000000000 + (0x17 >> 3) = 0xdffffc0000000002.
- Address
0xdffffc0000000002 is non-canonical on x86_64, which tripped a General Protection Fault (GPF). KASAN decoded the target address 0x17 as a null-pointer-range dereference in range [0x0000000000000010-0x0000000000000017].
-
Root Cause:
The list_for_each_entry macro traversed a node in hwsim_radios whose next pointer contained 0xffffffffffffffff (-1).
data2 = list_entry(pos, typeof(*data2), list) casts pos directly to data2 because list is at offset 0 of struct mac80211_hwsim_data.
- Either
hwsim_radios.next or an element's data2->list.next pointer was clobbered by a wild pointer or memory corruption.
- Additionally,
mac80211_hwsim_tx_frame_no_nl() uses spin_lock(&hwsim_radio_lock) rather than spin_lock_bh(&hwsim_radio_lock). While all writers (hwsim_del_radio_nl, remove_user_radios, hwsim_exit_net) use spin_lock_bh, calling spin_lock(&hwsim_radio_lock) from process context (mac80211_hwsim_tx) leaves bottom halves enabled, allowing same-CPU softirq preemption by mac80211_hwsim_beacon() leading to spinlock lockups (evident from Tainted: [L]=SOFTLOCKUP).
- The subsequent attempt to read
data2->hw on the invalid data2 pointer (-1) causes an immediate crash.
Sample crash report:
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000002: 0000 [#1] SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017]
CPU: 3 UID: 0 PID: 8630 Comm: syz.5.514 Tainted: G L syzkaller #0 PREEMPT(full)
Tainted: [L]=SOFTLOCKUP
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:mac80211_hwsim_tx_frame_no_nl+0x856/0x1840 drivers/net/wireless/virtual/mac80211_hwsim_main.c:1974
Code: 0f 84 a4 04 00 00 e8 09 a4 94 fa 48 8b 04 24 49 8d 7e 18 4c 89 bc 24 98 00 00 00 48 89 84 24 a0 00 00 00 48 89 f8 48 c1 e8 03 <80> 3c 18 00 0f 85 43 0d 00 00 49 8b 46 18 4c 89 ac 24 b0 00 00 00
RSP: 0018:ffffc90000718b40 EFLAGS: 00010203
RAX: 0000000000000002 RBX: dffffc0000000000 RCX: 0000000000000102
RDX: ffff88802d7d0000 RSI: ffffffff8779dcf7 RDI: 0000000000000017
RBP: ffff88805acf32c0 R08: 0000000000000004 R09: 00000000ffffffff
R10: 0000000000000001 R11: 0000000000000001 R12: 00000000ffffffff
R13: ffff888026f57e00 R14: ffffffffffffffff R15: ffff88805acf3558
FS: 00007f3e550b56c0(0000) GS:ffff8880d4771000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000110c395fab CR3: 00000000293a2000 CR4: 0000000000352ef0
Call Trace:
<IRQ>
mac80211_hwsim_tx_frame+0x1b7/0x250 drivers/net/wireless/virtual/mac80211_hwsim_main.c:2440
__mac80211_hwsim_beacon_tx drivers/net/wireless/virtual/mac80211_hwsim_main.c:2453 [inline]
mac80211_hwsim_beacon_tx+0x56d/0xa00 drivers/net/wireless/virtual/mac80211_hwsim_main.c:2516
__iterate_interfaces+0x2e6/0x650 net/mac80211/util.c:775
ieee80211_iterate_active_interfaces_atomic+0x71/0x1b0 net/mac80211/util.c:811
mac80211_hwsim_beacon+0xe5/0x2a0 drivers/net/wireless/virtual/mac80211_hwsim_main.c:2548
__run_hrtimer kernel/time/hrtimer.c:2079 [inline]
__hrtimer_run_queues+0x448/0x9a0 kernel/time/hrtimer.c:2136
hrtimer_run_softirq+0x1ca/0x360 kernel/time/hrtimer.c:2153
handle_softirqs+0x216/0xa20 kernel/softirq.c:669
__do_softirq kernel/softirq.c:703 [inline]
invoke_softirq kernel/softirq.c:542 [inline]
__irq_exit_rcu+0x178/0x220 kernel/softirq.c:786
irq_exit_rcu+0x9/0x30 kernel/softirq.c:809
instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1062 [inline]
sysvec_apic_timer_interrupt+0xa3/0xc0 arch/x86/kernel/apic/apic.c:1062
</IRQ>
<TASK>
asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:674
RIP: 0010:__raw_spin_unlock_irq include/linux/spinlock_api_smp.h:220 [inline]
RIP: 0010:_raw_spin_unlock_irq+0x29/0x50 kernel/locking/spinlock.c:229
Code: 90 f3 0f 1e fa 53 48 8b 74 24 08 48 89 fb 48 83 c7 18 e8 7a fe f6 f5 48 89 df e8 02 55 f7 f5 e8 ed 69 24 f6 fb bf 01 00 00 00 <e8> 52 1b e6 f5 65 48 83 3d c1 82 c8 09 00 74 06 5b c3 cc cc cc cc
RSP: 0018:ffffc9000617fc28 EFLAGS: 00000206
RAX: 0000000000000393 RBX: ffffffff90cc4bc0 RCX: 0000000000000080
RDX: 0000000000000001 RSI: ffffffff8e629a5f RDI: 0000000000000001
RBP: 0000000000000060 R08: 0000000000000001 R09: 0000000000000000
R10: 0000000000000001 R11: 0000000000000000 R12: ffff888024d23000
R13: 0000000054b508cd R14: ffffffff8be3bfb0 R15: 0000000000000054
pci_user_write_config_dword+0x150/0x230 drivers/pci/access.c:278
proc_bus_pci_write+0x531/0x5e0 drivers/pci/proc.c:173
pde_write fs/proc/inode.c:330 [inline]
proc_reg_write+0x240/0x330 fs/proc/inode.c:342
vfs_write+0x2aa/0x1040 fs/read_write.c:685
ksys_write+0x12a/0x250 fs/read_write.c:739
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x123/0x7b0 arch/x86/entry/syscall_64.c:89
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f3e5419fb19
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 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 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f3e550b5028 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 00007f3e54426090 RCX: 00007f3e5419fb19
RDX: 000000000000007f RSI: 0000200000000200 RDI: 0000000000000008
RBP: 00007f3e54237b70 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f3e54426128 R14: 00007f3e54426090 R15: 00007ffd874ac108
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:mac80211_hwsim_tx_frame_no_nl+0x856/0x1840 drivers/net/wireless/virtual/mac80211_hwsim_main.c:1974
Code: 0f 84 a4 04 00 00 e8 09 a4 94 fa 48 8b 04 24 49 8d 7e 18 4c 89 bc 24 98 00 00 00 48 89 84 24 a0 00 00 00 48 89 f8 48 c1 e8 03 <80> 3c 18 00 0f 85 43 0d 00 00 49 8b 46 18 4c 89 ac 24 b0 00 00 00
RSP: 0018:ffffc90000718b40 EFLAGS: 00010203
RAX: 0000000000000002 RBX: dffffc0000000000 RCX: 0000000000000102
RDX: ffff88802d7d0000 RSI: ffffffff8779dcf7 RDI: 0000000000000017
RBP: ffff88805acf32c0 R08: 0000000000000004 R09: 00000000ffffffff
R10: 0000000000000001 R11: 0000000000000001 R12: 00000000ffffffff
R13: ffff888026f57e00 R14: ffffffffffffffff R15: ffff88805acf3558
FS: 00007f3e550b56c0(0000) GS:ffff8880d4771000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000110c395fab CR3: 00000000293a2000 CR4: 0000000000352ef0
----------------
Code disassembly (best guess):
0: 0f 84 a4 04 00 00 je 0x4aa
6: e8 09 a4 94 fa call 0xfa94a414
b: 48 8b 04 24 mov (%rsp),%rax
f: 49 8d 7e 18 lea 0x18(%r14),%rdi
13: 4c 89 bc 24 98 00 00 mov %r15,0x98(%rsp)
1a: 00
1b: 48 89 84 24 a0 00 00 mov %rax,0xa0(%rsp)
22: 00
23: 48 89 f8 mov %rdi,%rax
26: 48 c1 e8 03 shr $0x3,%rax
* 2a: 80 3c 18 00 cmpb $0x0,(%rax,%rbx,1) <-- trapping instruction
2e: 0f 85 43 0d 00 00 jne 0xd77
34: 49 8b 46 18 mov 0x18(%r14),%rax
38: 4c 89 ac 24 b0 00 00 mov %r13,0xb0(%rsp)
3f: 00
* Struck through repros no longer work on HEAD.