# Collected Facts — `69efb8dd.050a0220.18b4f.0006.GAE@google.com` ## Debug symbols - **vmlinux path**: `oops-workdir/syzbot/vmlinux-254f4963` (pre-fetched by fetcher agent) - **Source**: syzbot asset URL `https://storage.googleapis.com/syzbot-assets/2a93e1c819bd/vmlinux-254f4963.xz` - **File type**: ELF 64-bit LSB executable, x86-64 - **Download status**: Success (decompressed, verified non-empty by fetcher) - **Kernel version from vmlinux**: Linux 7.1-rc1 (tag `v7.1-rc1`, commit `254f49634ee1`) ## Source tree - **Path**: `oops-workdir/linux` - **HEAD commit**: `254f49634ee1` — "Linux 7.1-rc1" - **Checkout method**: `git checkout 254f49634ee1` (performed by fetcher) - **semcode index**: refreshed at `oops-workdir/linux/.semcode.db` ## Resolved addresses All entries resolved via `backtrace_resolve.py` (batch) plus manual `gdb` for entries where `addr2line` returned line 0. | Index | Function | Offset | Address (computed) | Resolved source | Method | Notes | |-------|----------|--------|--------------------|-----------------|--------|-------| | 0 | `mac80211_hwsim_link_info_changed` | 0x476 | `0xffffffff870a6c76` | `mac80211_hwsim.c:2734` | gdb manual | addr2line returned line 0 — DWARF incomplete; gdb resolved OK | | 1 | `drv_link_info_changed` | 0x505 | `0xffffffff8b126765` | `driver-ops.c:497` | gdb manual | addr2line returned line 0; gdb resolved OK | | 2 | `ieee80211_offchannel_return` | 0x375 | `0xffffffff8b163635` | `offchannel.c:160` | script | | | 3 | `__ieee80211_scan_completed` | 0x75a | `0xffffffff8b15db6a` | `scan.c:519` | script | | | 4 | `cfg80211_wiphy_work` | 0x2cf | `0xffffffff8af01cbf` | `core.c:513` | gdb manual | addr2line returned line 0 | | 5 (inline) | `process_one_work` | — | — | `workqueue.c:3302` | source_hint | inlined into process_scheduled_works | | 5 | `process_scheduled_works` | 0xb5d | `0xffffffff818e85ad` | `workqueue.c:3302` | gdb manual | addr2line returned line 0; gdb resolved to 3302 (inlined process_one_work boundary) | | 6 | `worker_thread` | 0xa53 | `0xffffffff818f0613` | `workqueue.c:3466` | script | | | 7 | `kthread` | 0x388 | `0xffffffff81908118` | `kthread.c:436` | script | | | 8 | `ret_from_fork` | 0x514 | `0xffffffff816bcae4` | `arch/x86/kernel/process.c:158` | script | | | 9 | `ret_from_fork_asm` | 0x1a | `0xffffffff813340aa` | `arch/x86/entry/entry_64.S:245` | script | | ## Code bytes Raw code bytes from crash report: ``` 3c 06 00 49 89 c6 48 8b 7c 24 20 74 0a e8 42 72 26 fb 48 8b 7c 24 20 48 8b 0f 89 ce 4c 89 e0 48 c1 e8 20 74 60 4c 89 e0 31 d2 48 f7 f6 eb 5d e8 30 37 bb fa 4c 8b 74 24 20 49 8d 7e 10 e8 a2 e4 ... ``` Decoded instruction window (best guess, 3 bytes skipped at start): ``` 0: 49 89 c6 mov %rax,%r14 3: 48 8b 7c 24 20 mov 0x20(%rsp),%rdi ← load ptr to link_data->beacon_int 8: 74 0a je 0x14 ← skip KASAN report a: e8 42 72 26 fb call 0xfb267251 ← __asan_report_load8_noabort f: 48 8b 7c 24 20 mov 0x20(%rsp),%rdi 14: 48 8b 0f mov (%rdi),%rcx ← load 8 bytes (link_data->beacon_int) 17: 89 ce mov %ecx,%esi ← truncate to u32 → RSI = bcn_int 19: 4c 89 e0 mov %r12,%rax ← rax = tsf (u64) 1c: 48 c1 e8 20 shr $0x20,%rax ← check high 32 bits 20: 74 60 je 0x82 ← fast path if tsf fits in 32 bits 22: 4c 89 e0 mov %r12,%rax ← rax = tsf (full) 25: 31 d2 xor %edx,%edx ← rdx = 0 * 27: 48 f7 f6 div %rsi ← TRAP: RSI = 0, divide error 2a: eb 5d jmp 0x89 ``` Disassembly from `backtrace_resolve.py` with absolute addresses (index 0): ``` ffffffff870a6c3c: add 0x0(%r13),%r12 ffffffff870a6c40: movabs $0xdffffc0000000000,%rax ffffffff870a6c4a: cmpb $0x0,(%r14,%rax,1) ffffffff870a6c4f: mov %rax,%r14 ffffffff870a6c52: mov 0x20(%rsp),%rdi ffffffff870a6c57: je ffffffff870a6c63 ffffffff870a6c59: call ffffffff8230dea0 <__asan_report_load8_noabort> ffffffff870a6c5e: mov 0x20(%rsp),%rdi ffffffff870a6c63: mov (%rdi),%rcx ffffffff870a6c66: mov %ecx,%esi ffffffff870a6c68: mov %r12,%rax ffffffff870a6c6b: shr $0x20,%rax ffffffff870a6c6f: je ffffffff870a6cd1 ffffffff870a6c71: mov %r12,%rax ffffffff870a6c74: xor %edx,%edx ffffffff870a6c76: div %rsi <<< crash ffffffff870a6c79: jmp ffffffff870a6cd8 ffffffff870a6c7b: call ffffffff81c5a3b0 <__sanitizer_cov_trace_pc> ffffffff870a6c80: mov 0x20(%rsp),%r14 ffffffff870a6c85: lea 0x10(%r14),%rdi ffffffff870a6c89: call ffffffff81b25130 ``` ## Register annotations | Register | Value | Annotation | |----------|-------|------------| | RAX | `0x000650757bb12572` | TSF value (u64), dividend; high 32 bits = `0x00065075` ≠ 0 → 64-bit `div` path taken | | RBX | `0x0000000000000200` | `BSS_CHANGED_BEACON_ENABLED` = `1<<9` = `0x200` (the `changed` bitmask bit) | | RCX | `0x0000000000000000` | `link_data->beacon_int` read via `mov (%rdi),%rcx` = 0 | | RDX | `0x0000000000000000` | High half of dividend; cleared by `xor %edx,%edx` before `div` | | RSI | `0x0000000000000000` | Divisor = `bcn_int` (low 32 bits of RCX); zero → triggers #DE | | RDI | `0xffff88806fbe7b98` | Address passed in `0x20(%rsp)`; points to `link_data->beacon_int` field | | RBP | `0xffffc90002ea7958` | Stack frame pointer | | R12 | `0x000650757bb12572` | TSF value (copy used for `mov %r12,%rax` before `div`) | | R13 | `0xffff88806fbe7b18` | Likely `link_data` base pointer (RDI - 0x80 = link_data + 8 would be beacon_int) | | R14 | `0xdffffc0000000000` | KASAN shadow base pointer (used in `cmpb $0x0,(%r14,%rax,1)`) | | RSP | `0xffffc90002ea7860` | Kernel stack pointer | ## Full source excerpts ### `mac80211_hwsim_link_data` struct (`mac80211_hwsim.c:660–664`) ```c 660struct mac80211_hwsim_link_data { 661u32 link_id; 662u64 beacon_int/* beacon interval in us */; 663struct hrtimer beacon_timer; 664}; ``` Field `beacon_int` is `u64` (8 bytes) at struct offset 8 (after `link_id` u32 + 4 bytes padding). Field `bcn_int` in the crash function is declared as `u32` at line 2730. ### `mac80211_hwsim_link_info_changed` full relevant block (`mac80211_hwsim.c:2722–2750`) ```c 2722if (changed & BSS_CHANGED_BEACON_ENABLED) { 2723wiphy_dbg(hw->wiphy, " BCN EN: %d (BI=%u)\n", 2724 info->enable_beacon, info->beacon_int); 2725vp->bcn_en = info->enable_beacon; 2726if (data->started && 2727 !hrtimer_active(&link_data->beacon_timer) && 2728 info->enable_beacon) { 2729u64 tsf, until_tbtt; 2730u32 bcn_int; 2731link_data->beacon_int = info->beacon_int * 1024; 2732tsf = mac80211_hwsim_get_tsf(hw, vif); 2733bcn_int = link_data->beacon_int; 2734until_tbtt = bcn_int - do_div(tsf, bcn_int); 2735 2736hrtimer_start(&link_data->beacon_timer, 2737 ns_to_ktime(until_tbtt * NSEC_PER_USEC), 2738 HRTIMER_MODE_REL_SOFT); 2739} else if (!info->enable_beacon) { 2740unsigned int count = 0; 2741ieee80211_iterate_active_interfaces_atomic( 2742data->hw, IEEE80211_IFACE_ITER_NORMAL, 2743mac80211_hwsim_bcn_en_iter, &count); 2744wiphy_dbg(hw->wiphy, " beaconing vifs remaining: %u", 2745 count); 2746if (count == 0) { 2747hrtimer_cancel(&link_data->beacon_timer); 2748link_data->beacon_int = 0; 2749} 2750} ``` ### `ieee80211_offchannel_return` full function (`offchannel.c:133–169`) ```c 133void ieee80211_offchannel_return(struct ieee80211_local *local) 134{ 135struct ieee80211_sub_if_data *sdata; 136 137lockdep_assert_wiphy(local->hw.wiphy); 138 139if (WARN_ON(!local->emulate_chanctx)) 140return; 141 142list_for_each_entry(sdata, &local->interfaces, list) { 143if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) 144continue; 145if (sdata->vif.type != NL80211_IFTYPE_MONITOR) 146clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); 147if (!ieee80211_sdata_running(sdata)) 148continue; 149/* Tell AP we're back */ 150if (sdata->vif.type == NL80211_IFTYPE_STATION && 151 sdata->u.mgd.associated) 152ieee80211_offchannel_ps_disable(sdata); 153if (test_and_clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, 154 &sdata->state)) { 155sdata->vif.bss_conf.enable_beacon = true; 156ieee80211_link_info_change_notify( 157sdata, &sdata->deflink, 158BSS_CHANGED_BEACON_ENABLED); 159} 160} 161 162ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, 163IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, 164false); 165} ``` Note: `ieee80211_offchannel_return` sets `enable_beacon = true` and notifies with `BSS_CHANGED_BEACON_ENABLED` but does **not** set `info->beacon_int` before the notification. ## git blame details for crash-site lines | File | Line | Hash (abbrev) | Full hash | Author | Date | Subject | |------|------|---------------|-----------|--------|------|---------| | mac80211_hwsim.c | 2731 | `e57f8a489c29` | `e57f8a489c294d83cc4e2c9cba1432f99fbf7fdd` | Shaul Triebitz | 2022-06-06 | `wifi: mac80211_hwsim: send a beacon per link` | | mac80211_hwsim.c | 2732 | `c51f878379b1` | `c51f878379b1d0677619798b1d9358d053bdbdb1` | Thomas Pedersen | 2013-01-02 | `mac80211_hwsim: fix beacon timing` | | mac80211_hwsim.c | 2733 | `e57f8a489c29` | `e57f8a489c294d83cc4e2c9cba1432f99fbf7fdd` | Shaul Triebitz | 2022-06-06 | `wifi: mac80211_hwsim: send a beacon per link` | | mac80211_hwsim.c | 2734 | `c51f878379b1` | `c51f878379b1d0677619798b1d9358d053bdbdb1` | Thomas Pedersen | 2013-01-02 | `mac80211_hwsim: fix beacon timing` | | mac80211_hwsim.c | 2728 | `01e59e467ecf` | `01e59e467ecf976c782eecd4dc99644802cc60e2` | Thomas Pedersen | 2013-01-02 | `mac80211_hwsim: hrtimer beacon` | No upstream fix commits found (searched with `git log --all --grep "Fixes: c51f878379b1\|Fixes: e57f8a489c29"`). ## Factual notes - Crash type is x86 #DE (divide error), EFLAGS bit 1 (ZF) set at crash (EFLAGS = 0x00010246), which is consistent with the result of a prior comparison but is not the cause; the exception is triggered by `div %rsi` with RSI = 0. - The `div %rsi` instruction is a 64-bit unsigned division (RDX:RAX / RSI). It was reached because the high 32 bits of the TSF value were non-zero (`shr $0x20,%rax` showed a non-zero result), causing the code to bypass the fast-path `je` at `ffffffff870a6c6f` and execute the 64-bit `div`. - KASAN instrumentation is present (syzbot build). A KASAN `__asan_report_load8_noabort` shadow check appears immediately before the `mov (%rdi),%rcx` load. The shadow check passed (no KASAN report in the crash); the memory was accessible. The zero value `0` was legitimately stored there. - `link_data->beacon_int` is declared as `u64` in `struct mac80211_hwsim_link_data` (line 662). The local variable `bcn_int` at line 2730 is `u32`. The assignment `bcn_int = link_data->beacon_int` (line 2733) truncates the u64 field to u32. - The disasm shows `mov (%rdi),%rcx` (8-byte load) followed by `mov %ecx,%esi` (32-bit truncation), consistent with the compiler accessing the u64 `beacon_int` field and then truncating to u32 for `bcn_int`. - `ieee80211_offchannel_return` (offchannel.c:159) sets `sdata->vif.bss_conf.enable_beacon = true` and calls `ieee80211_link_info_change_notify` with `BSS_CHANGED_BEACON_ENABLED`. This notification reaches `mac80211_hwsim_link_info_changed` with `info->enable_beacon` true. - The condition at line 2726–2728 requires `data->started && !hrtimer_active(beacon_timer) && info->enable_beacon`. This was satisfied, allowing entry to the beacon timer setup block at lines 2731–2738. - The field `link_data->beacon_int` (u64) was 0 at the time of the crash. This field was loaded into RCX (confirmed: RCX = 0), then into RSI (32-bit truncation, RSI = 0), then used as divisor in `div %rsi`. - The taint flag `L` (softlockup) is present in the crash header. The `Tainted: [L]=SOFTLOCKUP` line confirms this. This indicates a prior softlockup on the system; it does not directly relate to the divide error crash. - No locks-held block was present in the crash report; no lock activity table constructed.