| 0/0 |
2026/06/27 02:04 |
flow |
assessment-security |
16m
Results: map[DenialOfService:true Explanation:**Bug Analysis:**
The crash is a NULL pointer dereference occurring in
`__ieee80211_get_radio_mask` within the `mac80211` subsystem.
The sequence of events leading to the crash is as follows:
1. When a new channel context is being created (e.g., when joining an IBSS
network), `mac80211` checks if it can create a new context by calling
`ieee80211_max_num_channels(local, radio_idx)`.
2. This invokes `cfg80211_iter_combinations()` with a specific `radio_idx >= 0`.
3. `cfg80211_iter_combinations()` calls `cfg80211_calculate_bi_data()`, which
iterates over all wireless devices (`wdev`) on the wiphy to calculate beacon
interval data.
4. For each `wdev`, it checks if the device is active on the given radio by
calling `rdev_get_radio_mask(rdev, wdev->netdev)`.
5. However, certain interface types (such as `NL80211_IFTYPE_P2P_DEVICE` or
`NL80211_IFTYPE_NAN`) do not have an associated `netdev`, meaning `wdev->netdev`
is `NULL`.
6. `mac80211`'s implementation of the `get_radio_mask` callback
(`ieee80211_get_radio_mask`) does not check if the `dev` pointer is `NULL`. It
directly calls `IEEE80211_DEV_TO_SUB_IF(dev)`, which uses `netdev_priv(dev)`.
7. `netdev_priv(NULL)` returns a small offset (e.g., `0xec0`), and the
subsequent attempt to access `sdata->vif.active_links` in
`__ieee80211_get_radio_mask` results in a general protection fault or NULL
pointer dereference.
**Security Impact:**
* **Exploitable:** No. The bug is a read access to a small offset relative to a
NULL pointer (e.g., `0x34fa`). The memory access will reliably page fault and
crash the kernel. It cannot be used for memory corruption, privilege escalation,
or information leaks.
* **Denial of Service:** Yes. Triggering the bug results in a kernel oops/panic,
leading to a local denial of service.
* **Accessible From Unprivileged Processes / User Namespaces:** No. To trigger
this bug, a user must first create a wireless interface without a `netdev` (like
a P2P Device) and then initiate a connection that creates a new channel context
(like joining an IBSS). Both of these `nl80211` commands require `CAP_NET_ADMIN`
in the network namespace of the wireless device. Since wireless devices
typically reside in the initial network namespace and cannot be moved by
unprivileged users, this is completely inaccessible to unprivileged processes or
from within unprivileged user namespaces.
* **Remote / Peripheral / VM Triggers:** No. The bug is triggered strictly via
local administrative configuration commands (netlink) and is not reachable via
remote network packets, malicious USB devices, or VM guest interactions. Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:false UserNamespace:false VMGuestTrigger:false VMHostTrigger:false]
|
| 1/1 |
2026/06/27 02:04 |
action |
syz-repro-to-c-repro |
0m
Results:
|
| 2/1 |
2026/06/27 02:04 |
action |
kernel-checkouter |
0m
Results: map[KernelSrc:/app/workdir/cache/src/27ac4aa0933e119b340d7ec120e45871a4d047fa]
|
| 3/1 |
2026/06/27 02:04 |
action |
kernel-builder |
0m
Results: map[KernelObj:/app/workdir/cache/build/95b02bb79fdc7df30f68a6bf902fe95a420dd1dc]
|
| 4/1 |
2026/06/27 02:04 |
action |
codesearch-prepare |
0m
Results: map[Index:codesearch-index]
|
| 5/1 |
2026/06/27 02:04 |
agent |
expert |
15m
Model:
Results: map[DenialOfService:true Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:false UserNamespace:false VMGuestTrigger:false VMHostTrigger:false]
Instruction: You are an experienced Linux kernel security engineer. Your task is to analyze given kernel bug report
and determine its security impact based on the following dimensions.
Use the provided tools to examine the source code, check for capability checks (e.g., capable(), ns_capable()),
and understand the nature of the bug. Analyze the given kernel build and configuration.
You can check the kernel config by grepping ".config" file; you can check kernel cmdline by grepping
".config" file for "CONFIG_CMDLINE=". Assume sysctl parameters have default values.
But analyze for the corresponding production build w/o debugging tools enabled (like KASAN, KMSAN, UBSAN).
Try different strategies when analyzing the bug:
- think of ways in which the vulnerable code is unreachable
- or the other way around: try to come up with different ideas of how an unprivileged user can reach the bug
If still unsure err on the side of the bug being non-exploitable/not-accessible.
In the final reply, provide a reasoning for your assessment.
Analysis dimensions:
* Exploitable:
Determine if the bug can result in memory corruption, elevated privileges, or an information leak.
Memory safety issues are almost always exploitable (KASAN or UBSAN reports for use-after-free, out-of-bounds;
refcounting issues, corrupted lists, etc). When kernel is crashing on a completely wild pointer access
(e.g. user-space address, or non-canonical address, but not on NULL or address corresponding to KASAN shadow
for NULL address), including both data accesses and control transfers, that also usually implies possibility
of exploitation. Such reports usually say "unable to handle kernel paging request".
Uses of uninitialized values detected by KMSAN may be exploitable b/c attacker frequently can affect uninit
values with spraying techniques. However, for these exploitability depends on how exactly the uninit value
is used in the code, and what it affects.
Information leaks are exploitable on their own and should be classified as such. A bug that copies kernel
memory contents to userspace (e.g. an out-of-bounds read whose result is returned to the caller, or
uninitialized stack/heap bytes written to a user buffer) is exploitable: it can reveal kernel pointer
values and defeat KASLR, expose sensitive data such as cryptographic keys or other processes' memory, and
serves as a necessary building block in most modern kernel privilege-escalation exploit chains. Do not classify
an information leak as non-exploitable solely because it does not directly cause a memory write or control-flow
hijack; the leak itself is the exploit primitive.
Think of what happens after the bug is triggered. Some bugs cause kernel panic and halt execution,
they are harder to exploit. For example, BUG reports halts the kernel. However, WARNING reports don't halt
execution in production builds. Debug bug detection tools (like KASAN, KMSAN, KCSAN, UBSAN) are also not enabled
in production builds, so attacker can freely exploit these bugs w/o being detected by these tools.
If you see an integer overflow, think how the overflowed value used later (if it's used as allocation size,
or an array index). If you see an out-of-bounds read, think if it's followed by an out-of-bounds write as well.
Some KCSAN data-races may be exploitable by skilled attackers as well. Think what data structures got corrupted
as the result of data races and how. However, note that kernel has lots of "benign" data races that don't lead
to any runtime misbehavior at all.
* Denial Of Service:
Determine if the bug can result in denial-of-service. Most bugs can, since they cause system crash,
hangs, deadlocks, or resource leaks. This is mostly applicable to WARNING bugs that won't cause system crash
in production. For these think what will be consequences of the violation of the kernel assumptions flagged
by the WARNING. In some cases the unexpected condition is also properly handled by the normal control flow
(e.g. with "if (WARN_ON(...))"), these won't cause denial-of-service. If the condition is not handled,
then it may or may not cause denial-of-service.
* Accessible From Unprivileged Processes:
Determine if the bug can be reached from a typical (non-root) user process that does NOT have any special capabilities
(like CAP_SYS_ADMIN, CAP_NET_ADMIN, CAP_NET_RAW, CAP_PERFMON) or access to device nodes restricted to root.
Assume that unprivileged_bpf_disabled=1, that is eBPF loading is not accessible. However, cBPF (classical BPF)
is still accessible to non-root processes.
Assume that user namespaces are not accessible, that is, the process cannot get the mentioned capabilities even
within a new user namespace (checked by ns_capable() function in the kernel sources).
* Accessible From User Namespaces:
Determine if the bug can be reached within a user-namespace where the process has all capabilities
(including CAP_SYS_ADMIN, CAP_NET_ADMIN, CAP_NET_RAW, CAP_PERFMON). Such capabilities are checked with ns_capable()
function in the kernel sources.
* VM Guest Trigger:
Determine if the bug can be triggered from the context of a typical KVM guest (e.g., set up by a QEMU VMM).
Consider accesses to standard Linux host paravirtualized features (virtio-blk, virtio-net, etc.),
and handling of VM exits in the KVM code.
* VM Host Trigger in The Confidential Computing Context:
Determine if the bug can be triggered in a confidential computing guest kernel from the context of a KVM host.
Consider access to standard Linux guest paravirtualized features (virtio-blk, virtio-net, etc.).
* Ethernet Network Trigger:
Determine if the bug can be triggered by processing ingress network Ethernet traffic, either directly (network stack)
or via drivers exposed to network data.
* Other Remote Trigger:
Determine if the bug can be triggered by processing remote traffic other than Ethernet (Wifi, Bluetooth, NFC, etc).
* Peripheral Trigger:
Determine if the bug can be triggered via an untrusted peripheral device that can be physically plugged
into a system, such as a USB device or a niche hardware driver handling external hardware inputs.
This is particularly important for mobile and desktop environments where users can plug in unknown devices.
* Malicious Filesystem Trigger:
Determine if the bug can be triggered by the kernel mounting and parsing a malicious filesystem image.
This is highly critical for Desktop and Mobile environments where external media or downloaded images
might be auto-mounted.
Don't make assumptions about the kernel source code (it may be different from what you assume it is).
Extensively use the provided code access tools (codesearch-*, git-*, grepper, etc)
to examine the actual source code, and confirm any assumptions.
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt:
The kernel bug report is:
wlan0: Created IBSS using preconfigured BSSID 50:50:50:50:50:50
wlan0: Creating new IBSS network, BSSID 50:50:50:50:50:50
Oops: general protection fault, probably for non-canonical address 0xdffffc000000069f: 0000 [#1] SMP KASAN PTI
KASAN: probably user-memory-access in range [0x00000000000034f8-0x00000000000034ff]
CPU: 0 UID: 0 PID: 7823 Comm: kworker/u8:9 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/09/2026
Workqueue: events_unbound cfg80211_wiphy_work
RIP: 0010:__ieee80211_get_radio_mask+0xa1/0x420 net/mac80211/util.c:4225
Code: 04 00 00 00 00 eb 1e e8 ed 06 9f f6 49 89 de 49 83 fc 0e 0f 84 71 03 00 00 e8 db 06 9f f6 48 83 c5 08 49 ff c4 48 8b 44 24 30 <42> 0f b6 04 38 84 c0 0f 85 f6 02 00 00 48 8b 44 24 08 44 0f b7 28
RSP: 0018:ffffc90003636fb8 EFLAGS: 00010202
RAX: 000000000000069f RBX: 0000000000000ec0 RCX: ffff8880276f8000
RDX: 0000000000000330 RSI: 0000000000000000 RDI: 0000000000000ec0
RBP: 0000000000003480 R08: ffff888079520ad7 R09: 1ffff1100f2a415a
R10: dffffc0000000000 R11: ffffffff8b26ee80 R12: 0000000000000000
R13: ffff888079520020 R14: 0000000000000ed0 R15: dffffc0000000000
FS: 0000000000000000(0000) GS:ffff88812527c000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00002000001d4000 CR3: 0000000052412000 CR4: 00000000003526f0
Call Trace:
<TASK>
rdev_get_radio_mask net/wireless/rdev-ops.h:1605 [inline]
cfg80211_calculate_bi_data net/wireless/util.c:2431 [inline]
cfg80211_iter_combinations+0x260/0x1c90 net/wireless/util.c:2504
ieee80211_max_num_channels+0x186/0x250 net/mac80211/util.c:4389
ieee80211_can_create_new_chanctx+0x1df/0x270 net/mac80211/chan.c:256
ieee80211_find_available_radio net/mac80211/chan.c:1529 [inline]
ieee80211_find_or_create_chanctx+0x4e2/0x7b0 net/mac80211/chan.c:2208
_ieee80211_link_use_channel+0x4fd/0xcb0 net/mac80211/chan.c:2319
ieee80211_link_use_channel net/mac80211/ieee80211_i.h:2823 [inline]
__ieee80211_sta_join_ibss+0x6a4/0x1660 net/mac80211/ibss.c:292
ieee80211_sta_create_ibss+0x300/0x480 net/mac80211/ibss.c:1286
ieee80211_sta_find_ibss net/mac80211/ibss.c:1415 [inline]
ieee80211_ibss_work+0xd99/0x1060 net/mac80211/ibss.c:1636
cfg80211_wiphy_work+0x29e/0x420 net/wireless/core.c:538
process_one_work kernel/workqueue.c:3314 [inline]
process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3397
worker_thread+0xa47/0xfb0 kernel/workqueue.c:3478
kthread+0x388/0x470 kernel/kthread.c:436
ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:__ieee80211_get_radio_mask+0xa1/0x420 net/mac80211/util.c:4225
Code: 04 00 00 00 00 eb 1e e8 ed 06 9f f6 49 89 de 49 83 fc 0e 0f 84 71 03 00 00 e8 db 06 9f f6 48 83 c5 08 49 ff c4 48 8b 44 24 30 <42> 0f b6 04 38 84 c0 0f 85 f6 02 00 00 48 8b 44 24 08 44 0f b7 28
RSP: 0018:ffffc90003636fb8 EFLAGS: 00010202
RAX: 000000000000069f RBX: 0000000000000ec0 RCX: ffff8880276f8000
RDX: 0000000000000330 RSI: 0000000000000000 RDI: 0000000000000ec0
RBP: 0000000000003480 R08: ffff888079520ad7 R09: 1ffff1100f2a415a
R10: dffffc0000000000 R11: ffffffff8b26ee80 R12: 0000000000000000
R13: ffff888079520020 R14: 0000000000000ed0 R15: dffffc0000000000
FS: 0000000000000000(0000) GS:ffff88812527c000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00002000004f9000 CR3: 0000000084fec000 CR4: 00000000003526f0
----------------
Code disassembly (best guess), 1 bytes skipped:
0: 00 00 add %al,(%rax)
2: 00 00 add %al,(%rax)
4: eb 1e jmp 0x24
6: e8 ed 06 9f f6 call 0xf69f06f8
b: 49 89 de mov %rbx,%r14
e: 49 83 fc 0e cmp $0xe,%r12
12: 0f 84 71 03 00 00 je 0x389
18: e8 db 06 9f f6 call 0xf69f06f8
1d: 48 83 c5 08 add $0x8,%rbp
21: 49 ff c4 inc %r12
24: 48 8b 44 24 30 mov 0x30(%rsp),%rax
* 29: 42 0f b6 04 38 movzbl (%rax,%r15,1),%eax <-- trapping instruction
2e: 84 c0 test %al,%al
30: 0f 85 f6 02 00 00 jne 0x32c
36: 48 8b 44 24 08 mov 0x8(%rsp),%rax
3b: 44 0f b7 28 movzwl (%rax),%r13d
Reply: **Bug Analysis:**
The crash is a NULL pointer dereference occurring in `__ieee80211_get_radio_mask` within the `mac80211` subsystem.
The sequence of events leading to the crash is as follows:
1. When a new channel context is being created (e.g., when joining an IBSS network), `mac80211` checks if it can create a new context by calling `ieee80211_max_num_channels(local, radio_idx)`.
2. This invokes `cfg80211_iter_combinations()` with a specific `radio_idx >= 0`.
3. `cfg80211_iter_combinations()` calls `cfg80211_calculate_bi_data()`, which iterates over all wireless devices (`wdev`) on the wiphy to calculate beacon interval data.
4. For each `wdev`, it checks if the device is active on the given radio by calling `rdev_get_radio_mask(rdev, wdev->netdev)`.
5. However, certain interface types (such as `NL80211_IFTYPE_P2P_DEVICE` or `NL80211_IFTYPE_NAN`) do not have an associated `netdev`, meaning `wdev->netdev` is `NULL`.
6. `mac80211`'s implementation of the `get_radio_mask` callback (`ieee80211_get_radio_mask`) does not check if the `dev` pointer is `NULL`. It directly calls `IEEE80211_DEV_TO_SUB_IF(dev)`, which uses `netdev_priv(dev)`.
7. `netdev_priv(NULL)` returns a small offset (e.g., `0xec0`), and the subsequent attempt to access `sdata->vif.active_links` in `__ieee80211_get_radio_mask` results in a general protection fault or NULL pointer dereference.
**Security Impact:**
* **Exploitable:** No. The bug is a read access to a small offset relative to a NULL pointer (e.g., `0x34fa`). The memory access will reliably page fault and crash the kernel. It cannot be used for memory corruption, privilege escalation, or information leaks.
* **Denial of Service:** Yes. Triggering the bug results in a kernel oops/panic, leading to a local denial of service.
* **Accessible From Unprivileged Processes / User Namespaces:** No. To trigger this bug, a user must first create a wireless interface without a `netdev` (like a P2P Device) and then initiate a connection that creates a new channel context (like joining an IBSS). Both of these `nl80211` commands require `CAP_NET_ADMIN` in the network namespace of the wireless device. Since wireless devices typically reside in the initial network namespace and cannot be moved by unprivileged users, this is completely inaccessible to unprivileged processes or from within unprivileged user namespaces.
* **Remote / Peripheral / VM Triggers:** No. The bug is triggered strictly via local administrative configuration commands (netlink) and is not reachable via remote network packets, malicious USB devices, or VM guest interactions.
|
| 6/2 |
2026/06/27 02:04 |
llm |
expert |
0m
Model:
Tokens:
input: 8582
output: 31
thoughts: 213
Thoughts: **Analyzing a Kernel Panic in mac80211**
Okay, here's what I'm seeing: a general protection fault. The kernel's complaining in `__ieee80211_get_radio_mask` at `net/mac80211/util.c:4225`. The actual instruction causing the problem is `movzbl (%rax,%r15,1),%eax`. That immediately flags a memory access issue. Looking closer, `%r15` holds this massive KASAN shadow offset, `dffffc0000000000`, so that's a red herring at the moment. But, `%rax` is `000000000000069f`. Wait a minute, if that's the base address, then the original, un-shadowed address would have been `0x00000000000034f8`. That's a *classic* NULL pointer dereference, with an offset of 0x34f8! Now, that's interesting. I know where that line of code is located, and I should start there. Time to dive into `net/mac80211/util.c:4225` and figure out what pointer is being mishandled.
|
| 7/2 |
2026/06/27 02:04 |
tool |
codesearch-file-index |
0m
Args: map[SourceFile:net/mac80211/util.c]
Results: map[Entities:[map[Kind:function Name:__ieee80211_flush_queues] map[Kind:function Name:__ieee80211_get_radio_mask] map[Kind:function Name:__ieee80211_iterate_interfaces] map[Kind:function Name:__ieee80211_iterate_stations] map[Kind:function Name:__ieee80211_stop_queue] map[Kind:function Name:__ieee80211_wake_queue] map[Kind:function Name:__ieee80211_wake_txqs] map[Kind:function Name:__iterate_interfaces] map[Kind:function Name:__iterate_stations] map[Kind:function Name:_ieee80211_wake_txqs] map[Kind:function Name:ieee80211_add_aid_request_ie] map[Kind:function Name:ieee80211_add_pending_skb] map[Kind:function Name:ieee80211_add_pending_skbs] map[Kind:function Name:ieee80211_add_s1g_capab_ie] map[Kind:function Name:ieee80211_add_wmm_info_ie] map[Kind:function Name:ieee80211_assign_chanctx] map[Kind:function Name:ieee80211_ave_rssi] map[Kind:function Name:ieee80211_build_preq_ies] map[Kind:function Name:ieee80211_build_probe_req] map[Kind:function Name:ieee80211_calculate_rx_timestamp] map[Kind:function Name:ieee80211_can_queue_work] map[Kind:function Name:ieee80211_chanctx_radar_detect] map[Kind:function Name:ieee80211_chandef_downgrade] map[Kind:function Name:ieee80211_chandef_eht_oper] map[Kind:function Name:ieee80211_chandef_he_6ghz_oper] map[Kind:function Name:ieee80211_chandef_ht_oper] map[Kind:function Name:ieee80211_chandef_s1g_oper] map[Kind:function Name:ieee80211_chandef_vht_oper] map[Kind:function Name:ieee80211_check_combinations_ext] map[Kind:function Name:ieee80211_clear_tpe] map[Kind:function Name:ieee80211_conn_mode_str] map[Kind:function Name:ieee80211_ctstoself_duration] map[Kind:function Name:ieee80211_dfs_cac_cancel] map[Kind:function Name:ieee80211_dfs_radar_detected_work] map[Kind:function Name:ieee80211_encode_usf] map[Kind:function Name:ieee80211_extend_absent_time] map[Kind:function Name:ieee80211_extend_noa_desc] map[Kind:function Name:ieee80211_fill_ifcomb_params] map[Kind:function Name:ieee80211_flush_completed_scan] map[Kind:function Name:ieee80211_flush_queues] map[Kind:function Name:ieee80211_frame_duration] map[Kind:function Name:ieee80211_generic_frame_duration] map[Kind:function Name:ieee80211_get_adjusted_he_cap] map[Kind:function Name:ieee80211_get_bssid] map[Kind:function Name:ieee80211_get_noa_absent_time] map[Kind:function Name:ieee80211_get_radio_mask] map[Kind:function Name:ieee80211_get_vif_queues] map[Kind:function Name:ieee80211_handle_reconfig_failure] map[Kind:function Name:ieee80211_handle_wake_tx_queue] map[Kind:function Name:ieee80211_hw_restart_disconnect] map[Kind:function Name:ieee80211_ie_build_eht_oper] map[Kind:function Name:ieee80211_ie_build_he_oper] map[Kind:function Name:ieee80211_ie_build_ht_cap] map[Kind:function Name:ieee80211_ie_build_ht_oper] map[Kind:function Name:ieee80211_ie_build_vht_cap] map[Kind:function Name:ieee80211_ie_build_vht_oper] map[Kind:function Name:ieee80211_ie_build_wide_bw_cs] map[Kind:function Name:ieee80211_ie_len_eht_cap] map[Kind:function Name:ieee80211_ie_len_he_cap] map[Kind:function Name:ieee80211_ie_split_vendor] map[Kind:function Name:ieee80211_is_radio_idx_in_scan_req] map[Kind:function Name:ieee80211_iter_max_chans] map[Kind:function Name:ieee80211_iterate_active_interfaces_atomic] map[Kind:function Name:ieee80211_iterate_interfaces] map[Kind:function Name:ieee80211_iterate_stations_atomic] map[Kind:function Name:ieee80211_max_num_channels] map[Kind:function Name:ieee80211_mcs_to_chains] map[Kind:function Name:ieee80211_min_bw_limit_from_chandef] map[Kind:function Name:ieee80211_parse_p2p_noa] map[Kind:function Name:ieee80211_put_eht_cap] map[Kind:function Name:ieee80211_put_he_6ghz_cap] map[Kind:function Name:ieee80211_put_he_cap] map[Kind:function Name:ieee80211_put_preq_ies] map[Kind:function Name:ieee80211_put_preq_ies_band] map[Kind:function Name:ieee80211_put_reg_conn] map[Kind:function Name:ieee80211_put_s1g_cap] map[Kind:function Name:ieee80211_put_srates_elem] map[Kind:function Name:ieee80211_put_uhr_cap] map[Kind:function Name:ieee80211_queue_delayed_work] map[Kind:function Name:ieee80211_queue_stopped] map[Kind:function Name:ieee80211_queue_work] map[Kind:function Name:ieee80211_radar_detected] map[Kind:function Name:ieee80211_radar_mark_chan_ctx_iterator] map[Kind:function Name:ieee80211_recalc_dtim] map[Kind:function Name:ieee80211_recalc_min_chandef] map[Kind:function Name:ieee80211_recalc_sb_count] map[Kind:function Name:ieee80211_recalc_smps] map[Kind:function Name:ieee80211_reconfig] map[Kind:function Name:ieee80211_reconfig_ap_links] map[Kind:function Name:ieee80211_reconfig_disconnect] map[Kind:function Name:ieee80211_reconfig_nan] map[Kind:function Name:ieee80211_reconfig_nan_offload_de] map[Kind:function Name:ieee80211_reconfig_stations] map[Kind:function Name:ieee80211_regulatory_limit_wmm_params] map[Kind:function Name:ieee80211_resume_disconnect] map[Kind:function Name:ieee80211_rts_duration] map[Kind:function Name:ieee80211_sdata_uses_radio] map[Kind:function Name:ieee80211_send_action_csa] map[Kind:function Name:ieee80211_send_auth] map[Kind:function Name:ieee80211_send_deauth_disassoc] map[Kind:function Name:ieee80211_set_wmm_default] map[Kind:function Name:ieee80211_sta_get_rates] map[Kind:function Name:ieee80211_sta_rx_bw_to_chan_width] map[Kind:function Name:ieee80211_stop_device] map[Kind:function Name:ieee80211_stop_queue] map[Kind:function Name:ieee80211_stop_queue_by_reason] map[Kind:function Name:ieee80211_stop_queues] map[Kind:function Name:ieee80211_stop_queues_by_reason] map[Kind:function Name:ieee80211_tx_set_protected] map[Kind:function Name:ieee80211_txq_get_depth] map[Kind:function Name:ieee80211_update_p2p_noa] map[Kind:function Name:ieee80211_vif_nan_started] map[Kind:function Name:ieee80211_vif_to_wdev] map[Kind:function Name:ieee80211_wake_queue] map[Kind:function Name:ieee80211_wake_queue_by_reason] map[Kind:function Name:ieee80211_wake_queues] map[Kind:function Name:ieee80211_wake_queues_by_reason] map[Kind:function Name:ieee80211_wake_txqs] map[Kind:function Name:wake_tx_push_queue] map[Kind:function Name:wdev_to_ieee80211_vif] map[Kind:function Name:wiphy_to_ieee80211_hw] map[Kind:global_variable Name:__UNIQUE_ID_addressable___ieee80211_iterate_interfaces_2736] map[Kind:global_variable Name:__UNIQUE_ID_addressable___ieee80211_iterate_stations_2742] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_ave_rssi_2874] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_calculate_rx_timestamp_2880] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_ctstoself_duration_2701] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_generic_frame_duration_2699] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_handle_wake_tx_queue_2702] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_hw_restart_disconnect_2837] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_iterate_active_interfaces_atomic_2731] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_iterate_interfaces_2730] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_iterate_stations_atomic_2739] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_parse_p2p_noa_2896] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_queue_delayed_work_2746] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_queue_stopped_2724] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_queue_work_2745] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_radar_detected_2885] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_resume_disconnect_2838] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_rts_duration_2700] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_stop_queue_2716] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_stop_queues_2721] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_txq_get_depth_2925] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_update_p2p_noa_2895] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_vif_nan_started_2951] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_vif_to_wdev_2744] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_wake_queue_2713] map[Kind:global_variable Name:__UNIQUE_ID_addressable_ieee80211_wake_queues_2725] map[Kind:global_variable Name:__UNIQUE_ID_addressable_wdev_to_ieee80211_vif_2743] map[Kind:global_variable Name:__UNIQUE_ID_addressable_wiphy_to_ieee80211_hw_2698] map[Kind:global_variable Name:__gendwarfksyms_ptr___ieee80211_iterate_interfaces] map[Kind:global_variable Name:__gendwarfksyms_ptr___ieee80211_iterate_stations] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_ave_rssi] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_calculate_rx_timestamp] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_ctstoself_duration] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_generic_frame_duration] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_handle_wake_tx_queue] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_hw_restart_disconnect] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_iterate_active_interfaces_atomic] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_iterate_interfaces] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_iterate_stations_atomic] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_parse_p2p_noa] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_queue_delayed_work] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_queue_stopped] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_queue_work] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_radar_detected] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_resume_disconnect] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_rts_duration] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_stop_queue] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_stop_queues] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_txq_get_depth] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_update_p2p_noa] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_vif_nan_started] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_vif_to_wdev] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_wake_queue] map[Kind:global_variable Name:__gendwarfksyms_ptr_ieee80211_wake_queues] map[Kind:global_variable Name:__gendwarfksyms_ptr_wdev_to_ieee80211_vif] map[Kind:global_variable Name:__gendwarfksyms_ptr_wiphy_to_ieee80211_hw] map[Kind:global_variable Name:ieee80211_ac_to_qos_mask] map[Kind:global_variable Name:ieee80211_conn_settings_unlimited] map[Kind:global_variable Name:mac80211_wiphy_privid]]]
|
| 8/2 |
2026/06/27 02:04 |
llm |
expert |
0m
Model:
Tokens:
input: 14263
output: 50
thoughts: 36
Thoughts: Okay, let's dive into this. Here's how I'd approach this task, as if I were thinking it through:
**Analyzing `__ieee80211_get_radio_mask` in `net/mac80211/util.c`**
Alright, time to get my hands dirty. I need to refresh my memory on the radio mask functionality within the mac80211 framework. So, my starting point is to zero in on the `__ieee80211_get_radio_mask` function, specifically within the `net/mac80211/util.c` source file. This utility function is fundamental to how mac80211 handles and exposes radio capabilities, so understanding its role is key to grasping the wider implications.
I want to see exactly how the radio mask is constructed and retrieved. What data structures are involved? What inputs does it take, and what does it return? Are there any clever bit manipulations or optimizations employed here? More importantly, how is this mask used in conjunction with other features, like rate selection, channel selection, or power management? I want to see if there are any subtle implementation details that could impact performance or compatibility.
This likely plays a role in how a particular hardware radio is described and used within the mac80211 layer. I anticipate there's a dependency on the underlying hardware description, perhaps via devicetree or some other system configuration mechanism. My goal is to extract a comprehensive understanding of the process, and I'll be sure to note any edge cases and any potential bugs.
|
| 9/2 |
2026/06/27 02:04 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/mac80211/util.c Name:__ieee80211_get_radio_mask]
Results: map[SourceCode:4217: static u32
4218: __ieee80211_get_radio_mask(struct ieee80211_sub_if_data *sdata)
4219: {
4220: struct ieee80211_bss_conf *link_conf;
4221: struct ieee80211_chanctx_conf *conf;
4222: unsigned int link_id;
4223: u32 mask = 0;
4224:
4225: for_each_vif_active_link(&sdata->vif, link_conf, link_id) {
4226: conf = sdata_dereference(link_conf->chanctx_conf, sdata);
4227: if (!conf || conf->radio_idx < 0)
4228: continue;
4229:
4230: mask |= BIT(conf->radio_idx);
4231: }
4232:
4233: return mask;
4234: }
SourceFile:net/mac80211/util.c]
|
| 10/2 |
2026/06/27 02:04 |
llm |
expert |
0m
Model:
Tokens:
input: 15013
output: 46
thoughts: 58
Thoughts: Here's my analysis of the situation:
**Debugging a Kernel Crash in `for_each_vif_active_link`**
Okay, so the kernel's crapping out at line 4225, and that's the `for_each_vif_active_link` function call. Time to dive in. Let's see what that function does. It's iterating over something related to virtual interfaces, probably active links, based on the name. I need to understand what `sdata->vif`, `link_conf`, and `link_id` represent within that context. From the context, this *has* to be some kind of network interface code. This function's probably walking a linked list or some data structure associated with each virtual network interface. Gotta figure out if there's a race condition or a bad pointer dereference happening inside that loop, or maybe the loop itself is just structured incorrectly. Time to pull up the definition and associated usage of that function to understand how the arguments are being used to narrow this down further.
|
| 11/2 |
2026/06/27 02:04 |
tool |
codesearch-definition-source |
0m
Error:
Args: map[ContextFile:net/mac80211/util.c Name:for_each_vif_active_link]
Results: map[SourceCode: SourceFile:]
|
| 12/2 |
2026/06/27 02:04 |
llm |
expert |
0m
Model:
Tokens:
input: 15363
output: 26
thoughts: 14
Thoughts: Okay, here's my interpretation of that thought process, assuming I'm deep in my code and thinking like an expert:
**Identifying and Hunting Down a Suspect**
Alright, that's probably a macro doing that. Let's not waste time going down any other rabbit holes right now. My first instinct, and the quickest way to confirm this suspicion, is to use `grep`. I'll quickly scan the relevant files and see if this particular behavior is being defined, or even just used, anywhere by a macro call. I'm thinking a targeted `grep` on the codebase will either confirm my suspicions and help me zero in on the exact location of this macro or quickly eliminate that possibility, saving me valuable time. Let's see what `grep` turns up!
|
| 13/2 |
2026/06/27 02:04 |
tool |
grepper |
0m
Args: map[Expression:#define for_each_vif_active_link]
Results: map[Output:include/net/mac80211.h=2281=static inline bool ieee80211_vif_link_active(const struct ieee80211_vif *vif,
--
include/net/mac80211.h-2288-
include/net/mac80211.h:2289:#define for_each_vif_active_link(vif, link, link_id) \
include/net/mac80211.h-2290- for (link_id = 0; link_id < ARRAY_SIZE((vif)->link_conf); link_id++) \
]
|
| 14/2 |
2026/06/27 02:05 |
llm |
expert |
0m
Model:
Tokens:
input: 15744
output: 41
thoughts: 20
Thoughts: Okay, here's my attempt at summarizing the thought process, as if I were considering the provided text, assuming I'm an expert:
**Delving into `for_each_vif_active_link`**
Alright, let's get right into it. I'm going to pull up the full definition of `for_each_vif_active_link` – let's see what we're actually dealing with here. Is it a macro? A function? What are its parameters? Understanding the precise structure is going to be key to interpreting the context and, more importantly, *why* we're using it. I need to pinpoint where this piece of code fits into the larger picture. I'm looking to understand its purpose within the virtual network interface (VIF) context. What specific active link operation or process does it support or implement? What's the target structure? Are we iterating, filtering, or modifying something? I'll probably start by looking at the header files to determine the function's prototype and possible usages. Then, let's explore the implementation and follow the logic flow. Only then can I determine its impact on the system's overall performance.
|
| 15/2 |
2026/06/27 02:05 |
tool |
read-file |
0m
Args: map[File:include/net/mac80211.h FirstLine:2288 LineCount:10]
Results: map[Contents:2288:
2289: #define for_each_vif_active_link(vif, link, link_id) \
2290: for (link_id = 0; link_id < ARRAY_SIZE((vif)->link_conf); link_id++) \
2291: if ((!(vif)->active_links || \
2292: (vif)->active_links & BIT(link_id)) && \
2293: (link = link_conf_dereference_check(vif, link_id)))
2294:
2295: static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
2296: {
2297: #ifdef CONFIG_MAC80211_MESH
]
|
| 16/2 |
2026/06/27 02:05 |
llm |
expert |
0m
Model:
Tokens:
input: 16289
output: 42
thoughts: 125
Thoughts: **Debugging a Suspected Radio Mask Issue**
Okay, so I'm hitting a crash, and it looks like it's happening right in the `for_each_vif_active_link` loop, specifically at that `movzbl` instruction. The address is 0x34f8, but the real key seems to be `sdata`, which is being passed to `__ieee80211_get_radio_mask`. This definitely smells like a potential radio mask issue; those are always tricky. Time to dive into `rdev_get_radio_mask`. I'll check `net/wireless/rdev-ops.h:1605` to see what's happening. I need to figure out how `sdata` is getting corrupted or being misinterpreted in that context. Let's see if the radio mask itself is the source of the problem.
|
| 17/2 |
2026/06/27 02:05 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/wireless/rdev-ops.h Name:rdev_get_radio_mask]
Results: map[SourceCode:1596: static inline u32
1597: rdev_get_radio_mask(struct cfg80211_registered_device *rdev,
1598: struct net_device *dev)
1599: {
1600: struct wiphy *wiphy = &rdev->wiphy;
1601:
1602: if (!rdev->ops->get_radio_mask)
1603: return 0;
1604:
1605: return rdev->ops->get_radio_mask(wiphy, dev);
1606: }
SourceFile:net/wireless/rdev-ops.h]
|
| 18/2 |
2026/06/27 02:05 |
llm |
expert |
0m
Model:
Tokens:
input: 16845
output: 43
thoughts: 38
Thoughts: Okay, here's my interpretation of that thought process, from an expert's perspective:
**Diving into the 802.11 Data Calculation**
Right, so I'm looking at this snippet of code. We've got `dev` being passed here. That's immediately interesting – I know that `dev` usually refers to a network device, likely the wireless interface in this context. It's a key piece of information for any 802.11 analysis.
Now, it seems we're deep within `cfg80211_calculate_bi_data`, specifically at line 2431 within `net/wireless/util.c`. That function name alone suggests we're dealing with calculations related to the Basic Information (BI) elements used in 802.11 frames. This is where the nitty-gritty of wireless configuration and negotiation happens – understanding how the Access Point and Station communicate their capabilities and chosen parameters. Line 2431 is likely a crucial step within that calculation. It's time to dig in and figure out *what* data is being calculated, and *how* the `dev` is being used to inform it. Is this a computation of supported rates, channel parameters, or other essential BI data? Knowing where `dev` comes into play here is key.
|
| 19/2 |
2026/06/27 02:05 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/wireless/util.c Name:cfg80211_calculate_bi_data]
Results: map[SourceCode:2410: static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
2411: u32 *beacon_int_gcd,
2412: bool *beacon_int_different,
2413: int radio_idx)
2414: {
2415: struct cfg80211_registered_device *rdev;
2416: struct wireless_dev *wdev;
2417:
2418: *beacon_int_gcd = 0;
2419: *beacon_int_different = false;
2420:
2421: rdev = wiphy_to_rdev(wiphy);
2422: list_for_each_entry(wdev, &wiphy->wdev_list, list) {
2423: int wdev_bi;
2424:
2425: /* this feature isn't supported with MLO */
2426: if (wdev->valid_links)
2427: continue;
2428:
2429: /* skip wdevs not active on the given wiphy radio */
2430: if (radio_idx >= 0 &&
2431: !(rdev_get_radio_mask(rdev, wdev->netdev) & BIT(radio_idx)))
2432: continue;
2433:
2434: wdev_bi = cfg80211_wdev_bi(wdev);
2435:
2436: if (!wdev_bi)
2437: continue;
2438:
2439: if (!*beacon_int_gcd) {
2440: *beacon_int_gcd = wdev_bi;
2441: continue;
2442: }
2443:
2444: if (wdev_bi == *beacon_int_gcd)
2445: continue;
2446:
2447: *beacon_int_different = true;
2448: *beacon_int_gcd = gcd(*beacon_int_gcd, wdev_bi);
2449: }
2450:
2451: if (new_beacon_int && *beacon_int_gcd != new_beacon_int) {
2452: if (*beacon_int_gcd)
2453: *beacon_int_different = true;
2454: *beacon_int_gcd = gcd(*beacon_int_gcd, new_beacon_int);
2455: }
2456: }
SourceFile:net/wireless/util.c]
|
| 20/2 |
2026/06/27 02:05 |
llm |
expert |
0m
Model:
Tokens:
input: 17951
output: 23
thoughts: 102
Thoughts: **Analyzing the Radio Mask Retrieval Process**
Okay, so I'm tracing through this code, and it looks like `wdev->netdev` gets passed into `rdev_get_radio_mask`. The interesting part is what happens if `wdev->netdev` is null. In that scenario, `rdev_get_radio_mask` calls `rdev->ops->get_radio_mask` with `wiphy` and `NULL`. Now I need to figure out what's actually being called. Is `get_radio_mask` the `mac80211_get_radio_mask` function? Time to confirm that detail.
|
| 21/2 |
2026/06/27 02:05 |
tool |
grepper |
0m
Args: map[Expression:\.get_radio_mask\s*=]
Results: map[Output:net/mac80211/cfg.c=5987=const struct cfg80211_ops mac80211_config_ops = {
--
net/mac80211/cfg.c-6099- .set_ttlm = ieee80211_set_ttlm,
net/mac80211/cfg.c:6100: .get_radio_mask = ieee80211_get_radio_mask,
net/mac80211/cfg.c-6101- .assoc_ml_reconf = ieee80211_assoc_ml_reconf,
]
|
| 22/2 |
2026/06/27 02:05 |
llm |
expert |
0m
Model:
Tokens:
input: 18396
output: 49
thoughts: 34
Thoughts: Here's my take on those thoughts:
**Analyzing `ieee80211_get_radio_mask` in `net/mac80211/cfg.c`**
Okay, so I'm diving into `net/mac80211/cfg.c` to understand how the radio mask is handled. Specifically, I'm thinking about how the `ieee80211_get_radio_mask` function functions. This is a critical function; understanding the radio mask is fundamental to how mac80211 configures and manages its wireless interfaces. I need to refresh my understanding of how this particular function is responsible for determining which radios are enabled or disabled and how that affects the available channels and modes. I'm going to look into what context it is called in and ensure my understanding of the implications of any returned values. Hopefully, I can walk away with a crystal clear picture of the inner workings.
|
| 23/2 |
2026/06/27 02:05 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/mac80211/cfg.c Name:ieee80211_get_radio_mask]
Results: map[SourceCode:4236: u32 ieee80211_get_radio_mask(struct wiphy *wiphy, struct net_device *dev)
4237: {
4238: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
4239:
4240: return __ieee80211_get_radio_mask(sdata);
4241: }
SourceFile:net/mac80211/util.c]
|
| 24/2 |
2026/06/27 02:05 |
llm |
expert |
0m
Model:
Tokens:
input: 18846
output: 30
thoughts: 66
Thoughts: Okay, let me think this through.
**Analyzing Potential Null Pointer Dereference in mac80211 Code**
Alright, I'm looking at this `ieee80211_get_radio_mask` function, and it's defined within `net/mac80211/util.c`. My immediate concern, as always, is robustness. I see this function uses the macro `IEEE80211_DEV_TO_SUB_IF(dev)`. The critical question that immediately pops into my head is: what happens if the `dev` pointer passed to this macro is NULL? We all know that's the number one cause of crashes in driver code. We're dealing with network devices here; a crash here is bad news.
I need to trace the implications. Does the macro itself contain any NULL checks, or does it implicitly rely on the caller to validate? Given my experience, I'd bet the latter is true, making the call to `ieee80211_get_radio_mask` itself the potential point of failure. I need to know where this function is called and with what arguments to understand the risk profile. The analysis starts here!
|
| 25/2 |
2026/06/27 02:05 |
tool |
grepper |
0m
Error:
Args: map[Expression:#define IEEE80211_DEV_TO_SUB_IF]
Results:
|
| 26/2 |
2026/06/27 02:05 |
llm |
expert |
0m
Model:
Tokens:
input: 19213
output: 28
thoughts: 20
Thoughts: Here's my thought process, as if I were considering this search:
**Diving into the IEEE 802.11 Sub-Interface Lookup**
Okay, so I need to find the definition or usage of `IEEE80211_DEV_TO_SUB_IF`. This likely relates to a core function within the 802.11 wireless networking stack, probably in a Linux or BSD-like environment, given the naming convention. My immediate thought is, "Where would I *expect* to find this?" Given my experience, the first place I'd check would be the kernel source code itself, specifically the wireless or networking directories.
I’m guessing this is likely a macro or function. If it's a macro, it's probably doing something like converting a device structure (perhaps `struct ieee80211_hw` or a related structure) to a sub-interface representation. This makes me consider data structures which have this capability. If it's a function, it probably performs a similar type cast or lookup, but potentially with more complex logic involved, perhaps a search through a list or a lookup table. My mental model suggests it’s a quick lookup, probably optimized for performance, given the typical demands of wireless networking.
I’m assuming the code is probably in C, given the prevalence of C in kernel development. The naming suggests IEEE 802.11 specific, but also the _DEV_TO_ naming convention indicates a type conversion from device to sub interface, if I were to hazard a guess. I'm going to start by searching the kernel source, specifically the networking subsystem, and look for header files and related source files. Keywords like "ieee80211", "netdev", "subif", or "interface" are likely to be useful search terms. I would start by exploring the source code or using a tool like `grep` to quickly find this identifier. This will be an iterative process, refining the search terms as needed. Let's get to it!
|
| 27/2 |
2026/06/27 02:05 |
tool |
grepper |
0m
Args: map[Expression:IEEE80211_DEV_TO_SUB_IF]
Results: map[Output:
Full output is too long, showing 500 out of 561 lines.
Use more precise expression if possible.
net/mac80211/cfg.c=259=static int ieee80211_change_iface(struct wiphy *wiphy,
--
net/mac80211/cfg.c-263-{
net/mac80211/cfg.c:264: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-265- struct ieee80211_local *local = sdata->local;
--
net/mac80211/cfg.c=572=static int ieee80211_set_noack_map(struct wiphy *wiphy,
--
net/mac80211/cfg.c-575-{
net/mac80211/cfg.c:576: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-577-
--
net/mac80211/cfg.c=918=static int ieee80211_config_default_key(struct wiphy *wiphy,
--
net/mac80211/cfg.c-922-{
net/mac80211/cfg.c:923: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-924- struct ieee80211_link_data *link =
--
net/mac80211/cfg.c=1060=static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
--
net/mac80211/cfg.c-1070-
net/mac80211/cfg.c:1071: sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-1072- if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
--
net/mac80211/cfg.c=1630=static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-1632-{
net/mac80211/cfg.c:1633: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-1634- struct ieee80211_local *local = sdata->local;
--
net/mac80211/cfg.c=1936=static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-1939-{
net/mac80211/cfg.c:1940: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-1941- struct ieee80211_link_data *link;
--
net/mac80211/cfg.c=2010=static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-2012-{
net/mac80211/cfg.c:2013: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-2014- struct ieee80211_sub_if_data *vlan;
--
net/mac80211/cfg.c=2630=static int ieee80211_add_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
net/mac80211/cfg.c-2641- if (params->vlan) {
net/mac80211/cfg.c:2642: sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
net/mac80211/cfg.c-2643-
--
net/mac80211/cfg.c=2783=static int ieee80211_change_station(struct wiphy *wiphy,
--
net/mac80211/cfg.c-2841- if (params->vlan && params->vlan != sta->sdata->dev) {
net/mac80211/cfg.c:2842: vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
net/mac80211/cfg.c-2843-
--
net/mac80211/cfg.c=2891=static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-2897-
net/mac80211/cfg.c:2898: sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-2899-
--
net/mac80211/cfg.c=2919=static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-2921-{
net/mac80211/cfg.c:2922: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-2923-
--
net/mac80211/cfg.c=2931=static int ieee80211_change_mpath(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-2937-
net/mac80211/cfg.c:2938: sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-2939-
--
net/mac80211/cfg.c=3006=static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-3012-
net/mac80211/cfg.c:3013: sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-3014-
--
net/mac80211/cfg.c=3027=static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-3033-
net/mac80211/cfg.c:3034: sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-3035-
--
net/mac80211/cfg.c=3057=static int ieee80211_get_mpp(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-3063-
net/mac80211/cfg.c:3064: sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-3065-
--
net/mac80211/cfg.c=3078=static int ieee80211_dump_mpp(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-3084-
net/mac80211/cfg.c:3085: sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-3086-
--
net/mac80211/cfg.c=3099=static int ieee80211_get_mesh_config(struct wiphy *wiphy,
--
net/mac80211/cfg.c-3103- struct ieee80211_sub_if_data *sdata;
net/mac80211/cfg.c:3104: sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-3105-
--
net/mac80211/cfg.c=3172=static int ieee80211_update_mesh_config(struct wiphy *wiphy,
--
net/mac80211/cfg.c-3179-
net/mac80211/cfg.c:3180: sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-3181- ifmsh = &sdata->u.mesh;
--
net/mac80211/cfg.c=3292=static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-3295-{
net/mac80211/cfg.c:3296: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-3297- struct ieee80211_chan_req chanreq = { .oper = setup->chandef };
--
net/mac80211/cfg.c=3322=static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
net/mac80211/cfg.c-3323-{
net/mac80211/cfg.c:3324: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-3325-
--
net/mac80211/cfg.c=3336=static int ieee80211_change_bss(struct wiphy *wiphy,
--
net/mac80211/cfg.c-3339-{
net/mac80211/cfg.c:3340: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-3341- struct ieee80211_link_data *link;
--
net/mac80211/cfg.c=3423=static int ieee80211_set_txq_params(struct wiphy *wiphy,
--
net/mac80211/cfg.c-3427- struct ieee80211_local *local = wiphy_priv(wiphy);
net/mac80211/cfg.c:3428: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-3429- struct ieee80211_link_data *link =
--
net/mac80211/cfg.c=3550=ieee80211_sched_scan_start(struct wiphy *wiphy,
--
net/mac80211/cfg.c-3553-{
net/mac80211/cfg.c:3554: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-3555-
--
net/mac80211/cfg.c=3574=static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-3576-{
net/mac80211/cfg.c:3577: return ieee80211_mgd_auth(IEEE80211_DEV_TO_SUB_IF(dev), req);
net/mac80211/cfg.c-3578-}
--
net/mac80211/cfg.c=3580=static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-3582-{
net/mac80211/cfg.c:3583: return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req);
net/mac80211/cfg.c-3584-}
--
net/mac80211/cfg.c=3586=static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-3588-{
net/mac80211/cfg.c:3589: return ieee80211_mgd_deauth(IEEE80211_DEV_TO_SUB_IF(dev), req);
net/mac80211/cfg.c-3590-}
--
net/mac80211/cfg.c=3592=static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-3594-{
net/mac80211/cfg.c:3595: return ieee80211_mgd_disassoc(IEEE80211_DEV_TO_SUB_IF(dev), req);
net/mac80211/cfg.c-3596-}
--
net/mac80211/cfg.c=3598=static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-3600-{
net/mac80211/cfg.c:3601: return ieee80211_ibss_join(IEEE80211_DEV_TO_SUB_IF(dev), params);
net/mac80211/cfg.c-3602-}
--
net/mac80211/cfg.c=3604=static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
net/mac80211/cfg.c-3605-{
net/mac80211/cfg.c:3606: return ieee80211_ibss_leave(IEEE80211_DEV_TO_SUB_IF(dev));
net/mac80211/cfg.c-3607-}
--
net/mac80211/cfg.c=3609=static int ieee80211_join_ocb(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-3611-{
net/mac80211/cfg.c:3612: return ieee80211_ocb_join(IEEE80211_DEV_TO_SUB_IF(dev), setup);
net/mac80211/cfg.c-3613-}
--
net/mac80211/cfg.c=3615=static int ieee80211_leave_ocb(struct wiphy *wiphy, struct net_device *dev)
net/mac80211/cfg.c-3616-{
net/mac80211/cfg.c:3617: return ieee80211_ocb_leave(IEEE80211_DEV_TO_SUB_IF(dev));
net/mac80211/cfg.c-3618-}
--
net/mac80211/cfg.c=3620=static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-3622-{
net/mac80211/cfg.c:3623: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-3624-
--
net/mac80211/cfg.c=3979=static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-3981-{
net/mac80211/cfg.c:3982: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-3983- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
net/mac80211/cfg.c=4052=static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy,
--
net/mac80211/cfg.c-4055-{
net/mac80211/cfg.c:4056: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-4057- struct ieee80211_vif *vif = &sdata->vif;
--
net/mac80211/cfg.c=4076=static int ieee80211_set_cqm_rssi_range_config(struct wiphy *wiphy,
--
net/mac80211/cfg.c-4079-{
net/mac80211/cfg.c:4080: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-4081- struct ieee80211_vif *vif = &sdata->vif;
--
net/mac80211/cfg.c=4099=static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
--
net/mac80211/cfg.c-4104-{
net/mac80211/cfg.c:4105: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-4106- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
net/mac80211/cfg.c=4206=static int ieee80211_start_radar_detection(struct wiphy *wiphy,
--
net/mac80211/cfg.c-4210-{
net/mac80211/cfg.c:4211: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-4212- struct ieee80211_chan_req chanreq = { .oper = *chandef };
--
net/mac80211/cfg.c=4241=static void ieee80211_end_cac(struct wiphy *wiphy,
--
net/mac80211/cfg.c-4243-{
net/mac80211/cfg.c:4244: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-4245- struct ieee80211_local *local = sdata->local;
--
net/mac80211/cfg.c=4700=__ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-4702-{
net/mac80211/cfg.c:4703: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-4704- struct ieee80211_chan_req chanreq = {
--
net/mac80211/cfg.c=4819=int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-4821-{
net/mac80211/cfg.c:4822: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-4823- struct ieee80211_local *local = sdata->local;
--
net/mac80211/cfg.c=4937=static int ieee80211_set_rekey_data(struct wiphy *wiphy,
--
net/mac80211/cfg.c-4941- struct ieee80211_local *local = wiphy_priv(wiphy);
net/mac80211/cfg.c:4942: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-4943-
--
net/mac80211/cfg.c=4952=static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-4954-{
net/mac80211/cfg.c:4955: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-4956- struct ieee80211_local *local = sdata->local;
--
net/mac80211/cfg.c=5117=static int ieee80211_set_qos_map(struct wiphy *wiphy,
--
net/mac80211/cfg.c-5120-{
net/mac80211/cfg.c:5121: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5122- struct mac80211_qos_map *new_qos_map, *old_qos_map;
--
net/mac80211/cfg.c=5142=static int ieee80211_set_ap_chanwidth(struct wiphy *wiphy,
--
net/mac80211/cfg.c-5146-{
net/mac80211/cfg.c:5147: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5148- struct ieee80211_link_data *link;
--
net/mac80211/cfg.c=5165=static int ieee80211_add_tx_ts(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-5168-{
net/mac80211/cfg.c:5169: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5170- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
--
net/mac80211/cfg.c=5191=static int ieee80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-5193-{
net/mac80211/cfg.c:5194: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5195- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
--
net/mac80211/cfg.c=5319=static int ieee80211_set_multicast_to_unicast(struct wiphy *wiphy,
--
net/mac80211/cfg.c-5322-{
net/mac80211/cfg.c:5323: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5324-
--
net/mac80211/cfg.c=5419=ieee80211_get_ftm_responder_stats(struct wiphy *wiphy,
--
net/mac80211/cfg.c-5423- struct ieee80211_local *local = wiphy_priv(wiphy);
net/mac80211/cfg.c:5424: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5425-
--
net/mac80211/cfg.c=5449=static int ieee80211_set_tid_config(struct wiphy *wiphy,
--
net/mac80211/cfg.c-5452-{
net/mac80211/cfg.c:5453: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5454- struct sta_info *sta;
--
net/mac80211/cfg.c=5471=static int ieee80211_reset_tid_config(struct wiphy *wiphy,
--
net/mac80211/cfg.c-5474-{
net/mac80211/cfg.c:5475: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5476- struct sta_info *sta;
--
net/mac80211/cfg.c=5730=ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-5732-{
net/mac80211/cfg.c:5733: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5734- struct ieee80211_local *local = sdata->local;
--
net/mac80211/cfg.c=5830=ieee80211_add_link_station(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-5832-{
net/mac80211/cfg.c:5833: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5834- struct ieee80211_local *local = wiphy_priv(wiphy);
--
net/mac80211/cfg.c=5872=ieee80211_mod_link_station(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-5874-{
net/mac80211/cfg.c:5875: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5876- struct ieee80211_local *local = wiphy_priv(wiphy);
--
net/mac80211/cfg.c=5893=ieee80211_del_link_station(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-5895-{
net/mac80211/cfg.c:5896: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5897- struct sta_info *sta;
--
net/mac80211/cfg.c=5917=static int ieee80211_set_hw_timestamp(struct wiphy *wiphy,
--
net/mac80211/cfg.c-5920-{
net/mac80211/cfg.c:5921: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5922- struct ieee80211_local *local = sdata->local;
--
net/mac80211/cfg.c=5934=ieee80211_set_ttlm(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-5936-{
net/mac80211/cfg.c:5937: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5938-
--
net/mac80211/cfg.c=5945=ieee80211_assoc_ml_reconf(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-5947-{
net/mac80211/cfg.c:5948: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5949-
--
net/mac80211/cfg.c=5956=ieee80211_set_epcs(struct wiphy *wiphy, struct net_device *dev, bool enable)
net/mac80211/cfg.c-5957-{
net/mac80211/cfg.c:5958: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/cfg.c-5959-
--
net/mac80211/ethtool.c=57=static int ieee80211_get_sset_count(struct net_device *dev, int sset)
net/mac80211/ethtool.c-58-{
net/mac80211/ethtool.c:59: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/ethtool.c-60- int rv = 0;
--
net/mac80211/ethtool.c=72=static void ieee80211_get_stats(struct net_device *dev,
--
net/mac80211/ethtool.c-75-{
net/mac80211/ethtool.c:76: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/ethtool.c-77- struct ieee80211_chanctx_conf *chanctx_conf;
--
net/mac80211/ethtool.c=217=static void ieee80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
net/mac80211/ethtool.c-218-{
net/mac80211/ethtool.c:219: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/ethtool.c-220- int sz_sta_stats = 0;
--
net/mac80211/ieee80211_i.h=1726=static inline struct ieee80211_sub_if_data *
net/mac80211/ieee80211_i.h:1727:IEEE80211_DEV_TO_SUB_IF(const struct net_device *dev)
net/mac80211/ieee80211_i.h-1728-{
--
net/mac80211/iface.c=311=static int ieee80211_change_mac(struct net_device *dev, void *addr)
net/mac80211/iface.c-312-{
net/mac80211/iface.c:313: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/iface.c-314- struct ieee80211_local *local = sdata->local;
--
net/mac80211/iface.c=461=static int ieee80211_open(struct net_device *dev)
net/mac80211/iface.c-462-{
net/mac80211/iface.c:463: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/iface.c-464- int err;
--
net/mac80211/iface.c=839=static int ieee80211_stop(struct net_device *dev)
net/mac80211/iface.c-840-{
net/mac80211/iface.c:841: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/iface.c-842-
--
net/mac80211/iface.c=867=static void ieee80211_set_multicast_list(struct net_device *dev)
net/mac80211/iface.c-868-{
net/mac80211/iface.c:869: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/iface.c-870- struct ieee80211_local *local = sdata->local;
--
net/mac80211/iface.c=921=static void ieee80211_uninit(struct net_device *dev)
net/mac80211/iface.c-922-{
net/mac80211/iface.c:923: ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev));
net/mac80211/iface.c-924-}
--
net/mac80211/iface.c=926=static int ieee80211_netdev_setup_tc(struct net_device *dev,
--
net/mac80211/iface.c-928-{
net/mac80211/iface.c:929: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/iface.c-930- struct ieee80211_local *local = sdata->local;
--
net/mac80211/iface.c=945=static u16 ieee80211_monitor_select_queue(struct net_device *dev,
--
net/mac80211/iface.c-948-{
net/mac80211/iface.c:949: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/iface.c-950- struct ieee80211_local *local = sdata->local;
--
net/mac80211/iface.c=983=static int ieee80211_netdev_fill_forward_path(struct net_device_path_ctx *ctx,
--
net/mac80211/iface.c-990-
net/mac80211/iface.c:991: sdata = IEEE80211_DEV_TO_SUB_IF(ctx->dev);
net/mac80211/iface.c-992- local = sdata->local;
--
net/mac80211/iface.c=2222=int ieee80211_if_add(struct ieee80211_local *local, const char *name,
--
net/mac80211/iface.c-2312-
net/mac80211/iface.c:2313: /* don't use IEEE80211_DEV_TO_SUB_IF -- it checks too much */
net/mac80211/iface.c-2314- sdata = netdev_priv(ndev);
--
net/mac80211/iface.c=2493=static int netdev_notify(struct notifier_block *nb,
--
net/mac80211/iface.c-2507-
net/mac80211/iface.c:2508: sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/iface.c-2509- memcpy(sdata->name, dev->name, IFNAMSIZ);
--
net/mac80211/main.c=562=static int ieee80211_ifa_changed(struct notifier_block *nb,
--
net/mac80211/main.c-583-
net/mac80211/main.c:584: sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
net/mac80211/main.c-585- vif_cfg = &sdata->vif.cfg;
--
net/mac80211/main.c=638=static int ieee80211_ifa6_changed(struct notifier_block *nb,
--
net/mac80211/main.c-652-
net/mac80211/main.c:653: sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
net/mac80211/main.c-654-
--
net/mac80211/tdls.c=795=ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/tdls.c-799-{
net/mac80211/tdls.c:800: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/tdls.c-801- struct ieee80211_tdls_data *tf;
--
net/mac80211/tdls.c=878=ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/tdls.c-882-{
net/mac80211/tdls.c:883: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/tdls.c-884- struct ieee80211_mgmt *mgmt;
--
net/mac80211/tdls.c=997=ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/tdls.c-1004-{
net/mac80211/tdls.c:1005: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/tdls.c-1006- struct sk_buff *skb = NULL;
--
net/mac80211/tdls.c=1135=ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/tdls.c-1140-{
net/mac80211/tdls.c:1141: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/tdls.c-1142- struct ieee80211_local *local = sdata->local;
--
net/mac80211/tdls.c=1206=ieee80211_tdls_mgmt_teardown(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/tdls.c-1212-{
net/mac80211/tdls.c:1213: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/tdls.c-1214- struct ieee80211_local *local = sdata->local;
--
net/mac80211/tdls.c=1254=int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/tdls.c-1259-{
net/mac80211/tdls.c:1260: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/tdls.c-1261- int ret;
--
net/mac80211/tdls.c=1413=int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/tdls.c-1416- struct sta_info *sta;
net/mac80211/tdls.c:1417: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/tdls.c-1418- struct ieee80211_local *local = sdata->local;
--
net/mac80211/tdls.c=1622=ieee80211_tdls_channel_switch(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/tdls.c-1625-{
net/mac80211/tdls.c:1626: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/tdls.c-1627- struct ieee80211_local *local = sdata->local;
--
net/mac80211/tdls.c=1673=ieee80211_tdls_cancel_channel_switch(struct wiphy *wiphy,
--
net/mac80211/tdls.c-1676-{
net/mac80211/tdls.c:1677: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/tdls.c-1678- struct ieee80211_local *local = sdata->local;
--
net/mac80211/tx.c=2317=netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
--
net/mac80211/tx.c-2328-
net/mac80211/tx.c:2329: sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/tx.c-2330- if (unlikely(!ieee80211_sdata_running(sdata)))
--
net/mac80211/tx.c=4326=void __ieee80211_subif_start_xmit(struct sk_buff *skb,
--
net/mac80211/tx.c-4331-{
net/mac80211/tx.c:4332: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
net/mac80211/tx.c-4333- struct ieee80211_local *local = sdata->local;
--
net/mac80211/tx.c=4423=static bool ieee80211_multicast_to_unicast(struct sk_buff *skb,
--
net/mac80211/tx.c-4425-{
]
|
| 28/2 |
2026/06/27 02:06 |
llm |
expert |
0m
Model:
Tokens:
input: 32677
output: 58
thoughts: 48
Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience:
**Diving into the 802.11 Sub-Interface Macro**
Right, so I'm looking at some mac80211 code, and I immediately notice `IEEE80211_DEV_TO_SUB_IF`. Okay, that's familiar. Let's see... a quick mental cross-reference, and I recall that's defined in `net/mac80211/ieee80211_i.h`. Specifically, line 1727. My intuition is telling me this macro likely provides a convenient way to get a specific sub-interface from its device context. It's probably related to how mac80211 handles virtual interfaces, station interfaces, or maybe some other kind of logically segmented interface within a single physical device. I'll need to dig into the definition itself to confirm the exact implementation, of course, but that's my initial hypothesis based on the naming and typical mac80211 structure. This is good, it allows to isolate various concerns.
|
| 29/2 |
2026/06/27 02:06 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/mac80211/ieee80211_i.h Name:IEEE80211_DEV_TO_SUB_IF]
Results: map[SourceCode:1726: static inline struct ieee80211_sub_if_data *
1727: IEEE80211_DEV_TO_SUB_IF(const struct net_device *dev)
1728: {
1729: return netdev_priv(dev);
1730: }
SourceFile:net/mac80211/ieee80211_i.h]
|
| 30/2 |
2026/06/27 02:06 |
llm |
expert |
0m
Model:
Tokens:
input: 33153
output: 20
thoughts: 106
Thoughts: **Analyzing the Behavior of `netdev_priv` with a NULL `dev` Argument**
Okay, so I'm thinking through this `netdev_priv` situation. The core of it seems to be how it handles a NULL `dev` argument. My immediate thought is, if `dev` *is* NULL, then `netdev_priv(NULL)` should return... Wait, let me break this down carefully. If I remember correctly, the definition involves adding an offset to the `dev` pointer. Right. It should return `NULL + ALIGN(sizeof(struct net_device), NETDEV_ALIGN)`. Which effectively translates to the starting address plus the aligned size of the `net_device` struct.
But hold on, let's look at the implementation of `netdev_priv` again, it's defined as `(void *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN)`. So, that means if `dev` is null, it's just going to be something like `0x0` plus the aligned size, let's say `0x1000` or something along those lines. So the function will return an address that is the beginning of the memory allocated for the private data of a hypothetical device.
I should verify that in the code, because my gut feeling is that is what it will do. Let me go check the `netdev_priv` definition again to be certain.
|
| 31/2 |
2026/06/27 02:06 |
tool |
grepper |
0m
Error:
Args: map[Expression:#define netdev_priv]
Results:
|
| 32/2 |
2026/06/27 02:06 |
llm |
expert |
0m
Model:
Tokens:
input: 33603
output: 22
thoughts: 8
Thoughts: Okay, here's my summary, presented as a stream of thought:
**Analyzing the Function Definition**
Alright, let's break this down. First off, it's a static inline function. Hmm, "static" means its scope is limited to the current compilation unit, so it's not going to be visible outside of the file it's defined in. That makes it easier to manage in terms of preventing naming conflicts. Good for modularity. And the "inline" keyword... ah, yes, that's a directive to the compiler. It's a suggestion, of course, but the compiler will *probably* try to expand the function's code directly at the call site, avoiding the overhead of a function call. It's an optimization technique. It usually improves performance and execution time by reducing branching and function call overhead, making it faster, but it also increases the compiled code size. I'll need to consider this in the context of memory constraints and the complexity of this function later on.
|
| 33/2 |
2026/06/27 02:06 |
tool |
grepper |
0m
Args: map[Expression:static inline void \*netdev_priv]
Results: map[Output:include/linux/netdevice.h=2793=void dev_net_set(struct net_device *dev, struct net *net)
--
include/linux/netdevice.h-2803- */
include/linux/netdevice.h:2804:static inline void *netdev_priv(const struct net_device *dev)
include/linux/netdevice.h-2805-{
]
|
| 34/2 |
2026/06/27 02:06 |
llm |
expert |
0m
Model:
Tokens:
input: 33956
output: 37
thoughts: 10
Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person:
**Diving into the `netdev_priv` Structure**
Alright, time to crack this open. Let's see what we're dealing with here, shall we? My immediate thought is to get my hands dirty and dive right into the `netdev_priv` structure. We know this is the private data associated with a network device – that critical area where all the driver-specific magic happens. I'm thinking about the intimate details of a particular NIC's configuration, its registers, internal state variables, the whole shebang. Understanding this structure is absolutely paramount. I'm expecting to find the key elements that dictate the device's behavior, its interaction with the kernel, and ultimately, its performance characteristics. I’m hoping this structure tells me something interesting. Hopefully it provides a path to better understanding. So, `netdev_priv` it is. Let's dig in.
|
| 35/2 |
2026/06/27 02:06 |
tool |
read-file |
0m
Args: map[File:include/linux/netdevice.h FirstLine:2804 LineCount:10]
Results: map[Contents:2804: static inline void *netdev_priv(const struct net_device *dev)
2805: {
2806: return (void *)dev->priv;
2807: }
2808:
2809: /**
2810: * netdev_from_priv() - get network device from priv
2811: * @priv: network device private data
2812: *
2813: * Returns: net_device to which @priv belongs
]
|
| 36/2 |
2026/06/27 02:06 |
llm |
expert |
0m
Model:
Tokens:
input: 34361
output: 21
thoughts: 307
Thoughts: **Debugging a Potential Null Pointer Dereference**
Okay, so I'm tracing this crash and it looks like `dev->priv` is being accessed. Naturally, if `dev` is NULL, that's a classic null pointer dereference, a quick way to bring things to a halt. The crash occurs inside `__ieee80211_get_radio_mask` specifically within that `for_each_vif_active_link` loop. Let's take another look at that function definition and walk through it:
```c
static u32
__ieee80211_get_radio_mask(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_bss_conf *link_conf;
struct ieee80211_chanctx_conf *conf;
unsigned int link_id;
u32 mask = 0;
for_each_vif_active_link(&sdata->vif, link_conf, link_id) {
```
Right, it's pretty clear that if `sdata` is derived from `netdev_priv(dev)`, and `dev` is null, that's where the crash originates. I'm wondering though, I seem to remember `dev->priv` has an offset, doesn't it? Let me just double-check that offset and make sure I haven't mixed something up. Okay, no, `dev` is a pointer to the `struct net_device`. Just need to quickly re-familiarize myself with the layout of that struct...
|
| 37/2 |
2026/06/27 02:06 |
tool |
codesearch-struct-layout |
0m
Args:
Results: map[Fields:[map[Name:__cacheline_group_begin__net_device_read_tx OffsetBits:0 SizeBits:0] map[Name: OffsetBits:0 SizeBits:64] map[Name:netdev_ops OffsetBits:64 SizeBits:64] map[Name:header_ops OffsetBits:128 SizeBits:64] map[Name:_tx OffsetBits:192 SizeBits:64] map[Name:gso_partial_features OffsetBits:256 SizeBits:64] map[Name:real_num_tx_queues OffsetBits:320 SizeBits:32] map[Name:gso_max_size OffsetBits:352 SizeBits:32] map[Name:gso_ipv4_max_size OffsetBits:384 SizeBits:32] map[Name:gso_max_segs OffsetBits:416 SizeBits:16] map[Name:num_tc OffsetBits:432 SizeBits:16] map[Name:mtu OffsetBits:448 SizeBits:32] map[Name:needed_headroom OffsetBits:480 SizeBits:16] map[Name:tc_to_txq OffsetBits:496 SizeBits:512] map[Name:xps_maps OffsetBits:1024 SizeBits:128] map[Name:nf_hooks_egress OffsetBits:1152 SizeBits:64] map[Name:tcx_egress OffsetBits:1216 SizeBits:64] map[Name:__cacheline_group_end__net_device_read_tx OffsetBits:1280 SizeBits:0] map[Name:__cacheline_group_begin__net_device_read_txrx OffsetBits:1280 SizeBits:0] map[Name: OffsetBits:1280 SizeBits:64] map[Name:state OffsetBits:1344 SizeBits:64] map[Name:flags OffsetBits:1408 SizeBits:32] map[Name:hard_header_len OffsetBits:1440 SizeBits:16] map[Name:pcpu_stat_type OffsetBits:1456 SizeBits:8] map[Name:features OffsetBits:1472 SizeBits:64] map[Name:ip6_ptr OffsetBits:1536 SizeBits:64] map[Name:__cacheline_group_end__net_device_read_txrx OffsetBits:1600 SizeBits:0] map[Name:__cacheline_group_begin__net_device_read_rx OffsetBits:1600 SizeBits:0] map[Name:xdp_prog OffsetBits:1600 SizeBits:64] map[Name:ptype_specific OffsetBits:1664 SizeBits:128] map[Name:ifindex OffsetBits:1792 SizeBits:32] map[Name:real_num_rx_queues OffsetBits:1824 SizeBits:32] map[Name:_rx OffsetBits:1856 SizeBits:64] map[Name:gro_max_size OffsetBits:1920 SizeBits:32] map[Name:gro_ipv4_max_size OffsetBits:1952 SizeBits:32] map[Name:rx_handler OffsetBits:1984 SizeBits:64] map[Name:rx_handler_data OffsetBits:2048 SizeBits:64] map[Name:nd_net OffsetBits:2112 SizeBits:64] map[Name:npinfo OffsetBits:2176 SizeBits:64] map[Name:tcx_ingress OffsetBits:2240 SizeBits:64] map[Name:__cacheline_group_end__net_device_read_rx OffsetBits:2304 SizeBits:0] map[Name:name OffsetBits:2304 SizeBits:128] map[Name:name_node OffsetBits:2432 SizeBits:64] map[Name:ifalias OffsetBits:2496 SizeBits:64] map[Name:mem_end OffsetBits:2560 SizeBits:64] map[Name:mem_start OffsetBits:2624 SizeBits:64] map[Name:base_addr OffsetBits:2688 SizeBits:64] map[Name:dev_list OffsetBits:2752 SizeBits:128] map[Name:napi_list OffsetBits:2880 SizeBits:128] map[Name:unreg_list OffsetBits:3008 SizeBits:128] map[Name:close_list OffsetBits:3136 SizeBits:128] map[Name:ptype_all OffsetBits:3264 SizeBits:128] map[Name:adj_list OffsetBits:3392 SizeBits:256] map[Name:xdp_features OffsetBits:3648 SizeBits:32] map[Name:xdp_metadata_ops OffsetBits:3712 SizeBits:64] map[Name:xsk_tx_metadata_ops OffsetBits:3776 SizeBits:64] map[Name:gflags OffsetBits:3840 SizeBits:16] map[Name:needed_tailroom OffsetBits:3856 SizeBits:16] map[Name:hw_features OffsetBits:3904 SizeBits:64] map[Name:wanted_features OffsetBits:3968 SizeBits:64] map[Name:vlan_features OffsetBits:4032 SizeBits:64] map[Name:hw_enc_features OffsetBits:4096 SizeBits:64] map[Name:mpls_features OffsetBits:4160 SizeBits:64] map[Name:mangleid_features OffsetBits:4224 SizeBits:64] map[Name:min_mtu OffsetBits:4288 SizeBits:32] map[Name:max_mtu OffsetBits:4320 SizeBits:32] map[Name:type OffsetBits:4352 SizeBits:16] map[Name:min_header_len OffsetBits:4368 SizeBits:8] map[Name:name_assign_type OffsetBits:4376 SizeBits:8] map[Name:group OffsetBits:4384 SizeBits:32] map[Name:stats OffsetBits:4416 SizeBits:1472] map[Name:core_stats OffsetBits:5888 SizeBits:64] map[Name:carrier_up_count OffsetBits:5952 SizeBits:32] map[Name:carrier_down_count OffsetBits:5984 SizeBits:32] map[Name:ethtool_ops OffsetBits:6016 SizeBits:64] map[Name:l3mdev_ops OffsetBits:6080 SizeBits:64] map[Name:ndisc_ops OffsetBits:6144 SizeBits:64] map[Name:xfrmdev_ops OffsetBits:6208 SizeBits:64] map[Name:tlsdev_ops OffsetBits:6272 SizeBits:64] map[Name:operstate OffsetBits:6336 SizeBits:32] map[Name:link_mode OffsetBits:6368 SizeBits:8] map[Name:if_port OffsetBits:6376 SizeBits:8] map[Name:dma OffsetBits:6384 SizeBits:8] map[Name:perm_addr OffsetBits:6392 SizeBits:256] map[Name:addr_assign_type OffsetBits:6648 SizeBits:8] map[Name:addr_len OffsetBits:6656 SizeBits:8] map[Name:upper_level OffsetBits:6664 SizeBits:8] map[Name:lower_level OffsetBits:6672 SizeBits:8] map[Name:threaded OffsetBits:6680 SizeBits:8] map[Name:neigh_priv_len OffsetBits:6688 SizeBits:16] map[Name:dev_id OffsetBits:6704 SizeBits:16] map[Name:dev_port OffsetBits:6720 SizeBits:16] map[Name:irq OffsetBits:6752 SizeBits:32] map[Name:priv_len OffsetBits:6784 SizeBits:32] map[Name:addr_list_lock OffsetBits:6848 SizeBits:512] map[Name:uc OffsetBits:7360 SizeBits:256] map[Name:mc OffsetBits:7616 SizeBits:256] map[Name:dev_addrs OffsetBits:7872 SizeBits:256] map[Name:queues_kset OffsetBits:8128 SizeBits:64] map[Name:unlink_list OffsetBits:8192 SizeBits:128] map[Name:promiscuity OffsetBits:8320 SizeBits:32] map[Name:allmulti OffsetBits:8352 SizeBits:32] map[Name:uc_promisc OffsetBits:8384 SizeBits:8] map[Name:rx_mode_node OffsetBits:8448 SizeBits:128] map[Name:rx_mode_tracker OffsetBits:8576 SizeBits:64] map[Name:rx_mode_addr_cache OffsetBits:8640 SizeBits:256] map[Name:rx_mode_retry_timer OffsetBits:8896 SizeBits:640] map[Name:rx_mode_retry_count OffsetBits:9536 SizeBits:32] map[Name:nested_level OffsetBits:9568 SizeBits:8] map[Name:ip_ptr OffsetBits:9600 SizeBits:64] map[Name:fib_nh_head OffsetBits:9664 SizeBits:64] map[Name:vlan_info OffsetBits:9728 SizeBits:64] map[Name:dsa_ptr OffsetBits:9792 SizeBits:64] map[Name:tipc_ptr OffsetBits:9856 SizeBits:64] map[Name:ieee80211_ptr OffsetBits:9920 SizeBits:64] map[Name:ieee802154_ptr OffsetBits:9984 SizeBits:64] map[Name:mpls_ptr OffsetBits:10048 SizeBits:64] map[Name:mctp_ptr OffsetBits:10112 SizeBits:64] map[Name:psp_dev OffsetBits:10176 SizeBits:64] map[Name:dev_addr OffsetBits:10240 SizeBits:64] map[Name:num_rx_queues OffsetBits:10304 SizeBits:32] map[Name:xdp_zc_max_segs OffsetBits:10336 SizeBits:32] map[Name:ingress_queue OffsetBits:10368 SizeBits:64] map[Name:nf_hooks_ingress OffsetBits:10432 SizeBits:64] map[Name:broadcast OffsetBits:10496 SizeBits:256] map[Name:rx_cpu_rmap OffsetBits:10752 SizeBits:64] map[Name:index_hlist OffsetBits:10816 SizeBits:128] map[Name:num_tx_queues OffsetBits:10944 SizeBits:32] map[Name:qdisc OffsetBits:11008 SizeBits:64] map[Name:tx_queue_len OffsetBits:11072 SizeBits:32] map[Name:tx_global_lock OffsetBits:11136 SizeBits:512] map[Name:xdp_bulkq OffsetBits:11648 SizeBits:64] map[Name:qdisc_hash OffsetBits:11712 SizeBits:1024] map[Name:watchdog_timer OffsetBits:12736 SizeBits:640] map[Name:watchdog_timeo OffsetBits:13376 SizeBits:32] map[Name:watchdog_lock OffsetBits:13440 SizeBits:512] map[Name:watchdog_ref_held OffsetBits:13952 SizeBits:8] map[Name:proto_down_reason OffsetBits:13984 SizeBits:32] map[Name:todo_list OffsetBits:14016 SizeBits:128] map[Name:dev_refcnt OffsetBits:14144 SizeBits:32] map[Name:refcnt_tracker OffsetBits:14208 SizeBits:960] map[Name:link_watch_list OffsetBits:15168 SizeBits:128] map[Name:reg_state OffsetBits:15296 SizeBits:8] map[Name:dismantle OffsetBits:15304 SizeBits:8] map[Name:moving_ns OffsetBits:15312 SizeBits:8] map[Name:rtnl_link_initializing OffsetBits:15320 SizeBits:8] map[Name:needs_free_netdev OffsetBits:15328 SizeBits:8] map[Name:priv_destructor OffsetBits:15360 SizeBits:64] map[Name:ml_priv OffsetBits:15424 SizeBits:64] map[Name:ml_priv_type OffsetBits:15488 SizeBits:32] map[Name:garp_port OffsetBits:15552 SizeBits:64] map[Name:mrp_port OffsetBits:15616 SizeBits:64] map[Name:dm_private OffsetBits:15680 SizeBits:64] map[Name:dev OffsetBits:15744 SizeBits:9792] map[Name:sysfs_groups OffsetBits:25536 SizeBits:320] map[Name:sysfs_rx_queue_group OffsetBits:25856 SizeBits:64] map[Name:rtnl_link_ops OffsetBits:25920 SizeBits:64] map[Name:stat_ops OffsetBits:25984 SizeBits:64] map[Name:queue_mgmt_ops OffsetBits:26048 SizeBits:64] map[Name:tso_max_size OffsetBits:26112 SizeBits:32] map[Name:tso_max_segs OffsetBits:26144 SizeBits:16] map[Name:dcbnl_ops OffsetBits:26176 SizeBits:64] map[Name:prio_tc_map OffsetBits:26240 SizeBits:128] map[Name:priomap OffsetBits:26368 SizeBits:64] map[Name:link_topo OffsetBits:26432 SizeBits:64] map[Name:phydev OffsetBits:26496 SizeBits:64] map[Name:sfp_bus OffsetBits:26560 SizeBits:64] map[Name:qdisc_tx_busylock OffsetBits:26624 SizeBits:64] map[Name:proto_down OffsetBits:26688 SizeBits:8] map[Name:irq_affinity_auto OffsetBits:26696 SizeBits:8] map[Name:rx_cpu_rmap_auto OffsetBits:26704 SizeBits:8] map[Name:see_all_hwtstamp_requests OffsetBits:26712 SizeBits:1] map[Name:change_proto_down OffsetBits:26713 SizeBits:1] map[Name:netns_immutable OffsetBits:26714 SizeBits:1] map[Name:fcoe_mtu OffsetBits:26715 SizeBits:1] map[Name:net_notifier_list OffsetBits:26752 SizeBits:128] map[Name:macsec_ops OffsetBits:26880 SizeBits:64] map[Name:udp_tunnel_nic_info OffsetBits:26944 SizeBits:64] map[Name:udp_tunnel_nic OffsetBits:27008 SizeBits:64] map[Name:cfg OffsetBits:27072 SizeBits:64] map[Name:cfg_pending OffsetBits:27136 SizeBits:64] map[Name:ethtool OffsetBits:27200 SizeBits:64] map[Name:xdp_state OffsetBits:27264 SizeBits:384] map[Name:dev_addr_shadow OffsetBits:27648 SizeBits:256] map[Name:linkwatch_dev_tracker OffsetBits:27904 SizeBits:64] map[Name:watchdog_dev_tracker OffsetBits:27968 SizeBits:64] map[Name:dev_registered_tracker OffsetBits:28032 SizeBits:64] map[Name:offload_xstats_l3 OffsetBits:28096 SizeBits:64] map[Name:devlink_port OffsetBits:28160 SizeBits:64] map[Name:page_pools OffsetBits:28224 SizeBits:64] map[Name:irq_moder OffsetBits:28288 SizeBits:64] map[Name:max_pacing_offload_horizon OffsetBits:28352 SizeBits:64] map[Name:napi_config OffsetBits:28416 SizeBits:64] map[Name:num_napi_configs OffsetBits:28480 SizeBits:32] map[Name:napi_defer_hard_irqs OffsetBits:28512 SizeBits:32] map[Name:gro_flush_timeout OffsetBits:28544 SizeBits:64] map[Name:up OffsetBits:28608 SizeBits:8] map[Name:request_ops_lock OffsetBits:28616 SizeBits:8] map[Name:lock OffsetBits:28672 SizeBits:1088] map[Name:net_shaper_hierarchy OffsetBits:29760 SizeBits:64] map[Name:neighbours OffsetBits:29824 SizeBits:128] map[Name:hwprov OffsetBits:29952 SizeBits:64] map[Name:priv OffsetBits:30208 SizeBits:0]]]
|
| 38/2 |
2026/06/27 02:06 |
llm |
expert |
0m
Model:
Tokens:
input: 39908
output: 31
thoughts: 217
Thoughts: **Deconstructing the `netdev_priv` Pointer Arithmetic**
Okay, let's break this down. `priv` is sitting at an offset of 30208 bits, which is the same as 3776 bytes, or in hexadecimal, `0xec0`. That makes sense. Wait, hang on... `netdev_priv` returns `(void *)dev->priv`? No, that's not quite right. Thinking back, `dev->priv` is actually a zero-length array at the *end* of `struct net_device`. Ah, right, that's it! `priv` *is* at offset 30208 bits, which is the same as 3776 bytes and `0xec0`. So, `netdev_priv(dev)` effectively returns `dev + 0xec0`, giving me a pointer that's offset from the beginning of the `net_device` struct.
Now, if `dev` *is* NULL, `netdev_priv(dev)` would end up returning `0xec0` directly. This then means that `sdata` ends up being `0xec0`. In the `__ieee80211_get_radio_mask` function, the code then accesses `sdata->vif`. Okay, makes sense. Now I need to refresh my memory and figure out what the offset of `vif` is within `struct ieee80211_sub_if_data`.
|
| 39/2 |
2026/06/27 02:06 |
tool |
codesearch-struct-layout |
0m
Args: map[Name:ieee80211_sub_if_data]
Results: map[Fields:[map[Name:list OffsetBits:0 SizeBits:128] map[Name:wdev OffsetBits:128 SizeBits:20736] map[Name:key_list OffsetBits:20864 SizeBits:128] map[Name:crypto_tx_tailroom_needed_cnt OffsetBits:20992 SizeBits:32] map[Name:crypto_tx_tailroom_pending_dec OffsetBits:21024 SizeBits:32] map[Name:dec_tailroom_needed_wk OffsetBits:21056 SizeBits:896] map[Name:dev OffsetBits:21952 SizeBits:64] map[Name:local OffsetBits:22016 SizeBits:64] map[Name:flags OffsetBits:22080 SizeBits:32] map[Name:state OffsetBits:22144 SizeBits:64] map[Name:name OffsetBits:22208 SizeBits:128] map[Name:frags OffsetBits:22336 SizeBits:3904] map[Name:noack_map OffsetBits:26240 SizeBits:16] map[Name:wmm_acm OffsetBits:26256 SizeBits:8] map[Name:keys OffsetBits:26304 SizeBits:256] map[Name:default_unicast_key OffsetBits:26560 SizeBits:64] map[Name:sequence_number OffsetBits:26624 SizeBits:16] map[Name:mld_mcast_seq OffsetBits:26640 SizeBits:16] map[Name:control_port_protocol OffsetBits:26656 SizeBits:16] map[Name:control_port_no_encrypt OffsetBits:26672 SizeBits:8] map[Name:control_port_no_preauth OffsetBits:26680 SizeBits:8] map[Name:control_port_over_nl80211 OffsetBits:26688 SizeBits:8] map[Name:num_tx_queued OffsetBits:26720 SizeBits:32] map[Name:qos_map OffsetBits:26752 SizeBits:64] map[Name:work OffsetBits:26816 SizeBits:192] map[Name:skb_queue OffsetBits:27008 SizeBits:704] map[Name:status_queue OffsetBits:27712 SizeBits:704] map[Name:bss OffsetBits:28416 SizeBits:64] map[Name:rc_rateidx_mask OffsetBits:28480 SizeBits:192] map[Name:rc_has_mcs_mask OffsetBits:28672 SizeBits:48] map[Name:rc_rateidx_mcs_mask OffsetBits:28720 SizeBits:480] map[Name:rc_has_vht_mcs_mask OffsetBits:29200 SizeBits:48] map[Name:rc_rateidx_vht_mcs_mask OffsetBits:29248 SizeBits:768] map[Name:beacon_rateidx_mask OffsetBits:30016 SizeBits:192] map[Name:beacon_rate_set OffsetBits:30208 SizeBits:8] map[Name:u OffsetBits:30272 SizeBits:20736] map[Name:deflink OffsetBits:51008 SizeBits:8960] map[Name:link OffsetBits:59968 SizeBits:960] map[Name:activate_links_work OffsetBits:60928 SizeBits:192] map[Name:desired_active_links OffsetBits:61120 SizeBits:16] map[Name:restart_active_links OffsetBits:61136 SizeBits:16] map[Name:debugfs OffsetBits:61184 SizeBits:320] map[Name:tx_handlers_drop OffsetBits:61504 SizeBits:32] map[Name:vif OffsetBits:61568 SizeBits:17536]]]
|
| 40/2 |
2026/06/27 02:06 |
llm |
expert |
0m
Model:
Tokens:
input: 41593
output: 28
thoughts: 292
Thoughts: **Analyzing the `vif` Structure in Relation to `__ieee80211_get_radio_mask`**
Okay, so I'm looking at this code and trying to figure out how `sdata->vif` is being accessed. First, `vif` is at an offset of 61568 bits, which is 7696 bytes or `0x1e10` in hex. `sdata` itself is at `0xec0`, so `sdata->vif` calculates to `0xec0 + 0x1e10 = 0x2cd0`. Just making sure I've got that straight... `sdata` is `0xec0`, and thus `sdata->vif` is indeed at `0x2cd0`.
Now, I see the code snippet from `__ieee80211_get_radio_mask`, specifically this loop:
```c
for_each_vif_active_link(&sdata->vif, link_conf, link_id) {
```
That macro `for_each_vif_active_link` is key here. Let's see how that expands:
```c
#define for_each_vif_active_link(vif, link, link_id) \
for (link_id = 0; link_id < ARRAY_SIZE((vif)->link_conf); link_id++) \
if ((!(vif)->active_links || \
(vif)->active_links & BIT(link_id)) && \
(link = link_conf_dereference_check(vif, link_id)))
```
This is iterating through the `link_conf` array within the `vif` structure. The important part seems to be the check on `(vif)->active_links`. Before I dive any further, I want to make sure I understand the offset of `active_links` within the `struct ieee80211_vif`. This will help me understand how this code is truly utilizing the `active_links` field and how it relates to the broader data structure. I'm going to determine how this relates to my mental model of this structure.
|
| 41/2 |
2026/06/27 02:06 |
tool |
codesearch-struct-layout |
0m
Args:
Results: map[Fields:[map[Name:type OffsetBits:0 SizeBits:32] map[Name:cfg OffsetBits:64 SizeBits:6272] map[Name:bss_conf OffsetBits:6336 SizeBits:9408] map[Name:link_conf OffsetBits:15744 SizeBits:960] map[Name:valid_links OffsetBits:16704 SizeBits:16] map[Name:active_links OffsetBits:16720 SizeBits:16] map[Name:dormant_links OffsetBits:16736 SizeBits:16] map[Name:suspended_links OffsetBits:16752 SizeBits:16] map[Name:neg_ttlm OffsetBits:16768 SizeBits:272] map[Name:addr OffsetBits:17040 SizeBits:48] map[Name:addr_valid OffsetBits:17088 SizeBits:8] map[Name:p2p OffsetBits:17096 SizeBits:8] map[Name:cab_queue OffsetBits:17104 SizeBits:8] map[Name:hw_queue OffsetBits:17112 SizeBits:32] map[Name:txq OffsetBits:17152 SizeBits:64] map[Name:txq_mgmt OffsetBits:17216 SizeBits:64] map[Name:netdev_features OffsetBits:17280 SizeBits:64] map[Name:driver_flags OffsetBits:17344 SizeBits:32] map[Name:offload_flags OffsetBits:17376 SizeBits:32] map[Name:debugfs_dir OffsetBits:17408 SizeBits:64] map[Name:probe_req_reg OffsetBits:17472 SizeBits:8] map[Name:rx_mcast_action_reg OffsetBits:17480 SizeBits:8] map[Name:drv_priv OffsetBits:17536 SizeBits:0]]]
|
| 42/2 |
2026/06/27 02:06 |
llm |
expert |
0m
Model:
Tokens:
input: 42965
output: 44
thoughts: 140
Thoughts: Okay, let me break this down.
**Analyzing a Potential Memory Corruption**
Right, so `active_links` for this virtual interface, `vif`, is located 2090 bytes into its structure, specifically at an offset of `0x82a` from the beginning. We also know that `vif` starts at `0x2cd0`, therefore, `(vif)->active_links` should be at `0x34fa`. Now, wait a second... the crash address is `0x34f8`. This is very close and immediately catches my attention.
Let's see, `link_conf` is at offset 1968 bytes = `0x7b0`. Also, I believe `vif->link_conf` is an array. Ok, the crash is probably linked to the array `link_conf`. Let's now examine `link_conf_dereference_check` to see if that reveals the problem.
|
| 43/2 |
2026/06/27 02:06 |
tool |
codesearch-definition-source |
0m
Error:
Args: map[ContextFile:include/net/mac80211.h Name:link_conf_dereference_check]
Results: map[SourceCode: SourceFile:]
|
| 44/2 |
2026/06/27 02:06 |
llm |
expert |
0m
Model:
Tokens:
input: 43381
output: 24
thoughts: 15
Thoughts: Here's my thought process, as if I were considering this search:
**Initial Assessment: Grep Search for a Specific Function**
Okay, so I need to find something, and the immediate thought is to use `grep`. That's standard practice when dealing with codebases, particularly larger ones where manual searching is a non-starter. The specific target is `link_conf_dereference_check`. That's a pretty specific function name, which is good. It gives me a decent chance of narrowing down the results effectively. The name itself suggests it's related to configuration, specifically dereferencing something, and likely involves some sort of checking mechanism. This probably indicates there is a function relating to checking a pointer before dereferencing it. My focus is going to be on efficiency and relevance. A targeted search like this is generally preferable to a broader, more generic one.
|
| 45/2 |
2026/06/27 02:06 |
tool |
grepper |
0m
Args: map[Expression:#define link_conf_dereference_check]
Results: map[Output:include/net/mac80211.h=2328=static inline bool lockdep_vif_wiphy_mutex_held(struct ieee80211_vif *vif)
--
include/net/mac80211.h-2336-
include/net/mac80211.h:2337:#define link_conf_dereference_check(vif, link_id) \
include/net/mac80211.h-2338- rcu_dereference_check((vif)->link_conf[link_id], \
]
|
| 46/2 |
2026/06/27 02:06 |
llm |
expert |
0m
Model:
Tokens:
input: 43765
output: 41
thoughts: 14
Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person:
**Analyzing the Code's Navigation Intent**
Alright, so the first step in tackling this task is clear: let's dive into the function `link_conf_dereference_check`. This name itself is informative. "link_conf" suggests we're dealing with configuration related to links, and "dereference_check" *strongly* implies we're about to explore the validity, safety, and possibly the consequences of following a pointer. My immediate thought is, what are the potential vulnerabilities at play here? Is this about preventing use-after-free, null pointer dereferences, or perhaps something more nuanced related to configuration validity and consistency within a linked structure?
I'm already mentally forming a hypothesis: likely a pointer to config data is being validated *before* it's actually used. We could be dealing with a linked list or tree of configuration objects, where this function ensures the integrity of the data being pointed to before letting subsequent routines act on it. My mind is already racing through potential scenarios; race conditions involving modification of configuration state, potential corruption. Let's see if those assumptions are correct.
|
| 47/2 |
2026/06/27 02:06 |
tool |
read-file |
0m
Args: map[File:include/net/mac80211.h FirstLine:2337 LineCount:10]
Results: map[Contents:2337: #define link_conf_dereference_check(vif, link_id) \
2338: rcu_dereference_check((vif)->link_conf[link_id], \
2339: lockdep_vif_wiphy_mutex_held(vif))
2340:
2341: /**
2342: * enum ieee80211_key_flags - key flags
2343: *
2344: * These flags are used for communication about keys between the driver
2345: * and mac80211, with the @flags parameter of &struct ieee80211_key_conf.
2346: *
]
|
| 48/2 |
2026/06/27 02:06 |
llm |
expert |
0m
Model:
Tokens:
input: 44279
output: 43
thoughts: 487
Thoughts: **Debugging a KASAN Trap**
Okay, so I've hit a KASAN trap, and I need to figure out what's going on. The address `(vif)->active_links` is at `0x34fa`. The failing instruction is `movzbl (%rax,%r15,1),%eax`, and `%rax` holds `0x34f8`. My initial thought was that `0x34f8` might be `0x34fa` with some bitmasking, like `0x34fa & ~7`. But, wait, `active_links` is a `u16`, so the byte access is what's tripping me up.
Let's look at the assembly. I've got:
```assembly
24: 48 8b 44 24 30 mov 0x30(%rsp),%rax
* 29: 42 0f b6 04 38 movzbl (%rax,%r15,1),%eax <-- trapping instruction
2e: 84 c0 test %al,%al
30: 0f 85 f6 02 00 00 jne 0x32c
36: 48 8b 44 24 08 mov 0x8(%rsp),%rax
3b: 44 0f b7 28 movzwl (%rax),%r13d
```
This is definitely KASAN checking the memory access. `%rax` is `0x69f`. Now, `0x69f * 8 = 0x34f8`. So, KASAN is checking the shadow byte for `0x34f8`. The actual address I'm trying to access is `0x34fa`, which corresponds to `active_links`.
Since `0x34fa` is a near-NULL address, KASAN catches it. Okay, that confirms it: `vif` is at `0x2cd0`, and `vif->active_links` is at `0x34fa`. Which also confirms that `dev` is NULL.
So the problem is that `dev` is NULL. Now, I need to figure out *why* `dev` is NULL. Let's trace back. I should look at `cfg80211_calculate_bi_data` in `net/wireless/util.c:2431`.
|
| 49/2 |
2026/06/27 02:06 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/wireless/util.c Name:cfg80211_calculate_bi_data]
Results: map[SourceCode:2410: static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
2411: u32 *beacon_int_gcd,
2412: bool *beacon_int_different,
2413: int radio_idx)
2414: {
2415: struct cfg80211_registered_device *rdev;
2416: struct wireless_dev *wdev;
2417:
2418: *beacon_int_gcd = 0;
2419: *beacon_int_different = false;
2420:
2421: rdev = wiphy_to_rdev(wiphy);
2422: list_for_each_entry(wdev, &wiphy->wdev_list, list) {
2423: int wdev_bi;
2424:
2425: /* this feature isn't supported with MLO */
2426: if (wdev->valid_links)
2427: continue;
2428:
2429: /* skip wdevs not active on the given wiphy radio */
2430: if (radio_idx >= 0 &&
2431: !(rdev_get_radio_mask(rdev, wdev->netdev) & BIT(radio_idx)))
2432: continue;
2433:
2434: wdev_bi = cfg80211_wdev_bi(wdev);
2435:
2436: if (!wdev_bi)
2437: continue;
2438:
2439: if (!*beacon_int_gcd) {
2440: *beacon_int_gcd = wdev_bi;
2441: continue;
2442: }
2443:
2444: if (wdev_bi == *beacon_int_gcd)
2445: continue;
2446:
2447: *beacon_int_different = true;
2448: *beacon_int_gcd = gcd(*beacon_int_gcd, wdev_bi);
2449: }
2450:
2451: if (new_beacon_int && *beacon_int_gcd != new_beacon_int) {
2452: if (*beacon_int_gcd)
2453: *beacon_int_different = true;
2454: *beacon_int_gcd = gcd(*beacon_int_gcd, new_beacon_int);
2455: }
2456: }
SourceFile:net/wireless/util.c]
|
| 50/2 |
2026/06/27 02:07 |
llm |
expert |
0m
Model:
Tokens:
input: 46128
output: 41
thoughts: 274
Thoughts: **Analyzing a Potential NULL Pointer Dereference**
Okay, so I'm looking at this `wdev->netdev` pointer and how it's being used within the `rdev_get_radio_mask` function. Right, so `wdev->netdev` is passed in. But hang on, what if `wdev` is a P2P Device, or some other wireless device where a `netdev` isn't assigned? In those cases, `wdev->netdev` could be NULL. I see, if `wdev->netdev` *is* NULL, then `rdev_get_radio_mask` will ultimately call `rdev->ops->get_radio_mask(wiphy, NULL)`.
Now, in the `mac80211` implementation of `ieee80211_get_radio_mask`, it uses `IEEE80211_DEV_TO_SUB_IF(dev)`, which then does `netdev_priv(dev)`. That's where things get interesting. If that `dev` argument is NULL – which it would be if `wdev->netdev` *was* NULL – the code will return a bogus pointer, and that’s a recipe for a NULL pointer dereference.
Let me just confirm that `wdev->netdev` *can* actually be NULL. Ah, right, the `NL80211_IFTYPE_P2P_DEVICE` interface type is a prime example; it doesn’t have an associated `netdev`.
Hmm, I think `cfg80211_calculate_bi_data` is called from `cfg80211_iter_combinations`, let me take a look at `cfg80211_iter_combinations`.
|
| 51/2 |
2026/06/27 02:07 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/wireless/util.c Name:cfg80211_iter_combinations]
Results: map[SourceCode:2475: int cfg80211_iter_combinations(struct wiphy *wiphy,
2476: struct iface_combination_params *params,
2477: void (*iter)(const struct ieee80211_iface_combination *c,
2478: void *data),
2479: void *data)
2480: {
2481: const struct wiphy_radio *radio = NULL;
2482: const struct ieee80211_iface_combination *c, *cs;
2483: const struct ieee80211_regdomain *regdom;
2484: enum nl80211_dfs_regions region = 0;
2485: int i, j, n, iftype;
2486: int num_interfaces = 0;
2487: u32 used_iftypes = 0;
2488: u32 beacon_int_gcd;
2489: bool beacon_int_different;
2490:
2491: if (params->radio_idx >= 0)
2492: radio = &wiphy->radio[params->radio_idx];
2493:
2494: /*
2495: * This is a bit strange, since the iteration used to rely only on
2496: * the data given by the driver, but here it now relies on context,
2497: * in form of the currently operating interfaces.
2498: * This is OK for all current users, and saves us from having to
2499: * push the GCD calculations into all the drivers.
2500: * In the future, this should probably rely more on data that's in
2501: * cfg80211 already - the only thing not would appear to be any new
2502: * interfaces (while being brought up) and channel/radar data.
2503: */
2504: cfg80211_calculate_bi_data(wiphy, params->new_beacon_int,
2505: &beacon_int_gcd, &beacon_int_different,
2506: params->radio_idx);
2507:
2508: if (params->radar_detect) {
2509: rcu_read_lock();
2510: regdom = rcu_dereference(cfg80211_regdomain);
2511: if (regdom)
2512: region = regdom->dfs_region;
2513: rcu_read_unlock();
2514: }
2515:
2516: for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
2517: num_interfaces += params->iftype_num[iftype];
2518: if (params->iftype_num[iftype] > 0 &&
2519: !cfg80211_iftype_allowed(wiphy, iftype, 0, 1))
2520: used_iftypes |= BIT(iftype);
2521: }
2522:
2523: if (radio) {
2524: cs = radio->iface_combinations;
2525: n = radio->n_iface_combinations;
2526: } else {
2527: cs = wiphy->iface_combinations;
2528: n = wiphy->n_iface_combinations;
2529: }
2530: for (i = 0; i < n; i++) {
2531: struct ieee80211_iface_limit *limits;
2532: u32 all_iftypes = 0;
2533:
2534: c = &cs[i];
2535: if (num_interfaces > c->max_interfaces)
2536: continue;
2537: if (params->num_different_channels > c->num_different_channels)
2538: continue;
2539:
2540: limits = kmemdup_array(c->limits, c->n_limits, sizeof(*limits),
2541: GFP_KERNEL);
2542: if (!limits)
2543: return -ENOMEM;
2544:
2545: for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
2546: if (cfg80211_iftype_allowed(wiphy, iftype, 0, 1))
2547: continue;
2548: for (j = 0; j < c->n_limits; j++) {
2549: all_iftypes |= limits[j].types;
2550: if (!(limits[j].types & BIT(iftype)))
2551: continue;
2552: if (limits[j].max < params->iftype_num[iftype])
2553: goto cont;
2554: limits[j].max -= params->iftype_num[iftype];
2555: }
2556: }
2557:
2558: if (params->radar_detect !=
2559: (c->radar_detect_widths & params->radar_detect))
2560: goto cont;
2561:
2562: if (params->radar_detect && c->radar_detect_regions &&
2563: !(c->radar_detect_regions & BIT(region)))
2564: goto cont;
2565:
2566: /* Finally check that all iftypes that we're currently
2567: * using are actually part of this combination. If they
2568: * aren't then we can't use this combination and have
2569: * to continue to the next.
2570: */
2571: if ((all_iftypes & used_iftypes) != used_iftypes)
2572: goto cont;
2573:
2574: if (beacon_int_gcd) {
2575: if (c->beacon_int_min_gcd &&
2576: beacon_int_gcd < c->beacon_int_min_gcd)
2577: goto cont;
2578: if (!c->beacon_int_min_gcd && beacon_int_different)
2579: goto cont;
2580: }
2581:
2582: /* This combination covered all interface types and
2583: * supported the requested numbers, so we're good.
2584: */
2585:
2586: (*iter)(c, data);
2587: cont:
2588: kfree(limits);
2589: }
2590:
2591: return 0;
2592: }
SourceFile:net/wireless/util.c]
|
| 52/2 |
2026/06/27 02:07 |
llm |
expert |
0m
Model:
Tokens:
input: 48733
output: 23
thoughts: 527
Thoughts: **Analyzing a Potential NULL Pointer Dereference**
Okay, so I'm looking at this code and something's immediately jumping out at me. I see that `wdev->netdev` could be NULL. If that's the case, then `rdev_get_radio_mask` gets called with a `dev` value that's NULL. That's a red flag. Digging deeper, I see `mac80211` calls `ieee80211_get_radio_mask`. The implementation looks like this, and it looks like the `dev` parameter gets passed as `NULL`. This function ultimately leads to `__ieee80211_get_radio_mask` where there's an issue.
```c
u32 ieee80211_get_radio_mask(struct wiphy *wiphy, struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
return __ieee80211_get_radio_mask(sdata);
}
```
Now, with `dev` being NULL, `sdata` ends up being `0xec0`. It looks like later on the code attempts to access `sdata->vif`, and then accesses `vif->active_links`. I can see the potential for a NULL pointer dereference right there. My initial thought is, this is not good.
The key question is: is this a `mac80211` bug, or is it a problem in `cfg80211`? I need to understand the call chain and the intended behavior.
Let's look at `cfg80211_calculate_bi_data`, because that's where `rdev_get_radio_mask` is called.
```c
list_for_each_entry(wdev, &wiphy->wdev_list, list) {
int wdev_bi;
/* this feature isn't supported with MLO */
if (wdev->valid_links)
continue;
/* skip wdevs not active on the given wiphy radio */
if (radio_idx >= 0 &&
!(rdev_get_radio_mask(rdev, wdev->netdev) & BIT(radio_idx)))
continue;
```
Here it is. If `wdev->netdev` is NULL, then `rdev_get_radio_mask` *does* receive `NULL`. However, the expectation should be for `rdev_get_radio_mask` to handle the NULL `dev` value. Is there something fundamentally wrong in how `rdev_get_radio_mask` is implemented in my driver? If that's the case then this is a bug in the higher level function and not a dereference. If there's some special handling or checks that should be going on, then maybe `mac80211` needs to check whether to pass a `NULL` to `rdev_get_radio_mask`.
I need to see if there are *other* implementations of `get_radio_mask`. Perhaps there are different approaches for handling a NULL `netdev` pointer. I need to get a better overview. I need to be sure that `rdev_get_radio_mask` has expected behavior.
|
| 53/2 |
2026/06/27 02:07 |
tool |
grepper |
0m
Args: map[Expression:\.get_radio_mask\s*=]
Results: map[Output:net/mac80211/cfg.c=5987=const struct cfg80211_ops mac80211_config_ops = {
--
net/mac80211/cfg.c-6099- .set_ttlm = ieee80211_set_ttlm,
net/mac80211/cfg.c:6100: .get_radio_mask = ieee80211_get_radio_mask,
net/mac80211/cfg.c-6101- .assoc_ml_reconf = ieee80211_assoc_ml_reconf,
]
|
| 54/2 |
2026/06/27 02:07 |
llm |
expert |
0m
Model:
Tokens:
input: 50221
output: 42
thoughts: 153
Thoughts: **Investigating the Radio Mask and Beacon Interval Logic**
Okay, so the `get_radio_mask` function, as far as I can see, is only implemented within `mac80211`. That's the first thing to note. Now, the `mac80211` implementation assumes that the `dev` pointer, which it receives, is *not* NULL. Specifically, it uses `IEEE80211_DEV_TO_SUB_IF(dev)`. That's a potential issue if we have a NULL device pointer.
Hang on a second. If `wdev->netdev` is actually NULL, does the `wdev` struct even *have* a radio mask? This is where things get interesting. My understanding is that a NULL `wdev->netdev` likely indicates a P2P Device or something similar—a virtual interface. If it's a virtual interface, does it even *use* a beacon interval? I'll need to confirm that.
Alright, the next step is to examine how the beacon interval is retrieved using `wdev_bi = cfg80211_wdev_bi(wdev);`. I need to dig into `cfg80211_wdev_bi` to understand how that function is handling the various scenarios. This will clarify how the code navigates the presence or absence of a network device and other critical data.
|
| 55/2 |
2026/06/27 02:07 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/wireless/util.c Name:cfg80211_wdev_bi]
Results: map[SourceCode:2392: static int cfg80211_wdev_bi(struct wireless_dev *wdev)
2393: {
2394: switch (wdev->iftype) {
2395: case NL80211_IFTYPE_AP:
2396: case NL80211_IFTYPE_P2P_GO:
2397: WARN_ON(wdev->valid_links);
2398: return wdev->links[0].ap.beacon_interval;
2399: case NL80211_IFTYPE_MESH_POINT:
2400: return wdev->u.mesh.beacon_interval;
2401: case NL80211_IFTYPE_ADHOC:
2402: return wdev->u.ibss.beacon_interval;
2403: default:
2404: break;
2405: }
2406:
2407: return 0;
2408: }
SourceFile:net/wireless/util.c]
|
| 56/2 |
2026/06/27 02:07 |
llm |
expert |
0m
Model:
Tokens:
input: 51019
output: 49
thoughts: 349
Thoughts: **Analyzing a Potential NULL Pointer Dereference in mac80211**
Okay, so I'm looking at this bit of code and I think I've spotted a potential issue. If `wdev->iftype` is `NL80211_IFTYPE_P2P_DEVICE`, `cfg80211_wdev_bi` returns 0. That's fine, the `continue` is expected. However, the order of operations here is what's catching my eye. `rdev_get_radio_mask` is called *before* `cfg80211_wdev_bi(wdev)`.
If `wdev->netdev` is NULL, then `rdev_get_radio_mask` will crash if `radio_idx` is >= 0. The subsequent check for `!wdev_bi` would have protected us *if* we'd gotten that far. But we don't. That earlier call to `rdev_get_radio_mask` is the problem.
Now, the question is: when does `radio_idx` become >= 0? The key function to look at is `cfg80211_iter_combinations`, because that's where the `params->radio_idx` variable is being passed into the call to the function containing the suspicious code. So, let me find out who is calling `cfg80211_iter_combinations` with `params->radio_idx >= 0`. To do this, let's trace the execution back from `cfg80211_iter_combinations`.
I'll check `ieee80211_max_num_channels` as a starting point, it's a good place to start my search.
|
| 57/2 |
2026/06/27 02:07 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/mac80211/util.c Name:ieee80211_max_num_channels]
Results: map[SourceCode:4377: int ieee80211_max_num_channels(struct ieee80211_local *local, int radio_idx)
4378: {
4379: u32 max_num_different_channels = 1;
4380: int err;
4381: struct iface_combination_params params = {
4382: .radio_idx = radio_idx,
4383: };
4384:
4385: lockdep_assert_wiphy(local->hw.wiphy);
4386:
4387: ieee80211_fill_ifcomb_params(local, ¶ms, NULL, NULL, NULL, NULL);
4388:
4389: err = cfg80211_iter_combinations(local->hw.wiphy, ¶ms,
4390: ieee80211_iter_max_chans,
4391: &max_num_different_channels);
4392: if (err < 0)
4393: return err;
4394:
4395: return max_num_different_channels;
4396: }
SourceFile:net/mac80211/util.c]
|
| 58/2 |
2026/06/27 02:07 |
llm |
expert |
0m
Model:
Tokens:
input: 52159
output: 52
thoughts: 55
Thoughts: Here's my summary, as though I'm thinking through this process:
**Channel Context Creation and the Maximum Channel Limit**
Okay, so I'm digging into how new channel contexts are handled in mac80211, and I've traced a crucial function call. It looks like `ieee80211_max_num_channels` is being called from within `ieee80211_can_create_new_chanctx`. Specifically, this happens on line 256 of `net/mac80211/chan.c`. So, when the system's trying to instantiate a new channel context, it's checking against a maximum channel count. This makes perfect sense; you can't have an unbounded number of active channels without running into resource constraints, either hardware limits within the radio or software limitations. I'll need to figure out what `ieee80211_max_num_channels` actually *does* and what it's checking against, but this gives me the context I need. This confirms the initial hypothesis to control the creation of channel contexts, especially useful when working with regulatory constraints or multiple radio interfaces. This is an essential check to prevent system instability from excessive channel allocation.
|
| 59/2 |
2026/06/27 02:07 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/mac80211/chan.c Name:ieee80211_can_create_new_chanctx]
Results: map[SourceCode: 250: static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local,
251: int radio_idx)
252: {
253: lockdep_assert_wiphy(local->hw.wiphy);
254:
255: return ieee80211_num_chanctx(local, radio_idx) <
256: ieee80211_max_num_channels(local, radio_idx);
257: }
SourceFile:net/mac80211/chan.c]
|
| 60/2 |
2026/06/27 02:07 |
llm |
expert |
0m
Model:
Tokens:
input: 52721
output: 21
thoughts: 295
Thoughts: **Analyzing a Potential Kernel Crash**
Okay, let's break this down. It looks like a recent bug report highlights a potential crash within the `cfg80211_calculate_bi_data` function. The code says that if `radio_idx` is greater than or equal to zero, a call to `rdev_get_radio_mask` occurs with `wdev->netdev`. My initial thought is that if `wdev->netdev` is NULL, then this call is going to blow up.
The critical question now becomes: is it *possible* to have a `wdev` with a `netdev` pointer that's NULL? The answer, based on my understanding of the relevant structures and types, seems to be yes. I remember that a `NL80211_IFTYPE_P2P_DEVICE` interface has `netdev == NULL`. That seems like a prime suspect.
However, the bug report mentions an IBSS network being created ("wlan0: Created IBSS using preconfigured BSSID..."). This throws a wrench in the gears. If a user is also creating a P2P Device interface, then `wdev->netdev` *would* be NULL, right? Is this the root cause?
But I need to be thorough. Can `wdev->netdev` be NULL for *other* reasons? Let me think... during interface creation or destruction? Quickly checking my knowledge of the relevant code paths, I don't believe so. The P2P Device scenario is the main culprit.
Right, so the central question boils down to: is `wdev->netdev` confirmed to be NULL when handling a P2P Device, and under what specific conditions? I'll need to verify this assumption with more digging, but the P2P Device interface is the prime suspect.
|
| 61/2 |
2026/06/27 02:07 |
tool |
grepper |
0m
Error:
Args: map[Expression:wdev->netdev = NULL]
Results:
|
| 62/2 |
2026/06/27 02:07 |
llm |
expert |
0m
Model:
Tokens:
input: 53444
output: 19
thoughts: 17
Thoughts: Here's a first-person summary, tailored for an expert audience, of the thought process centered around `cfg80211_add_napi`:
**Analyzing `cfg80211_add_napi`**
Okay, let's dive into `cfg80211_add_napi`. My immediate focus is on its role within the broader 802.11 stack. I'm thinking about where this function fits in the interrupt handling and data processing flow, specifically where it interfaces with the Network Abstraction Layer for Interrupts (NAPI). This suggests a critical part of the driver's ability to efficiently receive frames.
I'm mentally mapping the surrounding calls. What are the common entry points that would call this function? `cfg80211_add_napi` must be adding a NAPI instance, presumably a per-device or per-channel context, right? How does this interact with the generic cfg80211 infrastructure? I want to understand the synchronization primitives used here. Are we dealing with spinlocks, mutexes, RCU, or something more specialized? How does it handle race conditions, especially with shared data structures like the `ieee80211_local` structure?
I'm anticipating seeing something that sets up the NAPI poll context. I'll be looking for configuration parameters passed. Am I dealing with a simple addition or perhaps an initialization/registration? Are there flags used to signal the type of operation, or are there different function versions? I need to look for calls to `napi_enable()`, `napi_complete()`, and any other NAPI-related functions within this context. The goal is to ensure that my mental picture of the receive path is complete and accurate. Specifically, I'm thinking about the performance implications of this setup. Latency, interrupt moderation, and potential for lock contention are key considerations in this area.
|
| 63/2 |
2026/06/27 02:07 |
tool |
grepper |
0m
Args: map[Expression:wdev->netdev]
Results: map[Output:
Full output is too long, showing 500 out of 1275 lines.
Use more precise expression if possible.
drivers/infiniband/hw/irdma/cm.c=1656=static int irdma_add_mqh_6(struct irdma_device *iwdev,
--
drivers/infiniband/hw/irdma/cm.c-1672- if (((rdma_vlan_dev_vlan_id(ip_dev) >= VLAN_N_VID) ||
drivers/infiniband/hw/irdma/cm.c:1673: (rdma_vlan_dev_real_dev(ip_dev) != iwdev->netdev)) &&
drivers/infiniband/hw/irdma/cm.c:1674: ip_dev != iwdev->netdev)
drivers/infiniband/hw/irdma/cm.c-1675- continue;
--
drivers/infiniband/hw/irdma/cm.c=1744=static int irdma_add_mqh_4(struct irdma_device *iwdev,
--
drivers/infiniband/hw/irdma/cm.c-1760- if (((rdma_vlan_dev_vlan_id(ip_dev) >= VLAN_N_VID) ||
drivers/infiniband/hw/irdma/cm.c:1761: (rdma_vlan_dev_real_dev(ip_dev) != iwdev->netdev)) &&
drivers/infiniband/hw/irdma/cm.c:1762: ip_dev != iwdev->netdev)
drivers/infiniband/hw/irdma/cm.c-1763- continue;
--
drivers/infiniband/hw/irdma/cm.c=2170=static int irdma_cm_create_ah(struct irdma_cm_node *cm_node, bool wait)
--
drivers/infiniband/hw/irdma/cm.c-2174-
drivers/infiniband/hw/irdma/cm.c:2175: ether_addr_copy(ah_info.mac_addr, iwdev->netdev->dev_addr);
drivers/infiniband/hw/irdma/cm.c-2176-
--
drivers/infiniband/hw/irdma/cm.c=2236=irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev,
--
drivers/infiniband/hw/irdma/cm.c-2242- int arpindex;
drivers/infiniband/hw/irdma/cm.c:2243: struct net_device *netdev = iwdev->netdev;
drivers/infiniband/hw/irdma/cm.c-2244- int ret;
--
drivers/infiniband/hw/irdma/hw.c=1199=static int irdma_alloc_set_mac(struct irdma_device *iwdev)
--
drivers/infiniband/hw/irdma/hw.c-1206- status = irdma_add_local_mac_entry(iwdev->rf,
drivers/infiniband/hw/irdma/hw.c:1207: (const u8 *)iwdev->netdev->dev_addr,
drivers/infiniband/hw/irdma/hw.c-1208- (u8)iwdev->mac_ip_table_idx);
--
drivers/infiniband/hw/irdma/hw.c=2600=int irdma_manage_qhash(struct irdma_device *iwdev, struct irdma_cm_info *cminfo,
--
drivers/infiniband/hw/irdma/hw.c-2628- info->user_pri = cminfo->user_pri;
drivers/infiniband/hw/irdma/hw.c:2629: ether_addr_copy(info->mac_addr, iwdev->netdev->dev_addr);
drivers/infiniband/hw/irdma/hw.c-2630- info->qp_num = cminfo->qh_qpid;
--
drivers/infiniband/hw/irdma/i40iw_if.c=73=static void i40iw_fill_device_info(struct irdma_device *iwdev, struct i40e_info *cdev_info)
--
drivers/infiniband/hw/irdma/i40iw_if.c-94- iwdev->rcv_wscale = IRDMA_CM_DEFAULT_RCV_WND_SCALE;
drivers/infiniband/hw/irdma/i40iw_if.c:95: iwdev->netdev = cdev_info->netdev;
drivers/infiniband/hw/irdma/i40iw_if.c-96- iwdev->vsi_num = 0;
--
drivers/infiniband/hw/irdma/icrdma_if.c=44=static void icrdma_iidc_event_handler(struct iidc_rdma_core_dev_info *cdev_info,
--
drivers/infiniband/hw/irdma/icrdma_if.c-50- if (*event->type & BIT(IIDC_RDMA_EVENT_AFTER_MTU_CHANGE)) {
drivers/infiniband/hw/irdma/icrdma_if.c:51: ibdev_dbg(&iwdev->ibdev, "CLNT: new MTU = %d\n", iwdev->netdev->mtu);
drivers/infiniband/hw/irdma/icrdma_if.c:52: if (iwdev->vsi.mtu != iwdev->netdev->mtu) {
drivers/infiniband/hw/irdma/icrdma_if.c:53: l2params.mtu = iwdev->netdev->mtu;
drivers/infiniband/hw/irdma/icrdma_if.c-54- l2params.mtu_changed = true;
--
drivers/infiniband/hw/irdma/icrdma_if.c=201=static void icrdma_fill_device_info(struct irdma_device *iwdev,
--
drivers/infiniband/hw/irdma/icrdma_if.c-231-
drivers/infiniband/hw/irdma/icrdma_if.c:232: iwdev->netdev = idc_priv->netdev;
drivers/infiniband/hw/irdma/icrdma_if.c-233- iwdev->vsi_num = idc_priv->vport_id;
--
drivers/infiniband/hw/irdma/icrdma_if.c=243=static int icrdma_probe(struct auxiliary_device *aux_dev, const struct auxiliary_device_id *id)
--
drivers/infiniband/hw/irdma/icrdma_if.c-276-
drivers/infiniband/hw/irdma/icrdma_if.c:277: l2params.mtu = iwdev->netdev->mtu;
drivers/infiniband/hw/irdma/icrdma_if.c-278- icrdma_fill_qos_info(&l2params, &idc_priv->qos_info);
--
drivers/infiniband/hw/irdma/main.c=50=static void ig3rdma_idc_vport_event_handler(struct iidc_rdma_vport_dev_info *cdev_info,
--
drivers/infiniband/hw/irdma/main.c-56- if (*event->type & BIT(IIDC_RDMA_EVENT_AFTER_MTU_CHANGE)) {
drivers/infiniband/hw/irdma/main.c:57: ibdev_dbg(&iwdev->ibdev, "CLNT: new MTU = %d\n", iwdev->netdev->mtu);
drivers/infiniband/hw/irdma/main.c:58: if (iwdev->vsi.mtu != iwdev->netdev->mtu) {
drivers/infiniband/hw/irdma/main.c:59: l2params.mtu = iwdev->netdev->mtu;
drivers/infiniband/hw/irdma/main.c-60- l2params.mtu_changed = true;
--
drivers/infiniband/hw/irdma/main.c=67=static int ig3rdma_vport_probe(struct auxiliary_device *aux_dev,
--
drivers/infiniband/hw/irdma/main.c-86- iwdev->vport_id = idc_adev->vdev_info->vport_id;
drivers/infiniband/hw/irdma/main.c:87: iwdev->netdev = idc_adev->vdev_info->netdev;
drivers/infiniband/hw/irdma/main.c-88- iwdev->init_state = INITIAL_STATE;
--
drivers/infiniband/hw/irdma/main.c-95-
drivers/infiniband/hw/irdma/main.c:96: l2params.mtu = iwdev->netdev->mtu;
drivers/infiniband/hw/irdma/main.c-97-
--
drivers/infiniband/hw/irdma/utils.c=250=int irdma_net_event(struct notifier_block *notifier, unsigned long event,
--
drivers/infiniband/hw/irdma/utils.c-281- "DEV: netdev %p state %d local_ip=%pI4 MAC=%pM\n",
drivers/infiniband/hw/irdma/utils.c:282: iwdev->netdev, neigh->nud_state, local_ipaddr,
drivers/infiniband/hw/irdma/utils.c-283- neigh->ha);
--
drivers/infiniband/hw/irdma/utils.c=336=static void irdma_add_ipv6_addr(struct irdma_device *iwdev)
--
drivers/infiniband/hw/irdma/utils.c-345- if (((rdma_vlan_dev_vlan_id(ip_dev) < 0xFFFF &&
drivers/infiniband/hw/irdma/utils.c:346: rdma_vlan_dev_real_dev(ip_dev) == iwdev->netdev) ||
drivers/infiniband/hw/irdma/utils.c:347: ip_dev == iwdev->netdev) &&
drivers/infiniband/hw/irdma/utils.c-348- (READ_ONCE(ip_dev->flags) & IFF_UP)) {
--
drivers/infiniband/hw/irdma/utils.c=378=static void irdma_add_ipv4_addr(struct irdma_device *iwdev)
--
drivers/infiniband/hw/irdma/utils.c-386- if (((rdma_vlan_dev_vlan_id(dev) < 0xFFFF &&
drivers/infiniband/hw/irdma/utils.c:387: rdma_vlan_dev_real_dev(dev) == iwdev->netdev) ||
drivers/infiniband/hw/irdma/utils.c:388: dev == iwdev->netdev) && (READ_ONCE(dev->flags) & IFF_UP)) {
drivers/infiniband/hw/irdma/utils.c-389- const struct in_ifaddr *ifa;
--
drivers/infiniband/hw/irdma/verbs.c=11=static int irdma_query_device(struct ib_device *ibdev,
--
drivers/infiniband/hw/irdma/verbs.c-24- addrconf_addr_eui48((u8 *)&props->sys_image_guid,
drivers/infiniband/hw/irdma/verbs.c:25: iwdev->netdev->dev_addr);
drivers/infiniband/hw/irdma/verbs.c-26- props->fw_ver = (u64)irdma_fw_major_ver(&rf->sc_dev) << 32 |
--
drivers/infiniband/hw/irdma/verbs.c=86=static int irdma_query_port(struct ib_device *ibdev, u32 port,
--
drivers/infiniband/hw/irdma/verbs.c-89- struct irdma_device *iwdev = to_iwdev(ibdev);
drivers/infiniband/hw/irdma/verbs.c:90: struct net_device *netdev = iwdev->netdev;
drivers/infiniband/hw/irdma/verbs.c-91-
--
drivers/infiniband/hw/irdma/verbs.c=792=static void irdma_roce_fill_and_set_qpctx_info(struct irdma_qp *iwqp,
--
drivers/infiniband/hw/irdma/verbs.c-807- roce_info = &iwqp->roce_info;
drivers/infiniband/hw/irdma/verbs.c:808: ether_addr_copy(roce_info->mac_addr, iwdev->netdev->dev_addr);
drivers/infiniband/hw/irdma/verbs.c-809-
--
drivers/infiniband/hw/irdma/verbs.c=835=static void irdma_iw_fill_and_set_qpctx_info(struct irdma_qp *iwqp,
--
drivers/infiniband/hw/irdma/verbs.c-842- iwarp_info = &iwqp->iwarp_info;
drivers/infiniband/hw/irdma/verbs.c:843: ether_addr_copy(iwarp_info->mac_addr, iwdev->netdev->dev_addr);
drivers/infiniband/hw/irdma/verbs.c-844- iwarp_info->rd_en = true;
--
drivers/infiniband/hw/irdma/verbs.c=4774=static int irdma_query_gid(struct ib_device *ibdev, u32 port, int index,
--
drivers/infiniband/hw/irdma/verbs.c-4779- memset(gid->raw, 0, sizeof(gid->raw));
drivers/infiniband/hw/irdma/verbs.c:4780: ether_addr_copy(gid->raw, iwdev->netdev->dev_addr);
drivers/infiniband/hw/irdma/verbs.c-4781-
--
drivers/infiniband/hw/irdma/verbs.c=5486=static void irdma_init_roce_device(struct irdma_device *iwdev)
--
drivers/infiniband/hw/irdma/verbs.c-5489- addrconf_addr_eui48((u8 *)&iwdev->ibdev.node_guid,
drivers/infiniband/hw/irdma/verbs.c:5490: iwdev->netdev->dev_addr);
drivers/infiniband/hw/irdma/verbs.c-5491- ib_set_device_ops(&iwdev->ibdev, &irdma_roce_dev_ops);
--
drivers/infiniband/hw/irdma/verbs.c=5498=static void irdma_init_iw_device(struct irdma_device *iwdev)
drivers/infiniband/hw/irdma/verbs.c-5499-{
drivers/infiniband/hw/irdma/verbs.c:5500: struct net_device *netdev = iwdev->netdev;
drivers/infiniband/hw/irdma/verbs.c-5501-
--
drivers/infiniband/hw/irdma/verbs.c=5564=int irdma_ib_register_device(struct irdma_device *iwdev)
--
drivers/infiniband/hw/irdma/verbs.c-5569-
drivers/infiniband/hw/irdma/verbs.c:5570: ret = ib_device_set_netdev(&iwdev->ibdev, iwdev->netdev, 1);
drivers/infiniband/hw/irdma/verbs.c-5571- if (ret)
--
drivers/net/wireless/ath/ath6kl/cfg80211.c=1127=static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/ath/ath6kl/cfg80211.c-1131-{
drivers/net/wireless/ath/ath6kl/cfg80211.c:1132: struct ath6kl *ar = ath6kl_priv(wdev->netdev);
drivers/net/wireless/ath/ath6kl/cfg80211.c:1133: struct ath6kl_vif *vif = netdev_priv(wdev->netdev);
drivers/net/wireless/ath/ath6kl/cfg80211.c-1134- struct ath6kl_key *key = NULL;
--
drivers/net/wireless/ath/ath6kl/cfg80211.c=1252=static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/ath/ath6kl/cfg80211.c-1255-{
drivers/net/wireless/ath/ath6kl/cfg80211.c:1256: struct ath6kl *ar = ath6kl_priv(wdev->netdev);
drivers/net/wireless/ath/ath6kl/cfg80211.c:1257: struct ath6kl_vif *vif = netdev_priv(wdev->netdev);
drivers/net/wireless/ath/ath6kl/cfg80211.c-1258-
--
drivers/net/wireless/ath/ath6kl/cfg80211.c=1282=static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/ath/ath6kl/cfg80211.c-1287-{
drivers/net/wireless/ath/ath6kl/cfg80211.c:1288: struct ath6kl_vif *vif = netdev_priv(wdev->netdev);
drivers/net/wireless/ath/ath6kl/cfg80211.c-1289- struct ath6kl_key *key = NULL;
--
drivers/net/wireless/ath/ath6kl/cfg80211.c=1542=static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
--
drivers/net/wireless/ath/ath6kl/cfg80211.c-1545- struct ath6kl *ar = wiphy_priv(wiphy);
drivers/net/wireless/ath/ath6kl/cfg80211.c:1546: struct ath6kl_vif *vif = netdev_priv(wdev->netdev);
drivers/net/wireless/ath/ath6kl/cfg80211.c-1547-
--
drivers/net/wireless/ath/ath6kl/cfg80211.c=1779=static int ath6kl_get_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/ath/ath6kl/cfg80211.c-1781-{
drivers/net/wireless/ath/ath6kl/cfg80211.c:1782: struct net_device *dev = wdev->netdev;
drivers/net/wireless/ath/ath6kl/cfg80211.c-1783- struct ath6kl *ar = ath6kl_priv(dev);
--
drivers/net/wireless/ath/ath6kl/cfg80211.c=2997=static int ath6kl_del_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/ath/ath6kl/cfg80211.c-2999-{
drivers/net/wireless/ath/ath6kl/cfg80211.c:3000: struct net_device *dev = wdev->netdev;
drivers/net/wireless/ath/ath6kl/cfg80211.c-3001- struct ath6kl *ar = ath6kl_priv(dev);
--
drivers/net/wireless/ath/ath6kl/cfg80211.c=3009=static int ath6kl_change_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/ath/ath6kl/cfg80211.c-3012-{
drivers/net/wireless/ath/ath6kl/cfg80211.c:3013: struct net_device *dev = wdev->netdev;
drivers/net/wireless/ath/ath6kl/cfg80211.c-3014- struct ath6kl *ar = ath6kl_priv(dev);
--
drivers/net/wireless/ath/ath6kl/core.c=66=int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
--
drivers/net/wireless/ath/ath6kl/core.c-231- ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
drivers/net/wireless/ath/ath6kl/core.c:232: __func__, wdev->netdev->name, wdev->netdev, ar);
drivers/net/wireless/ath/ath6kl/core.c-233-
--
drivers/net/wireless/ath/wil6210/netdev.c=299=wil_vif_alloc(struct wil6210_priv *wil, const char *name,
--
drivers/net/wireless/ath/wil6210/netdev.c-344- SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
drivers/net/wireless/ath/wil6210/netdev.c:345: wdev->netdev = ndev;
drivers/net/wireless/ath/wil6210/netdev.c-346- return vif;
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=963=static int brcmf_mon_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-965- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:966: struct net_device *ndev = wdev->netdev;
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-967-
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=1263=static int brcmf_cfg80211_del_apsta_iface(struct wiphy *wiphy,
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-1266- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:1267: struct net_device *ndev = wdev->netdev;
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-1268- struct brcmf_if *ifp = netdev_priv(ndev);
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=1298=int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-1300- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:1301: struct net_device *ndev = wdev->netdev;
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-1302-
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=2761=brcmf_cfg80211_del_key(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-2764-{
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:2765: struct brcmf_if *ifp = netdev_priv(wdev->netdev);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-2766- struct brcmf_wsec_key *key;
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=2799=brcmf_cfg80211_add_key(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-2803- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:2804: struct brcmf_if *ifp = netdev_priv(wdev->netdev);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-2805- struct brcmf_pub *drvr = cfg->pub;
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=2921=brcmf_cfg80211_get_key(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-2928- struct key_params params;
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:2929: struct brcmf_if *ifp = netdev_priv(wdev->netdev);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-2930- struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=2978=brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-2981-{
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:2982: struct brcmf_if *ifp = netdev_priv(wdev->netdev);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-2983-
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=3135=brcmf_cfg80211_get_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-3138- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:3139: struct brcmf_if *ifp = netdev_priv(wdev->netdev);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-3140- struct brcmf_pub *drvr = cfg->pub;
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=3258=brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-3261- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:3262: struct brcmf_if *ifp = netdev_priv(wdev->netdev);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-3263- struct brcmf_pub *drvr = cfg->pub;
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=5456=brcmf_cfg80211_del_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-5461- struct brcmf_scb_val_le scbval;
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:5462: struct net_device *ndev = wdev->netdev;
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-5463- struct brcmf_if *ifp = netdev_priv(ndev);
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=5489=brcmf_cfg80211_change_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-5493- struct brcmf_pub *drvr = cfg->pub;
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:5494: struct brcmf_if *ifp = netdev_priv(wdev->netdev);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-5495- s32 err;
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=5714=static int brcmf_cfg80211_get_channel(struct wiphy *wiphy,
--
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-5719- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:5720: struct net_device *ndev = wdev->netdev;
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-5721- struct brcmf_pub *drvr = cfg->pub;
--
drivers/net/wireless/intel/iwlwifi/mld/rx.c=1809=static int iwl_mld_rx_mgmt_prot(struct ieee80211_sta *sta,
--
drivers/net/wireless/intel/iwlwifi/mld/rx.c-1899- wdev = ieee80211_vif_to_wdev(mld_sta->vif);
drivers/net/wireless/intel/iwlwifi/mld/rx.c:1900: if (wdev->netdev)
drivers/net/wireless/intel/iwlwifi/mld/rx.c:1901: cfg80211_rx_unprot_mlme_mgmt(wdev->netdev, (void *)hdr,
drivers/net/wireless/intel/iwlwifi/mld/rx.c-1902- mpdu_len);
--
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c=322=static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
--
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c-407- wdev = ieee80211_vif_to_wdev(mvmsta->vif);
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c:408: if (wdev->netdev)
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c:409: cfg80211_rx_unprot_mlme_mgmt(wdev->netdev, (void *)hdr, len);
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c-410-
--
drivers/net/wireless/marvell/libertas/cfg.c=1510=static int lbs_cfg_add_key(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/marvell/libertas/cfg.c-1518-
drivers/net/wireless/marvell/libertas/cfg.c:1519: if (wdev->netdev == priv->mesh_dev)
drivers/net/wireless/marvell/libertas/cfg.c-1520- return -EOPNOTSUPP;
--
drivers/net/wireless/marvell/libertas/main.c=823=struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
--
drivers/net/wireless/marvell/libertas/main.c-857- SET_NETDEV_DEV(dev, dmdev);
drivers/net/wireless/marvell/libertas/main.c:858: wdev->netdev = dev;
drivers/net/wireless/marvell/libertas/main.c-859- priv->dev = dev;
--
drivers/net/wireless/marvell/libertas/mesh.c=979=static int lbs_add_mesh(struct lbs_private *priv)
--
drivers/net/wireless/marvell/libertas/mesh.c-1007-
drivers/net/wireless/marvell/libertas/mesh.c:1008: mesh_wdev->netdev = mesh_dev;
drivers/net/wireless/marvell/libertas/mesh.c-1009-
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=144=mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-147-{
drivers/net/wireless/marvell/mwifiex/cfg80211.c:148: struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-149- static const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=198=mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-206- struct mwifiex_txinfo *tx_info;
drivers/net/wireless/marvell/mwifiex/cfg80211.c:207: struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-208-
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=282=mwifiex_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-285-{
drivers/net/wireless/marvell/mwifiex/cfg80211.c:286: struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-287- u32 mask = upd->interface_stypes;
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=304=mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-309-{
drivers/net/wireless/marvell/mwifiex/cfg80211.c:310: struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-311- int ret;
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=347=mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-349-{
drivers/net/wireless/marvell/mwifiex/cfg80211.c:350: struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-351- int ret;
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=484=mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-487-{
drivers/net/wireless/marvell/mwifiex/cfg80211.c:488: struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-489- struct mwifiex_wep_key *wep_key;
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=521=mwifiex_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-525-{
drivers/net/wireless/marvell/mwifiex/cfg80211.c:526: struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-527- struct mwifiex_ds_encrypt_key encrypt_key;
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=1558=mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-1560-{
drivers/net/wireless/marvell/mwifiex/cfg80211.c:1561: struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-1562-
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=1575=mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-1577-{
drivers/net/wireless/marvell/mwifiex/cfg80211.c:1578: struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-1579- struct mwifiex_sta_node *node;
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=1905=mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-1908- struct mwifiex_private *priv =
drivers/net/wireless/marvell/mwifiex/cfg80211.c:1909: mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-1910- struct mwifiex_sta_node *sta_node;
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=2659=mwifiex_cfg80211_scan(struct wiphy *wiphy,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-2661-{
drivers/net/wireless/marvell/mwifiex/cfg80211.c:2662: struct net_device *dev = request->wdev->netdev;
drivers/net/wireless/marvell/mwifiex/cfg80211.c-2663- struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=3223=int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
drivers/net/wireless/marvell/mwifiex/cfg80211.c-3224-{
drivers/net/wireless/marvell/mwifiex/cfg80211.c:3225: struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-3226- struct mwifiex_adapter *adapter = priv->adapter;
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-3245-
drivers/net/wireless/marvell/mwifiex/cfg80211.c:3246: if (wdev->netdev->reg_state == NETREG_REGISTERED)
drivers/net/wireless/marvell/mwifiex/cfg80211.c:3247: cfg80211_unregister_netdevice(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-3248-
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=4007=mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-4009-{
drivers/net/wireless/marvell/mwifiex/cfg80211.c:4010: struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-4011-
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=4084=static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-4088-{
drivers/net/wireless/marvell/mwifiex/cfg80211.c:4089: struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-4090- struct mwifiex_bssdescriptor *curr_bss;
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=4142=static int mwifiex_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-4144-{
drivers/net/wireless/marvell/mwifiex/cfg80211.c:4145: struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-4146- struct mwifiex_ds_misc_cmd *hostcmd;
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c=4246=mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/marvell/mwifiex/cfg80211.c-4250- int ret;
drivers/net/wireless/marvell/mwifiex/cfg80211.c:4251: struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
drivers/net/wireless/marvell/mwifiex/cfg80211.c-4252-
--
drivers/net/wireless/mediatek/mt76/mt7915/mac.c=236=mt7915_wed_check_ppe(struct mt7915_dev *dev, struct mt76_queue *q,
--
drivers/net/wireless/mediatek/mt76/mt7915/mac.c-254- wdev = ieee80211_vif_to_wdev(vif);
drivers/net/wireless/mediatek/mt76/mt7915/mac.c:255: skb->dev = wdev->netdev;
drivers/net/wireless/mediatek/mt76/mt7915/mac.c-256-
--
drivers/net/wireless/mediatek/mt76/mt7996/mac.c=384=mt7996_wed_check_ppe(struct mt7996_dev *dev, struct mt76_queue *q,
--
drivers/net/wireless/mediatek/mt76/mt7996/mac.c-402- wdev = ieee80211_vif_to_wdev(vif);
drivers/net/wireless/mediatek/mt76/mt7996/mac.c:403: skb->dev = wdev->netdev;
drivers/net/wireless/mediatek/mt76/mt7996/mac.c-404-
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c=261=static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
drivers/net/wireless/microchip/wilc1000/cfg80211.c-262-{
drivers/net/wireless/microchip/wilc1000/cfg80211.c:263: struct wilc_vif *vif = netdev_priv(request->wdev->netdev);
drivers/net/wireless/microchip/wilc1000/cfg80211.c-264- struct wilc_priv *priv = &vif->priv;
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c=537=static int add_key(struct wiphy *wiphy, struct wireless_dev *wdev, int link_id,
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c-546- u8 op_mode;
drivers/net/wireless/microchip/wilc1000/cfg80211.c:547: struct wilc_vif *vif = netdev_priv(wdev->netdev);
drivers/net/wireless/microchip/wilc1000/cfg80211.c-548- struct wilc_priv *priv = &vif->priv;
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c-634- default:
drivers/net/wireless/microchip/wilc1000/cfg80211.c:635: netdev_err(wdev->netdev, "%s: Unsupported cipher\n", __func__);
drivers/net/wireless/microchip/wilc1000/cfg80211.c-636- ret = -ENOTSUPP;
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c=642=static int del_key(struct wiphy *wiphy, struct wireless_dev *wdev, int link_id,
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c-646-{
drivers/net/wireless/microchip/wilc1000/cfg80211.c:647: struct wilc_vif *vif = netdev_priv(wdev->netdev);
drivers/net/wireless/microchip/wilc1000/cfg80211.c-648- struct wilc_priv *priv = &vif->priv;
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c=683=static int get_key(struct wiphy *wiphy, struct wireless_dev *wdev, int link_id,
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c-687-{
drivers/net/wireless/microchip/wilc1000/cfg80211.c:688: struct wilc_vif *vif = netdev_priv(wdev->netdev);
drivers/net/wireless/microchip/wilc1000/cfg80211.c-689- struct wilc_priv *priv = &vif->priv;
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c=728=static int set_default_mgmt_key(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c-730-{
drivers/net/wireless/microchip/wilc1000/cfg80211.c:731: struct wilc_vif *vif = netdev_priv(wdev->netdev);
drivers/net/wireless/microchip/wilc1000/cfg80211.c-732-
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c=736=static int get_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c-738-{
drivers/net/wireless/microchip/wilc1000/cfg80211.c:739: struct net_device *dev = wdev->netdev;
drivers/net/wireless/microchip/wilc1000/cfg80211.c-740- struct wilc_vif *vif = netdev_priv(dev);
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c=1100=static int remain_on_channel(struct wiphy *wiphy,
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c-1106- int ret = 0;
drivers/net/wireless/microchip/wilc1000/cfg80211.c:1107: struct wilc_vif *vif = netdev_priv(wdev->netdev);
drivers/net/wireless/microchip/wilc1000/cfg80211.c-1108- struct wilc_priv *priv = &vif->priv;
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c=1140=static int cancel_remain_on_channel(struct wiphy *wiphy,
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c-1143-{
drivers/net/wireless/microchip/wilc1000/cfg80211.c:1144: struct wilc_vif *vif = netdev_priv(wdev->netdev);
drivers/net/wireless/microchip/wilc1000/cfg80211.c-1145- struct wilc_priv *priv = &vif->priv;
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c=1153=static int mgmt_tx(struct wiphy *wiphy,
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c-1163- struct wilc_p2p_mgmt_data *mgmt_tx;
drivers/net/wireless/microchip/wilc1000/cfg80211.c:1164: struct wilc_vif *vif = netdev_priv(wdev->netdev);
drivers/net/wireless/microchip/wilc1000/cfg80211.c-1165- struct wilc_priv *priv = &vif->priv;
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c-1233-
drivers/net/wireless/microchip/wilc1000/cfg80211.c:1234: wilc_wlan_txq_add_mgmt_pkt(wdev->netdev, mgmt_tx,
drivers/net/wireless/microchip/wilc1000/cfg80211.c-1235- mgmt_tx->buff, mgmt_tx->size,
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c=1243=static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c-1246-{
drivers/net/wireless/microchip/wilc1000/cfg80211.c:1247: struct wilc_vif *vif = netdev_priv(wdev->netdev);
drivers/net/wireless/microchip/wilc1000/cfg80211.c-1248- struct wilc_priv *priv = &vif->priv;
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c=1267=void wilc_update_mgmt_frame_registrations(struct wiphy *wiphy,
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c-1271- struct wilc *wl = wiphy_priv(wiphy);
drivers/net/wireless/microchip/wilc1000/cfg80211.c:1272: struct wilc_vif *vif = netdev_priv(wdev->netdev);
drivers/net/wireless/microchip/wilc1000/cfg80211.c-1273- u32 presp_bit = BIT(IEEE80211_STYPE_PROBE_REQ >> 4);
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c=1317=static int dump_station(struct wiphy *wiphy, struct wireless_dev *wdev,
--
drivers/net/wireless/microchip/wilc1000/cfg80211.c-1319-{
drivers/net/wireless/microchip/wilc1000/cfg80211.c:1320: struct wilc_vif *vif = netdev_priv(wdev->netdev);
drivers/net/wireless/microchip/wilc1000/cfg80211.c-1321- int ret;
--
]
|
| 64/2 |
2026/06/27 02:07 |
llm |
expert |
0m
Model:
Tokens:
input: 69293
output: 44
thoughts: 1094
Thoughts: **Vulnerability Analysis: NULL Pointer Dereference in mac80211**
Okay, so I've been digging into this potential vulnerability, and here's what I've got so far. It looks like a NULL pointer dereference can occur within the `mac80211` wireless networking stack, specifically when dealing with `NL80211_IFTYPE_P2P_DEVICE` interfaces. The core issue seems to be that `wdev->netdev` can be NULL in this interface type.
If `wdev->netdev` is indeed NULL, the `rdev_get_radio_mask` function is called, which in turn calls a driver-specific `get_radio_mask` function. In the `mac80211` implementation, `ieee80211_get_radio_mask` is called with `dev = NULL`. This is where it gets interesting, as this then calls `IEEE80211_DEV_TO_SUB_IF(dev)`, which returns `netdev_priv(dev)`. Since the `dev` is NULL, this function gives the address of a control block, `0xec0`, for example. From there, `__ieee80211_get_radio_mask` attempts to access `sdata->vif` (at `0x2cd0`), which is likely an offset from that invalid base address, and then it goes on to access `vif->active_links` (at `0x34fa`). This sequence leads to a classic NULL pointer dereference, causing a kernel crash.
The critical question now is: can this be triggered by an unprivileged user? My initial thoughts went to user namespaces, as I know that `CAP_NET_ADMIN` can be granted within them. I can create a new net namespace and then a user namespace to achieve this. However, it looks like `mac80211` devices are usually in the init net namespace. I started thinking about whether an unprivileged user can move a wifi device into a new net namespace but remembered that that would also require `CAP_NET_ADMIN` in the init net namespace, which is not what we want. The same is true for `mac80211_hwsim`, where the capability requirement is also needed.
So I went back and considered what might happen when a P2P Device is created. Creating a P2P Device via `nl80211` *also* requires `CAP_NET_ADMIN` in the net namespace where the wiphy resides. This, too, looks like it's inaccessible to unprivileged processes or those within user namespaces, unless root had moved the wiphy into the user namespace, which is the exact opposite of what we're looking for.
I decided to double-check whether `cfg80211` allowed unprivileged users to create interfaces, but no, the `nl80211_new_interface` function requires `GENL_ADMIN_PERM`, which checks for `netlink_capable(skb, CAP_NET_ADMIN)`. Again, the need for `CAP_NET_ADMIN` is a roadblock.
Now, I was looking for other ways to reach the vulnerable code path. I thought of whether any other code paths could lead to `cfg80211_calculate_bi_data`, and started looking at its call graph. It's called from `cfg80211_iter_combinations`, which is in turn called from a few other functions, `ieee80211_max_num_channels`, `ieee80211_check_combinations_ext`, `cfg80211_check_combinations`, and `cfg80211_update_iface_num`.
Could a remote attacker, perhaps via a maliciously crafted management frame, trigger the creation of a new channel context? But no, channel contexts are created on join or AP start. The vulnerability's stack trace includes `__ieee80211_sta_join_ibss`, which is triggered by `NL80211_CMD_JOIN_IBSS`, *again* requiring `CAP_NET_ADMIN`.
What if the device is *already* in a vulnerable state, say, IBSS mode? Would a malicious beacon or probe response trigger the vulnerability? No. `__ieee80211_sta_join_ibss` comes from `ieee80211_ibss_work`, which is a workqueue scheduled on user request, when the user requests to join an IBSS. The device is not vulnerable to remote attack.
But... here's a thought: What if the user sets up the device to join an
|
| 65/2 |
2026/06/27 02:08 |
tool |
codesearch-definition-source |
0m
Error:
Args: map[ContextFile:net/wireless/core.c Name:cfg80211_del_virtual_intf]
Results: map[SourceCode: SourceFile:]
|
| 66/2 |
2026/06/27 02:08 |
llm |
expert |
0m
Model:
Tokens:
input: 71477
output: 21
thoughts: 14
Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience:
**Debugging Network Interface Initialization**
Alright, so the core of the issue likely revolves around the network device initialization, and it's looking like `wdev->netdev` might not be getting set correctly, or it's getting clobbered somewhere. Let's start with a focused grep. I'll search for every instance where `wdev->netdev` is explicitly assigned or, crucially, *assigned to NULL*. This seems like the most direct route to pinpointing the culprit. It could be an early initialization issue, a race condition, or a simple oversight somewhere in the device driver's setup sequence. This `grep` is going to be my first line of attack. I'm hoping it'll highlight the specific lines of code that are touching this particular pointer and then I'll be able to quickly determine the most likely cause.
|
| 67/2 |
2026/06/27 02:08 |
tool |
grepper |
0m
Error:
Args: map[Expression:wdev->netdev = NULL]
Results:
|
| 68/2 |
2026/06/27 02:08 |
llm |
expert |
0m
Model:
Tokens:
input: 71721
output: 21
thoughts: 13
Thoughts: Here's my thought process, as requested:
**Deconstructing a Network Device Assignment**
Okay, so I need to understand how a network device is being assigned within this code. My immediate thought is to use `grep` to quickly pinpoint the crucial line(s) where the assignment happens. I'll search for `wdev->netdev = `. That exact phrase is key because it clearly indicates that the `netdev` member of something named `wdev` is being assigned a value. The assignment is the action I need to find to understand the flow. Using `grep` will quickly identify all instances, which should help me to understand all the other factors involved in the assignment. Hopefully this approach will get me to the source code very fast, since I know exactly what I'm looking for. Let's see what pops up!
|
| 69/2 |
2026/06/27 02:08 |
tool |
grepper |
0m
Args: map[Expression:wdev->netdev = ]
Results: map[Output:drivers/infiniband/hw/irdma/i40iw_if.c=73=static void i40iw_fill_device_info(struct irdma_device *iwdev, struct i40e_info *cdev_info)
--
drivers/infiniband/hw/irdma/i40iw_if.c-94- iwdev->rcv_wscale = IRDMA_CM_DEFAULT_RCV_WND_SCALE;
drivers/infiniband/hw/irdma/i40iw_if.c:95: iwdev->netdev = cdev_info->netdev;
drivers/infiniband/hw/irdma/i40iw_if.c-96- iwdev->vsi_num = 0;
--
drivers/infiniband/hw/irdma/icrdma_if.c=201=static void icrdma_fill_device_info(struct irdma_device *iwdev,
--
drivers/infiniband/hw/irdma/icrdma_if.c-231-
drivers/infiniband/hw/irdma/icrdma_if.c:232: iwdev->netdev = idc_priv->netdev;
drivers/infiniband/hw/irdma/icrdma_if.c-233- iwdev->vsi_num = idc_priv->vport_id;
--
drivers/infiniband/hw/irdma/main.c=67=static int ig3rdma_vport_probe(struct auxiliary_device *aux_dev,
--
drivers/infiniband/hw/irdma/main.c-86- iwdev->vport_id = idc_adev->vdev_info->vport_id;
drivers/infiniband/hw/irdma/main.c:87: iwdev->netdev = idc_adev->vdev_info->netdev;
drivers/infiniband/hw/irdma/main.c-88- iwdev->init_state = INITIAL_STATE;
--
drivers/net/wireless/ath/wil6210/netdev.c=299=wil_vif_alloc(struct wil6210_priv *wil, const char *name,
--
drivers/net/wireless/ath/wil6210/netdev.c-344- SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
drivers/net/wireless/ath/wil6210/netdev.c:345: wdev->netdev = ndev;
drivers/net/wireless/ath/wil6210/netdev.c-346- return vif;
--
drivers/net/wireless/marvell/libertas/main.c=823=struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
--
drivers/net/wireless/marvell/libertas/main.c-857- SET_NETDEV_DEV(dev, dmdev);
drivers/net/wireless/marvell/libertas/main.c:858: wdev->netdev = dev;
drivers/net/wireless/marvell/libertas/main.c-859- priv->dev = dev;
--
drivers/net/wireless/marvell/libertas/mesh.c=979=static int lbs_add_mesh(struct lbs_private *priv)
--
drivers/net/wireless/marvell/libertas/mesh.c-1007-
drivers/net/wireless/marvell/libertas/mesh.c:1008: mesh_wdev->netdev = mesh_dev;
drivers/net/wireless/marvell/libertas/mesh.c-1009-
--
drivers/net/wireless/realtek/rtw89/core.c=4544=int rtw89_core_napi_init(struct rtw89_dev *rtwdev)
drivers/net/wireless/realtek/rtw89/core.c-4545-{
drivers/net/wireless/realtek/rtw89/core.c:4546: rtwdev->netdev = alloc_netdev_dummy(0);
drivers/net/wireless/realtek/rtw89/core.c-4547- if (!rtwdev->netdev)
--
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c=2112=static int rtw_cfg80211_add_monitor_if(struct adapter *padapter, char *name, struct net_device **ndev)
--
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c-2154- mon_wdev->wiphy = padapter->rtw_wdev->wiphy;
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c:2155: mon_wdev->netdev = mon_ndev;
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c-2156- mon_wdev->iftype = NL80211_IFTYPE_MONITOR;
--
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c=2704=int rtw_wdev_alloc(struct adapter *padapter, struct device *dev)
--
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c-2735- wdev->wiphy = wiphy;
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c:2736: wdev->netdev = pnetdev;
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c-2737-
--
net/wireless/core.c=1702=static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
--
net/wireless/core.c-1719- SET_NETDEV_DEVTYPE(dev, &wiphy_type);
net/wireless/core.c:1720: wdev->netdev = dev;
net/wireless/core.c-1721- /* can only change netns with wiphy */
]
|
| 70/2 |
2026/06/27 02:08 |
llm |
expert |
0m
Model:
Tokens:
input: 73537
output: 44
thoughts: 97
Thoughts: **Wireless Network Device Registration and Unregistration: A Quick Review**
Okay, so I'm looking at `net/wireless/core.c` and specifically this snippet:
```c
SET_NETDEV_DEVTYPE(dev, &wiphy_type);
wdev->netdev = dev;
```
This is within `cfg80211_netdev_notifier_call`, triggered by `NETDEV_REGISTER`. Pretty standard stuff, setting the device type and linking the network device (`dev`) to the wireless device structure (`wdev`). It confirms the device is registered.
But, a thought is nagging me. We're setting `wdev->netdev` when the network device is *registered*. Makes perfect sense. The question is, is there a corresponding *unregistration* path and how is `wdev->netdev` handled when the device is unregistered? I need to make sure the structure is cleaned up properly or it could lead to all sorts of issues downstream. I need to track down where this unregistration is handled. Time to dig deeper and see if there are corresponding calls, especially for `NETDEV_UNREGISTER`.
|
| 71/2 |
2026/06/27 02:08 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/wireless/core.c Name:cfg80211_netdev_notifier_call]
Results: map[SourceCode:1702: static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
1703: unsigned long state, void *ptr)
1704: {
1705: struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1706: struct wireless_dev *wdev = dev->ieee80211_ptr;
1707: struct cfg80211_registered_device *rdev;
1708: struct cfg80211_sched_scan_request *pos, *tmp;
1709:
1710: if (!wdev)
1711: return NOTIFY_DONE;
1712:
1713: rdev = wiphy_to_rdev(wdev->wiphy);
1714:
1715: WARN_ON(wdev->iftype == NL80211_IFTYPE_UNSPECIFIED);
1716:
1717: switch (state) {
1718: case NETDEV_POST_INIT:
1719: SET_NETDEV_DEVTYPE(dev, &wiphy_type);
1720: wdev->netdev = dev;
1721: /* can only change netns with wiphy */
1722: dev->netns_immutable = true;
1723:
1724: cfg80211_init_wdev(wdev);
1725: break;
1726: case NETDEV_REGISTER:
1727: if (!wdev->registered) {
1728: guard(wiphy)(&rdev->wiphy);
1729:
1730: cfg80211_register_wdev(rdev, wdev);
1731: }
1732: break;
1733: case NETDEV_UNREGISTER:
1734: /*
1735: * It is possible to get NETDEV_UNREGISTER multiple times,
1736: * so check wdev->registered.
1737: */
1738: if (wdev->registered && !wdev->registering) {
1739: guard(wiphy)(&rdev->wiphy);
1740:
1741: _cfg80211_unregister_wdev(wdev, false);
1742: }
1743: break;
1744: case NETDEV_GOING_DOWN:
1745: cfg80211_leave(rdev, wdev, -1);
1746: scoped_guard(wiphy, &rdev->wiphy)
1747: cfg80211_remove_links(wdev);
1748: /* since we just did cfg80211_leave() nothing to do there */
1749: cancel_work_sync(&wdev->disconnect_wk);
1750: cancel_work_sync(&wdev->pmsr_free_wk);
1751: break;
1752: case NETDEV_DOWN:
1753: wiphy_lock(&rdev->wiphy);
1754: cfg80211_update_iface_num(rdev, wdev->iftype, -1);
1755: if (rdev->scan_req && rdev->scan_req->req.wdev == wdev) {
1756: if (WARN_ON(!rdev->scan_req->notified &&
1757: (!rdev->int_scan_req ||
1758: !rdev->int_scan_req->notified)))
1759: rdev->scan_req->info.aborted = true;
1760: ___cfg80211_scan_done(rdev, false);
1761: }
1762:
1763: list_for_each_entry_safe(pos, tmp,
1764: &rdev->sched_scan_req_list, list) {
1765: if (WARN_ON(pos->dev == wdev->netdev))
1766: cfg80211_stop_sched_scan_req(rdev, pos, false);
1767: }
1768:
1769: rdev->opencount--;
1770: wiphy_unlock(&rdev->wiphy);
1771: wake_up(&rdev->dev_wait);
1772: break;
1773: case NETDEV_UP:
1774: wiphy_lock(&rdev->wiphy);
1775: cfg80211_update_iface_num(rdev, wdev->iftype, 1);
1776: switch (wdev->iftype) {
1777: #ifdef CONFIG_CFG80211_WEXT
1778: case NL80211_IFTYPE_ADHOC:
1779: cfg80211_ibss_wext_join(rdev, wdev);
1780: break;
1781: case NL80211_IFTYPE_STATION:
1782: cfg80211_mgd_wext_connect(rdev, wdev);
1783: break;
1784: #endif
1785: #ifdef CONFIG_MAC80211_MESH
1786: case NL80211_IFTYPE_MESH_POINT:
1787: {
1788: /* backward compat code... */
1789: struct mesh_setup setup;
1790: memcpy(&setup, &default_mesh_setup,
1791: sizeof(setup));
1792: /* back compat only needed for mesh_id */
1793: setup.mesh_id = wdev->u.mesh.id;
1794: setup.mesh_id_len = wdev->u.mesh.id_up_len;
1795: if (wdev->u.mesh.id_up_len)
1796: __cfg80211_join_mesh(rdev, dev,
1797: &setup,
1798: &default_mesh_config);
1799: break;
1800: }
1801: #endif
1802: default:
1803: break;
1804: }
1805: rdev->opencount++;
1806:
1807: /*
1808: * Configure power management to the driver here so that its
1809: * correctly set also after interface type changes etc.
1810: */
1811: if ((wdev->iftype == NL80211_IFTYPE_STATION ||
1812: wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
1813: rdev->ops->set_power_mgmt &&
1814: rdev_set_power_mgmt(rdev, dev, wdev->ps,
1815: wdev->ps_timeout)) {
1816: /* assume this means it's off */
1817: wdev->ps = false;
1818: }
1819: wiphy_unlock(&rdev->wiphy);
1820: break;
1821: case NETDEV_PRE_UP:
1822: if (!cfg80211_iftype_allowed(wdev->wiphy, wdev->iftype,
1823: wdev->use_4addr, 0))
1824: return notifier_from_errno(-EOPNOTSUPP);
1825:
1826: if (rfkill_blocked(rdev->wiphy.rfkill))
1827: return notifier_from_errno(-ERFKILL);
1828:
1829: /* NAN_DATA interfaces require a running NAN interface */
1830: if (wdev->iftype == NL80211_IFTYPE_NAN_DATA) {
1831: struct wireless_dev *iter;
1832: bool nan_started = false;
1833:
1834: list_for_each_entry(iter, &rdev->wiphy.wdev_list, list) {
1835: if (iter->iftype == NL80211_IFTYPE_NAN &&
1836: wdev_running(iter)) {
1837: nan_started = true;
1838: break;
1839: }
1840: }
1841:
1842: if (!nan_started)
1843: return notifier_from_errno(-ENOLINK);
1844: }
1845: break;
1846: default:
1847: return NOTIFY_DONE;
1848: }
1849:
1850: wireless_nlevent_flush();
1851:
1852: return NOTIFY_OK;
1853: }
SourceFile:net/wireless/core.c]
|
| 72/2 |
2026/06/27 02:08 |
llm |
expert |
0m
Model:
Tokens:
input: 76397
output: 43
thoughts: 44
Thoughts: Okay, let me think this through...
**Analyzing `wdev->netdev` in the Context of Netlink Registration**
Hmm, hold on a second. I'm recalling that `wdev->netdev` is actually initialized, or more precisely, set during `NETDEV_POST_INIT`. That's important. This means we're dealing with an allocation that's tied to the device's lifecycle. Now, the next crucial question is, under what circumstances, if ever, is that pointer, `wdev->netdev`, explicitly or implicitly set to `NULL` *after* its initial setup? It needs a closer look. I need to ensure that unregistering correctly nullifies this pointer.
Okay, let's now consider this function `_cfg80211_unregister_wdev`. I need to ensure that the unregistration process cleans up after itself and ensures memory safety. That means this is where I need to focus my attention. It's the point of removal, so it's the obvious place to look for a deallocation, or at the very least a `wdev->netdev = NULL` assignment. I need to confirm that these actions are being performed.
|
| 73/2 |
2026/06/27 02:08 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/wireless/core.c Name:_cfg80211_unregister_wdev]
Results: map[SourceCode:1404: static void _cfg80211_unregister_wdev(struct wireless_dev *wdev,
1405: bool unregister_netdev)
1406: {
1407: struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
1408: struct cfg80211_cqm_config *cqm_config;
1409: unsigned int link_id;
1410:
1411: ASSERT_RTNL();
1412: lockdep_assert_held(&rdev->wiphy.mtx);
1413:
1414: nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
1415:
1416: wdev->registered = false;
1417:
1418: if (wdev->netdev) {
1419: sysfs_remove_link(&wdev->netdev->dev.kobj, "phy80211");
1420: if (unregister_netdev)
1421: unregister_netdevice(wdev->netdev);
1422: }
1423:
1424: list_del_rcu(&wdev->list);
1425: synchronize_net();
1426: rdev->devlist_generation++;
1427:
1428: cfg80211_mlme_purge_registrations(wdev);
1429:
1430: switch (wdev->iftype) {
1431: case NL80211_IFTYPE_P2P_DEVICE:
1432: cfg80211_stop_p2p_device(rdev, wdev);
1433: break;
1434: case NL80211_IFTYPE_NAN:
1435: cfg80211_stop_nan(rdev, wdev);
1436: break;
1437: case NL80211_IFTYPE_PD:
1438: cfg80211_stop_pd(rdev, wdev);
1439: break;
1440: default:
1441: break;
1442: }
1443:
1444: #ifdef CONFIG_CFG80211_WEXT
1445: kfree_sensitive(wdev->wext.keys);
1446: wdev->wext.keys = NULL;
1447: #endif
1448: wiphy_work_cancel(wdev->wiphy, &wdev->cqm_rssi_work);
1449: /* deleted from the list, so can't be found from nl80211 any more */
1450: cqm_config = rcu_access_pointer(wdev->cqm_config);
1451: kfree_rcu(cqm_config, rcu_head);
1452: RCU_INIT_POINTER(wdev->cqm_config, NULL);
1453:
1454: /*
1455: * Ensure that all events have been processed and
1456: * freed.
1457: */
1458: cfg80211_process_wdev_events(wdev);
1459:
1460: if (wdev->iftype == NL80211_IFTYPE_STATION ||
1461: wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) {
1462: for (link_id = 0; link_id < ARRAY_SIZE(wdev->links); link_id++) {
1463: struct cfg80211_internal_bss *curbss;
1464:
1465: curbss = wdev->links[link_id].client.current_bss;
1466:
1467: if (WARN_ON(curbss)) {
1468: cfg80211_unhold_bss(curbss);
1469: cfg80211_put_bss(wdev->wiphy, &curbss->pub);
1470: wdev->links[link_id].client.current_bss = NULL;
1471: }
1472: }
1473: }
1474:
1475: wdev->connected = false;
1476: }
SourceFile:net/wireless/core.c]
|
| 74/2 |
2026/06/27 02:08 |
llm |
expert |
0m
Model:
Tokens:
input: 77991
output: 47
thoughts: 605
Thoughts: **Analyzing a Potential Kernel Vulnerability**
Okay, so I'm digging into this code, and something's not quite right. It looks like `wdev->netdev` isn't being set to `NULL` explicitly in all cases. This means, as I see it, that for interfaces that *don't* have a `netdev`, like `NL80211_IFTYPE_P2P_DEVICE` or `NL80211_IFTYPE_NAN`, `wdev->netdev` could be uninitialized.
Wait a sec, does `NL80211_IFTYPE_NAN` really lack a `netdev`? Okay, let me quickly confirm that with `cfg80211_wdev_bi`. Hmm, it returns zero. Right, so that means `cfg80211_calculate_bi_data` is going to crash if it hits a `P2P_DEVICE` or `NAN` interface. Specifically, it's because `rdev_get_radio_mask` is called before checking `wdev_bi`.
Now, is this actually exploitable? It’s a NULL pointer dereference, which is a big flag. The address accessed is like `0x34fa`, which is a pretty low memory offset. Since the `mmap_min_addr` is normally set to a pretty large value like 65536, this is almost certainly an unmapped address from user space. Which means this is a pure NULL pointer dereference and will lead to a kernel oops, or even a panic if `panic_on_oops` is on. So this is a Denial of Service.
Can an unprivileged user trigger this? Creating either of those interfaces, a P2P Device or NAN interface, requires `CAP_NET_ADMIN` in the net namespace of the wiphy. Usually, the wiphy lives in the init net namespace, which is restricted. So, a regular user can't create those interfaces, at least not directly.
But, hang on... Could an unprivileged user trigger the crash *if* those interfaces are *already* created by root? If root has, say, created a P2P Device and an unprivileged user can somehow reach `cfg80211_calculate_bi_data`? Okay, let's see. `cfg80211_calculate_bi_data` is called from `cfg80211_iter_combinations`, which in turn is called from `ieee80211_max_num_channels`. And, that last function is called when you create a new channel context. When does that happen? Right, when you join a network, or start an AP, etc.
Can an unprivileged user join a network? No, things like `NL80211_CMD_JOIN_IBSS`, `NL80211_CMD_CONNECT` – those all require `CAP_NET_ADMIN`. Hmm... wait a second. What about `NL80211_CMD_GET_WIPHY`? Does *that* call `cfg80211_iter_combinations`? Time to check `nl80211_send_wiphy`. I need to figure out if that particular command path can be leveraged.
|
| 75/2 |
2026/06/27 02:08 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/wireless/nl80211.c Name:nl80211_send_wiphy]
Results: map[SourceCode:3054: static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
3055: enum nl80211_commands cmd,
3056: struct sk_buff *msg, u32 portid, u32 seq,
3057: int flags, struct nl80211_dump_wiphy_state *state)
3058: {
3059: void *hdr;
3060: struct nlattr *nl_bands, *nl_band;
3061: struct nlattr *nl_freqs, *nl_freq;
3062: struct nlattr *nl_cmds;
3063: enum nl80211_band band;
3064: struct ieee80211_channel *chan;
3065: int i;
3066: const struct ieee80211_txrx_stypes *mgmt_stypes =
3067: rdev->wiphy.mgmt_stypes;
3068: u32 features;
3069:
3070: hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
3071: if (!hdr)
3072: return -ENOBUFS;
3073:
3074: if (WARN_ON(!state))
3075: return -EINVAL;
3076:
3077: if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
3078: nla_put_string(msg, NL80211_ATTR_WIPHY_NAME,
3079: wiphy_name(&rdev->wiphy)) ||
3080: nla_put_u32(msg, NL80211_ATTR_GENERATION,
3081: cfg80211_rdev_list_generation))
3082: goto nla_put_failure;
3083:
3084: if (cmd != NL80211_CMD_NEW_WIPHY)
3085: goto finish;
3086:
3087: switch (state->split_start) {
3088: case 0:
3089: if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
3090: rdev->wiphy.retry_short) ||
3091: nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
3092: rdev->wiphy.retry_long) ||
3093: nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
3094: rdev->wiphy.frag_threshold) ||
3095: nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
3096: rdev->wiphy.rts_threshold) ||
3097: nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
3098: rdev->wiphy.coverage_class) ||
3099: nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
3100: rdev->wiphy.max_scan_ssids) ||
3101: nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
3102: rdev->wiphy.max_sched_scan_ssids) ||
3103: nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
3104: rdev->wiphy.max_scan_ie_len) ||
3105: nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
3106: rdev->wiphy.max_sched_scan_ie_len) ||
3107: nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS,
3108: rdev->wiphy.max_match_sets))
3109: goto nla_put_failure;
3110:
3111: if ((rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) &&
3112: nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN))
3113: goto nla_put_failure;
3114: if ((rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
3115: nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH))
3116: goto nla_put_failure;
3117: if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
3118: nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD))
3119: goto nla_put_failure;
3120: if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) &&
3121: nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT))
3122: goto nla_put_failure;
3123: if ((rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
3124: nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT))
3125: goto nla_put_failure;
3126: if ((rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
3127: nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
3128: goto nla_put_failure;
3129: state->split_start++;
3130: if (state->split)
3131: break;
3132: fallthrough;
3133: case 1:
3134: if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
3135: sizeof(u32) * rdev->wiphy.n_cipher_suites,
3136: rdev->wiphy.cipher_suites))
3137: goto nla_put_failure;
3138:
3139: if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
3140: rdev->wiphy.max_num_pmkids))
3141: goto nla_put_failure;
3142:
3143: if ((rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
3144: nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE))
3145: goto nla_put_failure;
3146:
3147: if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
3148: rdev->wiphy.available_antennas_tx) ||
3149: nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
3150: rdev->wiphy.available_antennas_rx))
3151: goto nla_put_failure;
3152:
3153: if ((rdev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) &&
3154: nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD,
3155: rdev->wiphy.probe_resp_offload))
3156: goto nla_put_failure;
3157:
3158: if ((rdev->wiphy.available_antennas_tx ||
3159: rdev->wiphy.available_antennas_rx) &&
3160: rdev->ops->get_antenna) {
3161: u32 tx_ant = 0, rx_ant = 0;
3162: int res;
3163:
3164: res = rdev_get_antenna(rdev, -1, &tx_ant, &rx_ant);
3165: if (!res) {
3166: if (nla_put_u32(msg,
3167: NL80211_ATTR_WIPHY_ANTENNA_TX,
3168: tx_ant) ||
3169: nla_put_u32(msg,
3170: NL80211_ATTR_WIPHY_ANTENNA_RX,
3171: rx_ant))
3172: goto nla_put_failure;
3173: }
3174: }
3175:
3176: state->split_start++;
3177: if (state->split)
3178: break;
3179: fallthrough;
3180: case 2:
3181: if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
3182: rdev->wiphy.interface_modes))
3183: goto nla_put_failure;
3184: state->split_start++;
3185: if (state->split)
3186: break;
3187: fallthrough;
3188: case 3:
3189: nl_bands = nla_nest_start_noflag(msg,
3190: NL80211_ATTR_WIPHY_BANDS);
3191: if (!nl_bands)
3192: goto nla_put_failure;
3193:
3194: for (band = state->band_start;
3195: band < (state->split ?
3196: NUM_NL80211_BANDS :
3197: NL80211_BAND_60GHZ + 1);
3198: band++) {
3199: struct ieee80211_supported_band *sband;
3200:
3201: /* omit higher bands for ancient software */
3202: if (band > NL80211_BAND_5GHZ && !state->split)
3203: break;
3204:
3205: sband = rdev->wiphy.bands[band];
3206:
3207: if (!sband)
3208: continue;
3209:
3210: nl_band = nla_nest_start_noflag(msg, band);
3211: if (!nl_band)
3212: goto nla_put_failure;
3213:
3214: switch (state->chan_start) {
3215: case 0:
3216: if (nl80211_send_band_rateinfo(msg, sband,
3217: state->split))
3218: goto nla_put_failure;
3219: state->chan_start++;
3220: if (state->split)
3221: break;
3222: fallthrough;
3223: default:
3224: /* add frequencies */
3225: nl_freqs = nla_nest_start_noflag(msg,
3226: NL80211_BAND_ATTR_FREQS);
3227: if (!nl_freqs)
3228: goto nla_put_failure;
3229:
3230: for (i = state->chan_start - 1;
3231: i < sband->n_channels;
3232: i++) {
3233: nl_freq = nla_nest_start_noflag(msg,
3234: i);
3235: if (!nl_freq)
3236: goto nla_put_failure;
3237:
3238: chan = &sband->channels[i];
3239:
3240: if (nl80211_msg_put_channel(
3241: msg, &rdev->wiphy, chan,
3242: state->split))
3243: goto nla_put_failure;
3244:
3245: nla_nest_end(msg, nl_freq);
3246: if (state->split)
3247: break;
3248: }
3249: if (i < sband->n_channels)
3250: state->chan_start = i + 2;
3251: else
3252: state->chan_start = 0;
3253: nla_nest_end(msg, nl_freqs);
3254: }
3255:
3256: nla_nest_end(msg, nl_band);
3257:
3258: if (state->split) {
3259: /* start again here */
3260: if (state->chan_start)
3261: band--;
3262: break;
3263: }
3264: }
3265: nla_nest_end(msg, nl_bands);
3266:
3267: if (band < NUM_NL80211_BANDS)
3268: state->band_start = band + 1;
3269: else
3270: state->band_start = 0;
3271:
3272: /* if bands & channels are done, continue outside */
3273: if (state->band_start == 0 && state->chan_start == 0)
3274: state->split_start++;
3275: if (state->split)
3276: break;
3277: fallthrough;
3278: case 4:
3279: nl_cmds = nla_nest_start_noflag(msg,
3280: NL80211_ATTR_SUPPORTED_COMMANDS);
3281: if (!nl_cmds)
3282: goto nla_put_failure;
3283:
3284: i = nl80211_add_commands_unsplit(rdev, msg);
3285: if (i < 0)
3286: goto nla_put_failure;
3287: if (state->split) {
3288: CMD(crit_proto_start, CRIT_PROTOCOL_START);
3289: CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
3290: if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
3291: CMD(channel_switch, CHANNEL_SWITCH);
3292: CMD(set_qos_map, SET_QOS_MAP);
3293: if (rdev->wiphy.features &
3294: NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
3295: CMD(add_tx_ts, ADD_TX_TS);
3296: CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
3297: CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
3298: CMD(update_ft_ies, UPDATE_FT_IES);
3299: if (rdev->wiphy.sar_capa)
3300: CMD(set_sar_specs, SET_SAR_SPECS);
3301: CMD(assoc_ml_reconf, ASSOC_MLO_RECONF);
3302: }
3303: #undef CMD
3304:
3305: nla_nest_end(msg, nl_cmds);
3306: state->split_start++;
3307: if (state->split)
3308: break;
3309: fallthrough;
3310: case 5:
3311: if (rdev->ops->remain_on_channel &&
3312: (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
3313: nla_put_u32(msg,
3314: NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
3315: rdev->wiphy.max_remain_on_channel_duration))
3316: goto nla_put_failure;
3317:
3318: if ((rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) &&
3319: nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK))
3320: goto nla_put_failure;
3321:
3322: state->split_start++;
3323: if (state->split)
3324: break;
3325: fallthrough;
3326: case 6:
3327: #ifdef CONFIG_PM
3328: if (nl80211_send_wowlan(msg, rdev, state->split))
3329: goto nla_put_failure;
3330: state->split_start++;
3331: if (state->split)
3332: break;
3333: #else
3334: state->split_start++;
3335: #endif
3336: fallthrough;
3337: case 7:
3338: if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
3339: rdev->wiphy.software_iftypes))
3340: goto nla_put_failure;
3341:
3342: if (nl80211_put_iface_combinations(&rdev->wiphy, msg,
3343: NL80211_ATTR_INTERFACE_COMBINATIONS,
3344: rdev->wiphy.n_radio ? 0 : -1,
3345: state->split, 0))
3346: goto nla_put_failure;
3347:
3348: state->split_start++;
3349: if (state->split)
3350: break;
3351: fallthrough;
3352: case 8:
3353: if ((rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
3354: nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
3355: rdev->wiphy.ap_sme_capa))
3356: goto nla_put_failure;
3357:
3358: features = rdev->wiphy.features;
3359: /*
3360: * We can only add the per-channel limit information if the
3361: * dump is split, otherwise it makes it too big. Therefore
3362: * only advertise it in that case.
3363: */
3364: if (state->split)
3365: features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
3366: if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features))
3367: goto nla_put_failure;
3368:
3369: if (rdev->wiphy.ht_capa_mod_mask &&
3370: nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
3371: sizeof(*rdev->wiphy.ht_capa_mod_mask),
3372: rdev->wiphy.ht_capa_mod_mask))
3373: goto nla_put_failure;
3374:
3375: if (rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
3376: rdev->wiphy.max_acl_mac_addrs &&
3377: nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX,
3378: rdev->wiphy.max_acl_mac_addrs))
3379: goto nla_put_failure;
3380:
3381: /*
3382: * Any information below this point is only available to
3383: * applications that can deal with it being split. This
3384: * helps ensure that newly added capabilities don't break
3385: * older tools by overrunning their buffers.
3386: *
3387: * We still increment split_start so that in the split
3388: * case we'll continue with more data in the next round,
3389: * but break unconditionally so unsplit data stops here.
3390: */
3391: if (state->split)
3392: state->split_start++;
3393: else
3394: state->split_start = 0;
3395: break;
3396: case 9:
3397: if (nl80211_send_mgmt_stypes(msg, mgmt_stypes))
3398: goto nla_put_failure;
3399:
3400: if (nla_put_u32(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
3401: rdev->wiphy.max_sched_scan_plans) ||
3402: nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
3403: rdev->wiphy.max_sched_scan_plan_interval) ||
3404: nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
3405: rdev->wiphy.max_sched_scan_plan_iterations))
3406: goto nla_put_failure;
3407:
3408: if (rdev->wiphy.extended_capabilities &&
3409: (nla_put(msg, NL80211_ATTR_EXT_CAPA,
3410: rdev->wiphy.extended_capabilities_len,
3411: rdev->wiphy.extended_capabilities) ||
3412: nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
3413: rdev->wiphy.extended_capabilities_len,
3414: rdev->wiphy.extended_capabilities_mask)))
3415: goto nla_put_failure;
3416:
3417: if (rdev->wiphy.vht_capa_mod_mask &&
3418: nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK,
3419: sizeof(*rdev->wiphy.vht_capa_mod_mask),
3420: rdev->wiphy.vht_capa_mod_mask))
3421: goto nla_put_failure;
3422:
3423: if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
3424: rdev->wiphy.perm_addr))
3425: goto nla_put_failure;
3426:
3427: if (!is_zero_ether_addr(rdev->wiphy.addr_mask) &&
3428: nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
3429: rdev->wiphy.addr_mask))
3430: goto nla_put_failure;
3431:
3432: if (rdev->wiphy.n_addresses > 1) {
3433: void *attr;
3434:
3435: attr = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
3436: if (!attr)
3437: goto nla_put_failure;
3438:
3439: for (i = 0; i < rdev->wiphy.n_addresses; i++)
3440: if (nla_put(msg, i + 1, ETH_ALEN,
3441: rdev->wiphy.addresses[i].addr))
3442: goto nla_put_failure;
3443:
3444: nla_nest_end(msg, attr);
3445: }
3446:
3447: state->split_start++;
3448: break;
3449: case 10:
3450: if (nl80211_send_coalesce(msg, rdev))
3451: goto nla_put_failure;
3452:
3453: if (rdev->wiphy.max_ap_assoc_sta &&
3454: nla_put_u32(msg, NL80211_ATTR_MAX_AP_ASSOC_STA,
3455: rdev->wiphy.max_ap_assoc_sta))
3456: goto nla_put_failure;
3457:
3458: state->split_start++;
3459: break;
3460: case 11:
3461: if (rdev->wiphy.n_vendor_commands) {
3462: const struct nl80211_vendor_cmd_info *info;
3463: struct nlattr *nested;
3464:
3465: nested = nla_nest_start_noflag(msg,
3466: NL80211_ATTR_VENDOR_DATA);
3467: if (!nested)
3468: goto nla_put_failure;
3469:
3470: for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
3471: info = &rdev->wiphy.vendor_commands[i].info;
3472: if (nla_put(msg, i + 1, sizeof(*info), info))
3473: goto nla_put_failure;
3474: }
3475: nla_nest_end(msg, nested);
3476: }
3477:
3478: if (rdev->wiphy.n_vendor_events) {
3479: const struct nl80211_vendor_cmd_info *info;
3480: struct nlattr *nested;
3481:
3482: nested = nla_nest_start_noflag(msg,
3483: NL80211_ATTR_VENDOR_EVENTS);
3484: if (!nested)
3485: goto nla_put_failure;
3486:
3487: for (i = 0; i < rdev->wiphy.n_vendor_events; i++) {
3488: info = &rdev->wiphy.vendor_events[i];
3489: if (nla_put(msg, i + 1, sizeof(*info), info))
3490: goto nla_put_failure;
3491: }
3492: nla_nest_end(msg, nested);
3493: }
3494: state->split_start++;
3495: break;
3496: case 12:
3497: if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
3498: nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
3499: rdev->wiphy.max_num_csa_counters))
3500: goto nla_put_failure;
3501:
3502: if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
3503: nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
3504: goto nla_put_failure;
3505:
3506: if (rdev->wiphy.max_sched_scan_reqs &&
3507: nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_MAX_REQS,
3508: rdev->wiphy.max_sched_scan_reqs))
3509: goto nla_put_failure;
3510:
3511: if (nla_put(msg, NL80211_ATTR_EXT_FEATURES,
3512: sizeof(rdev->wiphy.ext_features),
3513: rdev->wiphy.ext_features))
3514: goto nla_put_failure;
3515:
3516: if (rdev->wiphy.bss_param_support) {
3517: struct nlattr *nested;
3518: u32 parsup = rdev->wiphy.bss_param_support;
3519:
3520: nested = nla_nest_start(msg, NL80211_ATTR_BSS_PARAM);
3521: if (!nested)
3522: goto nla_put_failure;
3523:
3524: if ((parsup & WIPHY_BSS_PARAM_CTS_PROT) &&
3525: nla_put_flag(msg, NL80211_ATTR_BSS_CTS_PROT))
3526: goto nla_put_failure;
3527: if ((parsup & WIPHY_BSS_PARAM_SHORT_PREAMBLE) &&
3528: nla_put_flag(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE))
3529: goto nla_put_failure;
3530: if ((parsup & WIPHY_BSS_PARAM_SHORT_SLOT_TIME) &&
3531: nla_put_flag(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME))
3532: goto nla_put_failure;
3533: if ((parsup & WIPHY_BSS_PARAM_BASIC_RATES) &&
3534: nla_put_flag(msg, NL80211_ATTR_BSS_BASIC_RATES))
3535: goto nla_put_failure;
3536: if ((parsup & WIPHY_BSS_PARAM_AP_ISOLATE) &&
3537: nla_put_flag(msg, NL80211_ATTR_AP_ISOLATE))
3538: goto nla_put_failure;
3539: if ((parsup & WIPHY_BSS_PARAM_HT_OPMODE) &&
3540: nla_put_flag(msg, NL80211_ATTR_BSS_HT_OPMODE))
3541: goto nla_put_failure;
3542: if ((parsup & WIPHY_BSS_PARAM_P2P_CTWINDOW) &&
3543: nla_put_flag(msg, NL80211_ATTR_P2P_CTWINDOW))
3544: goto nla_put_failure;
3545: if ((parsup & WIPHY_BSS_PARAM_P2P_OPPPS) &&
3546: nla_put_flag(msg, NL80211_ATTR_P2P_OPPPS))
3547: goto nla_put_failure;
3548: nla_nest_end(msg, nested);
3549: }
3550: if (rdev->wiphy.bss_select_support) {
3551: struct nlattr *nested;
3552: u32 bss_select_support = rdev->wiphy.bss_select_support;
3553:
3554: nested = nla_nest_start_noflag(msg,
3555: NL80211_ATTR_BSS_SELECT);
3556: if (!nested)
3557: goto nla_put_failure;
3558:
3559: i = 0;
3560: while (bss_select_support) {
3561: if ((bss_select_support & 1) &&
3562: nla_put_flag(msg, i))
3563: goto nla_put_failure;
3564: i++;
3565: bss_select_support >>= 1;
3566: }
3567: nla_nest_end(msg, nested);
3568: }
3569:
3570: state->split_start++;
3571: break;
3572: case 13:
3573: if (rdev->wiphy.num_iftype_ext_capab &&
3574: rdev->wiphy.iftype_ext_capab) {
3575: struct nlattr *nested_ext_capab, *nested;
3576:
3577: nested = nla_nest_start_noflag(msg,
3578: NL80211_ATTR_IFTYPE_EXT_CAPA);
3579: if (!nested)
3580: goto nla_put_failure;
3581:
3582: for (i = state->capa_start;
3583: i < rdev->wiphy.num_iftype_ext_capab; i++) {
3584: const struct wiphy_iftype_ext_capab *capab;
3585:
3586: capab = &rdev->wiphy.iftype_ext_capab[i];
3587:
3588: nested_ext_capab = nla_nest_start_noflag(msg,
3589: i);
3590: if (!nested_ext_capab ||
3591: nla_put_u32(msg, NL80211_ATTR_IFTYPE,
3592: capab->iftype) ||
3593: nla_put(msg, NL80211_ATTR_EXT_CAPA,
3594: capab->extended_capabilities_len,
3595: capab->extended_capabilities) ||
3596: nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
3597: capab->extended_capabilities_len,
3598: capab->extended_capabilities_mask))
3599: goto nla_put_failure;
3600:
3601: if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO &&
3602: (nla_put_u16(msg,
3603: NL80211_ATTR_EML_CAPABILITY,
3604: capab->eml_capabilities) ||
3605: nla_put_u16(msg,
3606: NL80211_ATTR_MLD_CAPA_AND_OPS,
3607: capab->mld_capa_and_ops)))
3608: goto nla_put_failure;
3609: if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO &&
3610: capab->ext_mld_capa_and_ops &&
3611: nla_put_u16(msg,
3612: NL80211_ATTR_EXT_MLD_CAPA_AND_OPS,
3613: capab->ext_mld_capa_and_ops))
3614: goto nla_put_failure;
3615:
3616: nla_nest_end(msg, nested_ext_capab);
3617: if (state->split)
3618: break;
3619: }
3620: nla_nest_end(msg, nested);
3621: if (i < rdev->wiphy.num_iftype_ext_capab) {
3622: state->capa_start = i + 1;
3623: break;
3624: }
3625: }
3626:
3627: if (nla_put_u32(msg, NL80211_ATTR_BANDS,
3628: rdev->wiphy.nan_supported_bands))
3629: goto nla_put_failure;
3630:
3631: if (wiphy_ext_feature_isset(&rdev->wiphy,
3632: NL80211_EXT_FEATURE_TXQS)) {
3633: struct cfg80211_txq_stats txqstats = {};
3634: int res;
3635:
3636: res = rdev_get_txq_stats(rdev, NULL, &txqstats);
3637: if (!res &&
3638: !nl80211_put_txq_stats(msg, &txqstats,
3639: NL80211_ATTR_TXQ_STATS))
3640: goto nla_put_failure;
3641:
3642: if (nla_put_u32(msg, NL80211_ATTR_TXQ_LIMIT,
3643: rdev->wiphy.txq_limit))
3644: goto nla_put_failure;
3645: if (nla_put_u32(msg, NL80211_ATTR_TXQ_MEMORY_LIMIT,
3646: rdev->wiphy.txq_memory_limit))
3647: goto nla_put_failure;
3648: if (nla_put_u32(msg, NL80211_ATTR_TXQ_QUANTUM,
3649: rdev->wiphy.txq_quantum))
3650: goto nla_put_failure;
3651: }
3652:
3653: state->split_start++;
3654: break;
3655: case 14:
3656: if (nl80211_send_pmsr_capa(rdev, msg))
3657: goto nla_put_failure;
3658:
3659: state->split_start++;
3660: break;
3661: case 15:
3662: if (rdev->wiphy.akm_suites &&
3663: nla_put(msg, NL80211_ATTR_AKM_SUITES,
3664: sizeof(u32) * rdev->wiphy.n_akm_suites,
3665: rdev->wiphy.akm_suites))
3666: goto nla_put_failure;
3667:
3668: if (nl80211_put_iftype_akm_suites(rdev, msg))
3669: goto nla_put_failure;
3670:
3671: if (nl80211_put_tid_config_support(rdev, msg))
3672: goto nla_put_failure;
3673: state->split_start++;
3674: break;
3675: case 16:
3676: if (nl80211_put_sar_specs(rdev, msg))
3677: goto nla_put_failure;
3678:
3679: if (nl80211_put_mbssid_support(&rdev->wiphy, msg))
3680: goto nla_put_failure;
3681:
3682: if (nla_put_u16(msg, NL80211_ATTR_MAX_NUM_AKM_SUITES,
3683: rdev->wiphy.max_num_akm_suites))
3684: goto nla_put_failure;
3685:
3686: if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO)
3687: nla_put_flag(msg, NL80211_ATTR_MLO_SUPPORT);
3688:
3689: if (rdev->wiphy.hw_timestamp_max_peers &&
3690: nla_put_u16(msg, NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS,
3691: rdev->wiphy.hw_timestamp_max_peers))
3692: goto nla_put_failure;
3693:
3694: state->split_start++;
3695: break;
3696: case 17:
3697: if (nl80211_put_radios(&rdev->wiphy, msg))
3698: goto nla_put_failure;
3699:
3700: state->split_start++;
3701: break;
3702: case 18:
3703: if (nl80211_put_nan_capa(&rdev->wiphy, msg))
3704: goto nla_put_failure;
3705:
3706: /* done */
3707: state->split_start = 0;
3708: break;
3709: }
3710: finish:
3711: genlmsg_end(msg, hdr);
3712: return 0;
3713:
3714: nla_put_failure:
3715: genlmsg_cancel(msg, hdr);
3716: return -EMSGSIZE;
3717: }
SourceFile:net/wireless/nl80211.c]
|
| 76/2 |
2026/06/27 02:08 |
llm |
expert |
0m
Model:
Tokens:
input: 91169
output: 34
thoughts: 130
Thoughts: **Investigating the Data Calculation Path**
Okay, so I'm trying to trace the execution path that leads to `cfg80211_calculate_bi_data`. First, I assumed that `nl80211_send_wiphy` might be the trigger, but a quick check reveals that it doesn't directly call `cfg80211_iter_combinations`. That's not it. Hmm, let me think, what about the network configuration retrieval commands? Perhaps `NL80211_CMD_GET_INTERFACE`... nope, doesn't seem to be involved. How about `NL80211_CMD_GET_WIPHY`? Ah, that *does* call `nl80211_send_wiphy`. But that still doesn't get us to the combination iteration.
Alright, if `nl80211_send_wiphy` isn't the direct link to the combination iteration, I need to take a step back and identify *all* possible entry points. The next logical step is to systematically review every single caller of `cfg80211_iter_combinations`. I need to exhaustively track all the invocation points and see where the data calculations are actually performed.
|
| 77/2 |
2026/06/27 02:08 |
tool |
codesearch-find-references |
0m
Args: map[IncludeSnippetLines:0 Name:cfg80211_iter_combinations]
Results: map[References:[map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:cfg80211_check_combinations SourceFile:net/wireless/util.c SourceLine:2608] map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:ieee80211_max_num_channels SourceFile:net/mac80211/util.c SourceLine:4389] map[ReferenceKind:takes-address-of ReferencingEntityKind:global_variable ReferencingEntityName:__UNIQUE_ID_addressable_cfg80211_iter_combinations_2912 SourceFile:net/wireless/util.c SourceLine:2593] map[ReferenceKind:takes-address-of ReferencingEntityKind:global_variable ReferencingEntityName:__gendwarfksyms_ptr_cfg80211_iter_combinations SourceFile:net/wireless/util.c SourceLine:2593] map[ReferenceKind:takes-address-of ReferencingEntityKind:global_variable ReferencingEntityName:__gendwarfksyms_ptr_cfg80211_iter_combinations SourceFile:net/wireless/util.c SourceLine:2593]] TruncatedOutput:false]
|
| 78/2 |
2026/06/27 02:08 |
llm |
expert |
0m
Model:
Tokens:
input: 91957
output: 41
thoughts: 1524
Thoughts: **Analysis of the Wireless Device Driver Vulnerability**
Okay, let's break this down systematically. My initial thought process focused on identifying the attack surface and potential exploitability of this NULL pointer dereference.
First, I traced the call chain leading to the problematic code in `cfg80211_check_combinations`. It's called from `cfg80211_update_iface_num` during interface UP/DOWN operations, and `cfg80211_check_combinations_ext`. Crucially, all these paths require `CAP_NET_ADMIN`. This immediately narrows down the scope; an unprivileged user cannot directly trigger this.
My next line of inquiry involved checking if I could bypass this restriction, like with a user-namespace, or `mac80211_hwsim`. I quickly determined that creating a new net namespace and moving the wiphy there also requires `CAP_NET_ADMIN`. Using `mac80211_hwsim` appears attractive, but that also requires the `GENL_ADMIN_PERM`, which in turn, checks `CAP_NET_ADMIN`. This means that this bug is *not* accessible from unprivileged processes, and cannot be exploited within user namespaces.
Therefore, the vulnerability appears to be a Denial of Service, specifically a NULL pointer dereference. The crashing instruction's memory access is at a small offset from a null pointer, which causes a page fault. It looks like the KASAN is doing its job here. This means, an attacker cannot exploit this to achieve privilege escalation or leak information. It's just a kernel crash.
Then, I looked for a potential use-after-free scenario. I investigated if `wdev->netdev` could become a dangling pointer. I meticulously reviewed `_cfg80211_unregister_wdev`, and it became clear that while `wdev` is removed from the wiphy's list, `wdev->netdev` is not set to NULL. However, after unregistration, the `wdev` is removed from `wiphy->wdev_list` and will not be iterated over, which means it isn't a use-after-free.
The real root cause is that `wdev->netdev` is NULL for interfaces of type `NL80211_IFTYPE_P2P_DEVICE`, and `rdev_get_radio_mask` is not checking for this. I've re-confirmed this by checking the assembly, confirming the NULL pointer dereference.
Finally, I considered remote attack vectors. If the device is an AP, a new channel context is created when the AP starts. If a station roams, it could create new channel context. However, roaming is typically handled by firmware, and the kernel would require `CAP_NET_ADMIN` privileges. So, that attack vector appears unlikely.
In conclusion, this is a local Denial of Service vulnerability that is difficult to trigger due to `CAP_NET_ADMIN` privileges requirement.
|
| 79/2 |
2026/06/27 02:09 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/wireless/sme.c Name:cfg80211_roamed]
Results: map[SourceCode:1166: /* Consumes info->links.bss object(s) one way or another */
1167: void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info,
1168: gfp_t gfp)
1169: {
1170: struct wireless_dev *wdev = dev->ieee80211_ptr;
1171: struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
1172: struct cfg80211_event *ev;
1173: unsigned long flags;
1174: u8 *next;
1175: unsigned int link;
1176: size_t link_info_size = 0;
1177: bool bss_not_found = false;
1178:
1179: for_each_valid_link(info, link) {
1180: link_info_size += info->links[link].addr ? ETH_ALEN : 0;
1181: link_info_size += info->links[link].bssid ? ETH_ALEN : 0;
1182:
1183: if (info->links[link].bss)
1184: continue;
1185:
1186: info->links[link].bss =
1187: cfg80211_get_bss(wdev->wiphy,
1188: info->links[link].channel,
1189: info->links[link].bssid,
1190: wdev->u.client.ssid,
1191: wdev->u.client.ssid_len,
1192: wdev->conn_bss_type,
1193: IEEE80211_PRIVACY_ANY);
1194:
1195: if (!info->links[link].bss) {
1196: bss_not_found = true;
1197: break;
1198: }
1199: }
1200:
1201: if (WARN_ON(bss_not_found))
1202: goto out;
1203:
1204: ev = kzalloc(sizeof(*ev) + info->req_ie_len + info->resp_ie_len +
1205: info->fils.kek_len + info->fils.pmk_len +
1206: (info->fils.pmkid ? WLAN_PMKID_LEN : 0) +
1207: (info->ap_mld_addr ? ETH_ALEN : 0) + link_info_size, gfp);
1208: if (!ev)
1209: goto out;
1210:
1211: ev->type = EVENT_ROAMED;
1212: next = ((u8 *)ev) + sizeof(*ev);
1213: if (info->req_ie_len) {
1214: ev->rm.req_ie = next;
1215: ev->rm.req_ie_len = info->req_ie_len;
1216: memcpy((void *)ev->rm.req_ie, info->req_ie, info->req_ie_len);
1217: next += info->req_ie_len;
1218: }
1219: if (info->resp_ie_len) {
1220: ev->rm.resp_ie = next;
1221: ev->rm.resp_ie_len = info->resp_ie_len;
1222: memcpy((void *)ev->rm.resp_ie, info->resp_ie,
1223: info->resp_ie_len);
1224: next += info->resp_ie_len;
1225: }
1226: if (info->fils.kek_len) {
1227: ev->rm.fils.kek = next;
1228: ev->rm.fils.kek_len = info->fils.kek_len;
1229: memcpy((void *)ev->rm.fils.kek, info->fils.kek,
1230: info->fils.kek_len);
1231: next += info->fils.kek_len;
1232: }
1233: if (info->fils.pmk_len) {
1234: ev->rm.fils.pmk = next;
1235: ev->rm.fils.pmk_len = info->fils.pmk_len;
1236: memcpy((void *)ev->rm.fils.pmk, info->fils.pmk,
1237: info->fils.pmk_len);
1238: next += info->fils.pmk_len;
1239: }
1240: if (info->fils.pmkid) {
1241: ev->rm.fils.pmkid = next;
1242: memcpy((void *)ev->rm.fils.pmkid, info->fils.pmkid,
1243: WLAN_PMKID_LEN);
1244: next += WLAN_PMKID_LEN;
1245: }
1246: ev->rm.fils.update_erp_next_seq_num = info->fils.update_erp_next_seq_num;
1247: if (info->fils.update_erp_next_seq_num)
1248: ev->rm.fils.erp_next_seq_num = info->fils.erp_next_seq_num;
1249: if (info->ap_mld_addr) {
1250: ev->rm.ap_mld_addr = next;
1251: memcpy((void *)ev->rm.ap_mld_addr, info->ap_mld_addr,
1252: ETH_ALEN);
1253: next += ETH_ALEN;
1254: }
1255: ev->rm.valid_links = info->valid_links;
1256: for_each_valid_link(info, link) {
1257: ev->rm.links[link].bss = info->links[link].bss;
1258:
1259: if (info->links[link].addr) {
1260: ev->rm.links[link].addr = next;
1261: memcpy((void *)ev->rm.links[link].addr,
1262: info->links[link].addr,
1263: ETH_ALEN);
1264: next += ETH_ALEN;
1265: }
1266:
1267: if (info->links[link].bssid) {
1268: ev->rm.links[link].bssid = next;
1269: memcpy((void *)ev->rm.links[link].bssid,
1270: info->links[link].bssid,
1271: ETH_ALEN);
1272: next += ETH_ALEN;
1273: }
1274: }
1275:
1276: spin_lock_irqsave(&wdev->event_lock, flags);
1277: list_add_tail(&ev->list, &wdev->event_list);
1278: spin_unlock_irqrestore(&wdev->event_lock, flags);
1279: queue_work(cfg80211_wq, &rdev->event_work);
1280:
1281: return;
1282: out:
1283: for_each_valid_link(info, link)
1284: cfg80211_put_bss(wdev->wiphy, info->links[link].bss);
1285:
1286: }
SourceFile:net/wireless/sme.c]
|
| 80/2 |
2026/06/27 02:09 |
llm |
expert |
0m
Model:
Tokens:
input: 96337
output: 33
thoughts: 1145
Thoughts: **Analyzing the Kernel Vulnerability**
Okay, so I'm digging into this code and trying to figure out the attack surface. It looks like the core of this issue *isn't* directly triggered by `cfg80211_iter_combinations`. That's a good start. I need to trace the execution path that *does* lead here, which seems to involve `cfg80211_process_wdev_events`, specifically the `EVENT_ROAMED` event, though it ultimately isn't the key. The function `cfg80211_iter_combinations` is the target, but the vulnerability is in how its arguments are formed.
My initial thought is that the path to trigger this involves creating a P2P Device or NAN interface, and then kicking off something that calls `cfg80211_iter_combinations` with `radio_idx >= 0`. That narrows things down. This route demands `CAP_NET_ADMIN` privileges to create the interface and trigger the channel context, such as joining an IBSS. Because of that, this vulnerability is not accessible to unprivileged processes, and therefore, not reachable from user namespaces.
I'm starting to think about different exploitation scenarios. Could a VM guest trigger it? I considered a pass-through wiphy to the guest, but it quickly falls apart. If the wiphy is passed to the guest, the guest kernel controls it. So the crash would only affect the guest, not the host, thus eliminating a VM escape. I need to see if there is any standard for a paravirtualized WiFi device or some way a guest could influence the host through a USB device. This route also doesn't seem promising.
What about a malicious peripheral? Could a rogue USB Wi-Fi device be the vector? It would need to trick the host into creating a P2P Device and joining an IBSS. That sounds like something that requires user-space interaction, like NetworkManager or wpa_supplicant. Those *do* create P2P Device interfaces for Wi-Fi Direct. However, they don't *automatically* join an IBSS. If a user *specifically* configured them to do so, it might be possible. But this requires user configuration, which means a malicious peripheral alone can't directly trigger it. It's not a true peripheral trigger.
How about a network-based attack? Can a remote attacker send a crafted packet that triggers the crash? But it appears the crash occurs during *configuration*, like joining an IBSS or starting an AP. It is not triggered by the receipt of a packet. So that's another dead end.
So, from what I've found, the summary of this bug is as follows:
* Exploitable: No (NULL pointer dereference)
* Denial of Service: Yes
* Accessible From Unprivileged Processes: No (requires CAP_NET_ADMIN)
* Accessible From User Namespaces: No
* VM Guest Trigger: No
* VM Host Trigger: No
* Ethernet Network Trigger: No
* Other Remote Trigger: No
* Peripheral Trigger: No
* Malicious Filesystem Trigger: No
But wait... Let me double-check something. Is it possible for `wdev->netdev` to be NULL *for any other reason*? Could it be happening during interface creation when the event is processed concurrently? I have to look into the notification chain, specifically `cfg80211_netdev_notifier_call`. I see a `NETDEV_POST_INIT` case that initializes `wdev->netdev`. That *should* be fine.
But what about `nl80211_new_interface`? I see it calls `rdev_add_virtual_intf`. For `NL80211_IFTYPE_P2P_DEVICE`, it *doesn't* create a netdev. It just allocates a `wdev` and adds it to the list. That makes the `wdev->netdev` NULL. OKAY. This is a very interesting detail.
I need to confirm there is no other path or any other timing problem where `wdev->netdev` is accessed when it is null. What about the function `cfg80211_calculate_bi_data`? Here it is:
```c
/* skip wdevs not active on the given wiphy radio */
if (radio_idx >= 0 &&
!(rdev_get_radio_mask(rdev, wdev->netdev) & BIT(radio_idx)))
continue;
```
This is the key. The code added in commit `cfg80211: calculate beacon interval data per radio` is going to make
|
| 81/2 |
2026/06/27 02:09 |
tool |
git-log |
10m
Error:
Args: map[CodeRegexp:cfg80211_calculate_bi_data Count:5]
Results:
|
| 82/2 |
2026/06/27 02:19 |
llm |
expert |
0m
Model:
Tokens:
input: 98575
output: 46
thoughts: 14
Thoughts: Okay, here's my attempt at summarizing the thought process, as if it were my own, assuming I'm an expert in the field and restricting it to the specified file:
**Focusing on net/wireless/util.c**
Alright, let's zero in on `net/wireless/util.c`. That's where a lot of the core, low-level wireless utility functions reside – stuff that's probably used by a myriad of drivers and higher-level wireless components. Given my expertise, I already have a mental map of what's *likely* in there: functions for things like handling MAC addresses, calculating bitmasks for capabilities, converting between different wireless data formats, managing regulatory domain information... all the nitty-gritty details.
I'm thinking about the potential areas I might need to review. I should keep in mind common security issues such as buffer overflows or integer overflows, particularly when dealing with data derived from the wireless medium itself. Also, how the code handles different endianness, considering that wireless data can come from systems with potentially different architectures. I need to look for any potential race conditions if the utility functions access shared data or global variables that might be touched by multiple threads. In that file, there are likely a variety of functions, I will look to see how the code is structured, the naming conventions, and how well it is commented. I will also be looking for any inefficiencies such as unnecessary loops or duplicated calculations.
I also expect to find some critical functions that translate some hardware representation to some Linux netlink structure. The Linux netlink structure would need to have specific memory allocation and deallocation functions in place. The code must handle the memory in a way that minimizes fragmentation, in particular if large amounts of data are passed over time.
|
| 83/2 |
2026/06/27 02:19 |
tool |
git-log |
0m
Args: map[CodeRegexp:cfg80211_calculate_bi_data Count:5 PathPrefix:net/wireless/util.c]
Results: map[Output:4c8dea638c16 cfg80211: validate beacon int as part of iface combinations
]
|
| 84/2 |
2026/06/27 02:19 |
llm |
expert |
0m
Model:
Tokens:
input: 99043
output: 25
thoughts: 17
Thoughts: Okay, let's dive into commit `4c8dea638c16` and see what's what. I'm going to approach this with my usual methodical eye, focusing on the key aspects that matter. I want to quickly grasp the implications of this commit, and how it might impact the project as a whole. I'll be looking for potential side effects, performance considerations, and any subtle changes in architecture.
|
| 85/2 |
2026/06/27 02:19 |
tool |
git-show |
0m
Args:
Results: map[Output:commit 4c8dea638c16141adb046fd2e0cab51dfe43650c
Author: Johannes Berg <johannes.berg@intel.com>
Date: Fri Oct 21 14:25:13 2016 +0200
cfg80211: validate beacon int as part of iface combinations
Remove the pointless checking against interface combinations in
the initial basic beacon interval validation, that currently isn't
taking into account radar detection or channels properly. Instead,
just validate the basic range there, and then delay real checking
to the interface combination validation that drivers must do.
This means that drivers wanting to use the beacon_int_min_gcd will
now have to pass the new_beacon_int when validating the AP/mesh
start.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ec39f891b7a3..d1ffbc3a8e55 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -784,19 +784,15 @@ struct cfg80211_csa_settings {
* @iftype_num: array with the number of interfaces of each interface
* type. The index is the interface type as specified in &enum
* nl80211_iftype.
- * @beacon_int_gcd: a value specifying GCD of all beaconing interfaces,
- * the GCD of a single value is considered the value itself, so for
- * a single interface this should be set to that interface's beacon
- * interval
- * @beacon_int_different: a flag indicating whether or not all beacon
- * intervals (of beaconing interfaces) are different or not.
+ * @new_beacon_int: set this to the beacon interval of a new interface
+ * that's not operating yet, if such is to be checked as part of
+ * the verification
*/
struct iface_combination_params {
int num_different_channels;
u8 radar_detect;
int iftype_num[NUM_NL80211_IFTYPES];
- u32 beacon_int_gcd;
- bool beacon_int_different;
+ u32 new_beacon_int;
};
/**
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 78bf53705466..7681b65c4a3b 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -13,6 +13,7 @@
#include <net/dsfield.h>
#include <linux/if_vlan.h>
#include <linux/mpls.h>
+#include <linux/gcd.h>
#include "core.h"
#include "rdev-ops.h"
@@ -1558,47 +1559,53 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
}
EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
-int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
- enum nl80211_iftype iftype, u32 beacon_int)
+static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
+ u32 *beacon_int_gcd,
+ bool *beacon_int_different)
{
struct wireless_dev *wdev;
- struct iface_combination_params params = {
- .beacon_int_gcd = beacon_int, /* GCD(n) = n */
- };
- if (beacon_int < 10 || beacon_int > 10000)
- return -EINVAL;
+ *beacon_int_gcd = 0;
+ *beacon_int_different = false;
- params.iftype_num[iftype] = 1;
- list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
+ list_for_each_entry(wdev, &wiphy->wdev_list, list) {
if (!wdev->beacon_interval)
continue;
- params.iftype_num[wdev->iftype]++;
- }
-
- list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
- u32 bi_prev = wdev->beacon_interval;
-
- if (!wdev->beacon_interval)
+ if (!*beacon_int_gcd) {
+ *beacon_int_gcd = wdev->beacon_interval;
continue;
+ }
- /* slight optimisation - skip identical BIs */
- if (wdev->beacon_interval == beacon_int)
+ if (wdev->beacon_interval == *beacon_int_gcd)
continue;
- params.beacon_int_different = true;
-
- /* Get the GCD */
- while (bi_prev != 0) {
- u32 tmp_bi = bi_prev;
+ *beacon_int_different = true;
+ *beacon_int_gcd = gcd(*beacon_int_gcd, wdev->beacon_interval);
+ }
- bi_prev = params.beacon_int_gcd % bi_prev;
- params.beacon_int_gcd = tmp_bi;
- }
+ if (new_beacon_int && *beacon_int_gcd != new_beacon_int) {
+ if (*beacon_int_gcd)
+ *beacon_int_different = true;
+ *beacon_int_gcd = gcd(*beacon_int_gcd, new_beacon_int);
}
+}
- return cfg80211_check_combinations(&rdev->wiphy, ¶ms);
+int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
+ enum nl80211_iftype iftype, u32 beacon_int)
+{
+ /*
+ * This is just a basic pre-condition check; if interface combinations
+ * are possible the driver must already be checking those with a call
+ * to cfg80211_check_combinations(), in which case we'll validate more
+ * through the cfg80211_calculate_bi_data() call and code in
+ * cfg80211_iter_combinations().
+ */
+
+ if (beacon_int < 10 || beacon_int > 10000)
+ return -EINVAL;
+
+ return 0;
}
int cfg80211_iter_combinations(struct wiphy *wiphy,
@@ -1612,6 +1619,21 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
int i, j, iftype;
int num_interfaces = 0;
u32 used_iftypes = 0;
+ u32 beacon_int_gcd;
+ bool beacon_int_different;
+
+ /*
+ * This is a bit strange, since the iteration used to rely only on
+ * the data given by the driver, but here it now relies on context,
+ * in form of the currently operating interfaces.
+ * This is OK for all current users, and saves us from having to
+ * push the GCD calculations into all the drivers.
+ * In the future, this should probably rely more on data that's in
+ * cfg80211 already - the only thing not would appear to be any new
+ * interfaces (while being brought up) and channel/radar data.
+ */
+ cfg80211_calculate_bi_data(wiphy, params->new_beacon_int,
+ &beacon_int_gcd, &beacon_int_different);
if (params->radar_detect) {
rcu_read_lock();
@@ -1674,12 +1696,11 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
if ((all_iftypes & used_iftypes) != used_iftypes)
goto cont;
- if (params->beacon_int_gcd) {
+ if (beacon_int_gcd) {
if (c->beacon_int_min_gcd &&
- params->beacon_int_gcd < c->beacon_int_min_gcd)
+ beacon_int_gcd < c->beacon_int_min_gcd)
goto cont;
- if (!c->beacon_int_min_gcd &&
- params->beacon_int_different)
+ if (!c->beacon_int_min_gcd && beacon_int_different)
goto cont;
}
]
|
| 86/2 |
2026/06/27 02:19 |
llm |
expert |
0m
Model:
Tokens:
input: 101542
output: 42
thoughts: 47
Thoughts: Okay, here's my interpretation of those thoughts, framed as my own:
**Investigating a Late Addition**
Hmm, hold on a second. I seem to recall `rdev_get_radio_mask` being a function that was integrated later in the development cycle. I can't quite place the context.
Let's quickly confirm. My mental map of the driver code has me thinking, it looks like `cfg80211_calculate_bi_data` is the most likely place to start looking for its implementation or usage. Let me quickly examine that function's surrounding code and trace back its possible call paths in order to refresh my understanding.
|
| 87/2 |
2026/06/27 02:19 |
tool |
git-log |
0m
Args: map[CodeRegexp:rdev_get_radio_mask Count:5 PathPrefix:net/wireless/util.c]
Results: map[Output:abb4cfe3661a wifi: cfg80211: extend interface combination check for multi-radio
]
|
| 88/2 |
2026/06/27 02:19 |
llm |
expert |
0m
Model:
Tokens:
input: 101811
output: 23
thoughts: 15
Thoughts: Okay, let's dive into commit `abb4cfe3661a`. What's the core change here? I need to quickly grasp the implications. This commit looks like a major refactoring of the error handling system. Interesting. I see a shift towards a more centralized approach, which could mean improved maintainability and potentially better error reporting. The old system was… well, let's just say it had its quirks. I'm already mentally comparing this to the previous implementation. Are they utilizing a standard error hierarchy? That would be ideal for consistent error classification. A well-defined hierarchy drastically improves debugging and allows for more targeted exception handling. I need to check if they've accounted for all the edge cases. I'll need to dig into the new exception classes and their relationship to each other. Are there any potential performance bottlenecks introduced by this centralized approach? I'll have to look for unnecessary overhead or excessive logging, that would be a serious issue. I hope they've included sufficient unit tests to validate the new system and ensure backward compatibility. I'll be scrutinizing those tests closely. Overall, it's a bold move, and depending on the details, this could be a big win for the project. Let's see if the implementation lives up to the promise.
|
| 89/2 |
2026/06/27 02:19 |
tool |
git-show |
0m
Args:
Results: map[Output:commit abb4cfe3661aa05426916b21164f88ca5a405a3a
Author: Felix Fietkau <nbd@nbd.name>
Date: Tue Jul 9 10:38:31 2024 +0200
wifi: cfg80211: extend interface combination check for multi-radio
Add a field in struct iface_combination_params to check per-radio
interface combinations instead of per-wiphy ones.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Link: https://patch.msgid.link/32b28da89c2d759b0324deeefe2be4cee91de18e.1720514221.git-series.nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a00cf80e61dc..4767e2c76b01 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1598,6 +1598,7 @@ struct cfg80211_color_change_settings {
*
* Used to pass interface combination parameters
*
+ * @radio_idx: wiphy radio index or -1 for global
* @num_different_channels: the number of different channels we want
* to use for verification
* @radar_detect: a bitmap where each bit corresponds to a channel
@@ -1611,6 +1612,7 @@ struct cfg80211_color_change_settings {
* the verification
*/
struct iface_combination_params {
+ int radio_idx;
int num_different_channels;
u8 radar_detect;
int iftype_num[NUM_NL80211_IFTYPES];
@@ -4580,6 +4582,8 @@ struct mgmt_frame_regs {
*
* @set_hw_timestamp: Enable/disable HW timestamping of TM/FTM frames.
* @set_ttlm: set the TID to link mapping.
+ * @get_radio_mask: get bitmask of radios in use.
+ * (invoked with the wiphy mutex held)
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -4941,6 +4945,7 @@ struct cfg80211_ops {
struct cfg80211_set_hw_timestamp *hwts);
int (*set_ttlm)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ttlm_params *params);
+ u32 (*get_radio_mask)(struct wiphy *wiphy, struct net_device *dev);
};
/*
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index c6d5f73119d8..27f0db2e9796 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3944,6 +3944,7 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
int total = 1;
struct iface_combination_params params = {
.radar_detect = radar_detect,
+ .radio_idx = -1,
};
lockdep_assert_wiphy(local->hw.wiphy);
@@ -4034,7 +4035,9 @@ int ieee80211_max_num_channels(struct ieee80211_local *local)
struct ieee80211_chanctx *ctx;
u32 max_num_different_channels = 1;
int err;
- struct iface_combination_params params = {0};
+ struct iface_combination_params params = {
+ .radio_idx = -1,
+ };
lockdep_assert_wiphy(local->hw.wiphy);
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 8f15658002ee..ec3f4aa1c807 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1532,4 +1532,16 @@ rdev_set_ttlm(struct cfg80211_registered_device *rdev,
return ret;
}
+
+static inline u32
+rdev_get_radio_mask(struct cfg80211_registered_device *rdev,
+ struct net_device *dev)
+{
+ struct wiphy *wiphy = &rdev->wiphy;
+
+ if (!rdev->ops->get_radio_mask)
+ return 0;
+
+ return rdev->ops->get_radio_mask(wiphy, dev);
+}
#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/util.c b/net/wireless/util.c
index af6ec719567f..2492f259621f 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -2307,13 +2307,16 @@ static int cfg80211_wdev_bi(struct wireless_dev *wdev)
static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
u32 *beacon_int_gcd,
- bool *beacon_int_different)
+ bool *beacon_int_different,
+ int radio_idx)
{
+ struct cfg80211_registered_device *rdev;
struct wireless_dev *wdev;
*beacon_int_gcd = 0;
*beacon_int_different = false;
+ rdev = wiphy_to_rdev(wiphy);
list_for_each_entry(wdev, &wiphy->wdev_list, list) {
int wdev_bi;
@@ -2321,6 +2324,11 @@ static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
if (wdev->valid_links)
continue;
+ /* skip wdevs not active on the given wiphy radio */
+ if (radio_idx >= 0 &&
+ !(rdev_get_radio_mask(rdev, wdev->netdev) & BIT(radio_idx)))
+ continue;
+
wdev_bi = cfg80211_wdev_bi(wdev);
if (!wdev_bi)
@@ -2368,14 +2376,19 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
void *data),
void *data)
{
+ const struct wiphy_radio *radio = NULL;
+ const struct ieee80211_iface_combination *c, *cs;
const struct ieee80211_regdomain *regdom;
enum nl80211_dfs_regions region = 0;
- int i, j, iftype;
+ int i, j, n, iftype;
int num_interfaces = 0;
u32 used_iftypes = 0;
u32 beacon_int_gcd;
bool beacon_int_different;
+ if (params->radio_idx >= 0)
+ radio = &wiphy->radio[params->radio_idx];
+
/*
* This is a bit strange, since the iteration used to rely only on
* the data given by the driver, but here it now relies on context,
@@ -2387,7 +2400,8 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
* interfaces (while being brought up) and channel/radar data.
*/
cfg80211_calculate_bi_data(wiphy, params->new_beacon_int,
- &beacon_int_gcd, &beacon_int_different);
+ &beacon_int_gcd, &beacon_int_different,
+ params->radio_idx);
if (params->radar_detect) {
rcu_read_lock();
@@ -2404,13 +2418,18 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
used_iftypes |= BIT(iftype);
}
- for (i = 0; i < wiphy->n_iface_combinations; i++) {
- const struct ieee80211_iface_combination *c;
+ if (radio) {
+ cs = radio->iface_combinations;
+ n = radio->n_iface_combinations;
+ } else {
+ cs = wiphy->iface_combinations;
+ n = wiphy->n_iface_combinations;
+ }
+ for (i = 0; i < n; i++) {
struct ieee80211_iface_limit *limits;
u32 all_iftypes = 0;
- c = &wiphy->iface_combinations[i];
-
+ c = &cs[i];
if (num_interfaces > c->max_interfaces)
continue;
if (params->num_different_channels > c->num_different_channels)
]
|
| 90/2 |
2026/06/27 02:19 |
llm |
expert |
0m
Model:
Tokens:
input: 104779
output: 66
thoughts: 357
Thoughts: **My Analysis of the Vulnerability**
Okay, so looking at this, it seems like commit `abb4cfe3661a` introduced these `rdev_get_radio_mask` and `radio_idx` variables, which is a key part of how this bug manifested. The core issue is that `rdev_get_radio_mask` is being called with `wdev->netdev`, and *that* `netdev` pointer can, and apparently does, end up being NULL sometimes. The problem lies within `mac80211`'s `get_radio_mask` implementation, because it doesn't handle a NULL `dev` pointer gracefully, it assumes it's always valid.
So, in essence, it's a NULL pointer dereference within `mac80211`'s `ieee80211_get_radio_mask` function, triggered by a NULL `dev`. This happens specifically when `cfg80211_calculate_bi_data` is called with a non-negative `radio_idx` value, and there exists a wireless device (`wdev`) whose `netdev` pointer is NULL. This null `netdev` pointer happens when the interface type is set to `NL80211_IFTYPE_P2P_DEVICE` (and possibly other non-standard device types). This gets triggered by the call to `ieee80211_max_num_channels` from within `mac80211`. That function gets called whenever a new channel context is created.
The real kicker here is the access control. Creating a new channel context requires `CAP_NET_ADMIN` privileges. This is key.
Therefore, my conclusions are that this is not exploitable to gain further privileges and is a Denial of Service. My findings are that the vulnerability cannot be used by an unprivileged user. It does not look like there is a way to trigger this from inside a VM guest, or VM host. It can't be triggered by any network events, peripherals, or filesystem events.
Therefore, the final assessment will be:
* Exploitable: False
* DenialOfService: True
* Unprivileged: False
* UserNamespace: False
* VMGuestTrigger: False
* VMHostTrigger: False
* NetworkTrigger: False
* RemoteTrigger: False
* PeripheralTrigger: False
* FilesystemTrigger: False
I will now `set-results`.
|
| 91/2 |
2026/06/27 02:20 |
tool |
set-results |
0m
Args: map[DenialOfService:true Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:false UserNamespace:false VMGuestTrigger:false VMHostTrigger:false]
Results: map[DenialOfService:true Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:false UserNamespace:false VMGuestTrigger:false VMHostTrigger:false]
|
| 92/2 |
2026/06/27 02:20 |
llm |
expert |
0m
Model:
Tokens:
input: 105806
output: 727
thoughts: 451
Thoughts: **My Analysis of the Kernel Crash**
Okay, the results are in. Time to wrap this up into a concise explanation.
So, here's what's happening: we've got a nasty NULL pointer dereference, specifically in `__ieee80211_get_radio_mask`, which is being called through `ieee80211_get_radio_mask` within the `mac80211` module. My analysis shows this boils down to an issue in how the system handles wireless devices. The function `cfg80211_calculate_bi_data` is the culprit. It iterates through wireless devices (`wdev`), and within that loop, it calls `rdev_get_radio_mask`, which takes `wdev->netdev` as an argument. The problem is that not *all* wireless devices are created equal. Devices like P2P Devices or NAN interfaces don't necessarily have a `netdev` associated with them. So, `wdev->netdev` ends up being NULL in these cases.
The `mac80211` implementation of `get_radio_mask` is the next point of failure. It doesn't perform a null check on `dev` before calling `IEEE80211_DEV_TO_SUB_IF(dev)`, which then uses `netdev_priv(dev)`. That's where we get the crash, as it derives a pointer from NULL (like `0xec0`) and subsequent accesses to `sdata->vif.active_links` trigger a General Protection Fault or NULL pointer dereference.
Now, while it's a kernel panic – a denial-of-service, essentially – the good news is that it's not exploitable for privilege escalation or information leakage. This is because the crash results from a small offset relative to the null pointer.
To trigger this, you'd need to:
1. Create a wireless interface that *doesn't* have a `netdev`. Think of a P2P Device.
2. Then you need to trigger an action that causes interface combinations per radio to be evaluated, such as joining an IBSS network. This action, in turn, calls `ieee80211_max_num_channels` with `radio_idx >= 0`.
The catch? Both of those actions require `CAP_NET_ADMIN` privileges in the network namespace where the wireless device resides – typically, the initial network namespace. So, it's not something an unprivileged user can trigger, nor can it be initiated from inside an unprivileged user namespace. We can safely conclude this is also not remotely exploitable or via malicious peripherals or filesystems.
|
| 93/1 |
2026/06/27 02:20 |
action |
format-explanation |
0m
Results: map[Explanation:**Bug Analysis:**
The crash is a NULL pointer dereference occurring in
`__ieee80211_get_radio_mask` within the `mac80211` subsystem.
The sequence of events leading to the crash is as follows:
1. When a new channel context is being created (e.g., when joining an IBSS
network), `mac80211` checks if it can create a new context by calling
`ieee80211_max_num_channels(local, radio_idx)`.
2. This invokes `cfg80211_iter_combinations()` with a specific `radio_idx >= 0`.
3. `cfg80211_iter_combinations()` calls `cfg80211_calculate_bi_data()`, which
iterates over all wireless devices (`wdev`) on the wiphy to calculate beacon
interval data.
4. For each `wdev`, it checks if the device is active on the given radio by
calling `rdev_get_radio_mask(rdev, wdev->netdev)`.
5. However, certain interface types (such as `NL80211_IFTYPE_P2P_DEVICE` or
`NL80211_IFTYPE_NAN`) do not have an associated `netdev`, meaning `wdev->netdev`
is `NULL`.
6. `mac80211`'s implementation of the `get_radio_mask` callback
(`ieee80211_get_radio_mask`) does not check if the `dev` pointer is `NULL`. It
directly calls `IEEE80211_DEV_TO_SUB_IF(dev)`, which uses `netdev_priv(dev)`.
7. `netdev_priv(NULL)` returns a small offset (e.g., `0xec0`), and the
subsequent attempt to access `sdata->vif.active_links` in
`__ieee80211_get_radio_mask` results in a general protection fault or NULL
pointer dereference.
**Security Impact:**
* **Exploitable:** No. The bug is a read access to a small offset relative to a
NULL pointer (e.g., `0x34fa`). The memory access will reliably page fault and
crash the kernel. It cannot be used for memory corruption, privilege escalation,
or information leaks.
* **Denial of Service:** Yes. Triggering the bug results in a kernel oops/panic,
leading to a local denial of service.
* **Accessible From Unprivileged Processes / User Namespaces:** No. To trigger
this bug, a user must first create a wireless interface without a `netdev` (like
a P2P Device) and then initiate a connection that creates a new channel context
(like joining an IBSS). Both of these `nl80211` commands require `CAP_NET_ADMIN`
in the network namespace of the wireless device. Since wireless devices
typically reside in the initial network namespace and cannot be moved by
unprivileged users, this is completely inaccessible to unprivileged processes or
from within unprivileged user namespaces.
* **Remote / Peripheral / VM Triggers:** No. The bug is triggered strictly via
local administrative configuration commands (netlink) and is not reachable via
remote network packets, malicious USB devices, or VM guest interactions.]
|