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: 1h05m, last: 1h05m
✨ 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
Based on kernel commit 7475ea8b5861:

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

  1. 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().

  2. 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.

  3. 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].
  4. 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.
▶ ▼ ✨ AI Jobs (1)
ID Workflow Result Correct Bug Created Started Finished Revision
da202da2 assessment-security DenialOfService: ✅ Exploitable: ✅ FilesystemTrigger: ❌ FuzzingArtifact: ❌ MemoryCorruption: ✅ NetworkNeedsSetup: ❌ NetworkTrigger: ❌ PeripheralTrigger: ❌ RemoteTrigger: ❌ Unprivileged: ❌ UserNamespace: ✅ VMGuestTrigger: ❌ VMHostTrigger: ❌ ❓ general protection fault in mac80211_hwsim_tx_frame_no_nl (2) 2026/11/09 16:52 2026/11/09 16:53 2026/11/09 17:33 5cecaf1f
▶ ▼ Similar bugs (1)
Kernel Title Rank 🛈 Repro Cause bisect Fix bisect Count Last Reported Patched Status
upstream general protection fault in mac80211_hwsim_tx_frame_no_nl wireless 2 1 2236d 2233d 0/29 auto-closed as invalid on 2021/01/23 17:51

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

Crashes (1):
Time Kernel Commit Syzkaller Config Log Report Syz repro C repro VM info Assets (help?) Manager Title
2026/11/09 16:52 upstream 7475ea8b5861 5cecaf1f .config console log report info [disk image (non-bootable)] [vmlinux] [kernel image] ci-qemu-upstream general protection fault in mac80211_hwsim_tx_frame_no_nl
* Struck through repros no longer work on HEAD.