| 0/0 |
2026/08/19 16:45 |
flow |
assessment-security |
36m
Results: map[DenialOfService:true Explanation:Based on the analysis of the bug report and the kernel source code, here is the
assessment of the vulnerability:
**Root Cause Analysis:**
The bug is a memory leak of a `struct mesh_csa_settings` object. When a channel
switch is initiated on a mesh interface (e.g., via the
`NL80211_CMD_CHANNEL_SWITCH` netlink command), `ieee80211_mesh_csa_beacon()` is
called. This function allocates a new `mesh_csa_settings` object and assigns it
to `sdata->u.mesh.csa` (`ifmsh->csa`).
Under normal circumstances, when the channel switch completes,
`ieee80211_mesh_finish_csa()` is called, which properly frees `ifmsh->csa`.
However, if the mesh interface is stopped or destroyed (e.g., by bringing the
interface down or destroying the network namespace) while the channel switch is
still active, the cleanup routines (`ieee80211_do_stop()`,
`ieee80211_stop_mesh()`, and `ieee80211_mesh_teardown_sdata()`) fail to free the
pending `ifmsh->csa` pointer. This results in the memory leak reported by
kmemleak.
**Exploitability:**
This is a pure memory leak. While an attacker could repeatedly trigger this to
exhaust system memory (leading to an Out-Of-Memory condition and system
instability), it does not lead to memory corruption (like use-after-free or
out-of-bounds access), privilege escalation, or information leaks. Therefore, it
is classified as a Denial of Service (DoS) but not Exploitable for code
execution.
**Privilege Requirements:**
To trigger this bug, a user must be able to issue `NL80211_CMD_JOIN_MESH` and
`NL80211_CMD_CHANNEL_SWITCH` commands, and subsequently bring down or destroy
the interface. In the `mac80211` netlink policy (`nl80211_small_ops`), these
commands are flagged with `GENL_UNS_ADMIN_PERM`. This means they require the
`CAP_NET_ADMIN` capability.
- **Unprivileged Processes:** Cannot trigger the bug because they lack
`CAP_NET_ADMIN`.
- **User Namespaces:** Can trigger the bug, because `GENL_UNS_ADMIN_PERM` allows
the commands to be executed if the process has `CAP_NET_ADMIN` within its own
user/network namespace.
**Remote/Peripheral Triggers:**
While a remote attacker could potentially send a Channel Switch Announcement
(CSA) management frame over the air to initiate a channel switch on a victim's
mesh node, they cannot remotely force the victim's interface to be stopped or
destroyed to actually trigger the memory leak. Thus, it is not considered
remotely triggerable. It also does not involve malicious filesystems or
untrusted physical peripherals. Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:false UserNamespace:true VMGuestTrigger:false VMHostTrigger:false]
|
| 1/1 |
2026/08/19 16:45 |
action |
syz-repro-to-c-repro |
0m
Results: map[SimplifiedCRepro:// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <endian.h>
#include <errno.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/genetlink.h>
#include <linux/if_addr.h>
#include <linux/if_link.h>
#include <linux/in6.h>
#include <linux/neighbour.h>
#include <linux/net.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/veth.h>
struct nlmsg {
char* pos;
int nesting;
struct nlattr* nested[8];
char buf[4096];
};
static void netlink_init(struct nlmsg* nlmsg, int typ, int flags,
const void* data, int size)
{
memset(nlmsg, 0, sizeof(*nlmsg));
struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf;
hdr->nlmsg_type = typ;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
memcpy(hdr + 1, data, size);
nlmsg->pos = (char*)(hdr + 1) + NLMSG_ALIGN(size);
}
static void netlink_attr(struct nlmsg* nlmsg, int typ,
const void* data, int size)
{
struct nlattr* attr = (struct nlattr*)nlmsg->pos;
attr->nla_len = sizeof(*attr) + size;
attr->nla_type = typ;
if (size > 0)
memcpy(attr + 1, data, size);
nlmsg->pos += NLMSG_ALIGN(attr->nla_len);
}
static int netlink_send_ext(struct nlmsg* nlmsg, int sock,
uint16_t reply_type, int* reply_len, bool dofail)
{
if (nlmsg->pos > nlmsg->buf + sizeof(nlmsg->buf) || nlmsg->nesting)
exit(1);
struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf;
hdr->nlmsg_len = nlmsg->pos - nlmsg->buf;
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
ssize_t n = sendto(sock, nlmsg->buf, hdr->nlmsg_len, 0, (struct sockaddr*)&addr, sizeof(addr));
if (n != (ssize_t)hdr->nlmsg_len) {
if (dofail)
exit(1);
return -1;
}
n = recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0);
if (reply_len)
*reply_len = 0;
if (n < 0) {
if (dofail)
exit(1);
return -1;
}
if (n < (ssize_t)sizeof(struct nlmsghdr)) {
errno = EINVAL;
if (dofail)
exit(1);
return -1;
}
if (hdr->nlmsg_type == NLMSG_DONE)
return 0;
if (reply_len && hdr->nlmsg_type == reply_type) {
*reply_len = n;
return 0;
}
if (n < (ssize_t)(sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr))) {
errno = EINVAL;
if (dofail)
exit(1);
return -1;
}
if (hdr->nlmsg_type != NLMSG_ERROR) {
errno = EINVAL;
if (dofail)
exit(1);
return -1;
}
errno = -((struct nlmsgerr*)(hdr + 1))->error;
return -errno;
}
static int netlink_query_family_id(struct nlmsg* nlmsg, int sock, const char* family_name, bool dofail)
{
struct genlmsghdr genlhdr;
memset(&genlhdr, 0, sizeof(genlhdr));
genlhdr.cmd = CTRL_CMD_GETFAMILY;
netlink_init(nlmsg, GENL_ID_CTRL, 0, &genlhdr, sizeof(genlhdr));
netlink_attr(nlmsg, CTRL_ATTR_FAMILY_NAME, family_name, strnlen(family_name, GENL_NAMSIZ - 1) + 1);
int n = 0;
int err = netlink_send_ext(nlmsg, sock, GENL_ID_CTRL, &n, dofail);
if (err < 0) {
return -1;
}
uint16_t id = 0;
struct nlattr* attr = (struct nlattr*)(nlmsg->buf + NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(genlhdr)));
for (; (char*)attr < nlmsg->buf + n; attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) {
if (attr->nla_type == CTRL_ATTR_FAMILY_ID) {
id = *(uint16_t*)(attr + 1);
break;
}
}
if (!id) {
errno = EINVAL;
return -1;
}
recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0);
return id;
}
static long syz_genetlink_get_family_id(volatile long name, volatile long sock_arg)
{
int fd = sock_arg;
if (fd < 0) {
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
if (fd == -1) {
return -1;
}
}
struct nlmsg nlmsg_tmp;
int ret = netlink_query_family_id(&nlmsg_tmp, fd, (char*)name, false);
if ((int)sock_arg < 0)
close(fd);
if (ret < 0) {
return -1;
}
return ret;
}
uint64_t r[7] = {0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x0};
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200001000000ul, /*len=*/0x1000, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
const char* reason;
(void)reason;
intptr_t res = 0;
if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {}
// socket$nl_generic arguments: [
// domain: const = 0x10 (8 bytes)
// type: const = 0x3 (8 bytes)
// proto: const = 0x10 (4 bytes)
// ]
// returns sock_nl_generic
res = syscall(__NR_socket, /*domain=*/0x10ul, /*type=*/3ul, /*proto=*/0x10);
if (res != -1)
r[0] = res;
// syz_genetlink_get_family_id$nl80211 arguments: [
// name: ptr[in, buffer] {
// buffer: {6e 6c 38 30 32 31 31 00} (length 0x8)
// }
// fd: sock_nl_generic (resource)
// ]
// returns nl80211_family_id
memcpy((void*)0x200000000080, "nl80211\000", 8);
res = -1;
res = syz_genetlink_get_family_id(/*name=*/0x200000000080, /*fd=*/-1);
if (res != -1)
r[1] = res;
// ioctl$sock_SIOCGIFINDEX_80211 arguments: [
// fd: sock (resource)
// cmd: const = 0x8933 (4 bytes)
// arg: ptr[out, ifreq_dev_t[nl80211_devnames, nl80211_ifindex]] {
// ifreq_dev_t[nl80211_devnames, nl80211_ifindex] {
// ifr_ifrn: buffer: {77 6c 61 6e 30 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// elem: nl80211_ifindex (resource)
// pad = 0x0 (20 bytes)
// }
// }
// ]
memcpy((void*)0x2000000000c0, "wlan0\000\000\000\000\000\000\000\000\000\000\000", 16);
res = syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/0x8933, /*arg=*/0x2000000000c0ul);
if (res != -1)
r[2] = *(uint32_t*)0x2000000000d0;
// socket$inet arguments: [
// domain: const = 0x2 (8 bytes)
// type: socket_type = 0x2 (8 bytes)
// proto: int32 = 0x0 (4 bytes)
// ]
// returns sock_in
res = syscall(__NR_socket, /*domain=*/2ul, /*type=SOCK_DGRAM*/2ul, /*proto=*/0);
if (res != -1)
r[3] = res;
// ioctl$sock_inet_SIOCSIFFLAGS arguments: [
// fd: sock (resource)
// cmd: const = 0x8914 (4 bytes)
// arg: ptr[in, ifreq_dev_t[devnames, flags[ifru_flags, int16]]] {
// ifreq_dev_t[devnames, flags[ifru_flags, int16]] {
// ifr_ifrn: buffer: {77 6c 61 6e 30 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// elem: ifru_flags = 0x1000 (2 bytes)
// pad = 0x0 (22 bytes)
// }
// }
// ]
memcpy((void*)0x200000000300, "wlan0\000\000\000\000\000\000\000\000\000\000\000", 16);
*(uint16_t*)0x200000000310 = 0x1000;
syscall(__NR_ioctl, /*fd=*/r[3], /*cmd=*/0x8914, /*arg=*/0x200000000300ul);
// sendmsg$NL80211_CMD_SET_INTERFACE arguments: [
// fd: sock_nl_generic (resource)
// msg: ptr[in, msghdr_netlink[netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_SET_INTERFACE, nl80211_wdev_payload], nl80211_policy$set_interface]]] {
// msghdr_netlink[netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_SET_INTERFACE, nl80211_wdev_payload], nl80211_policy$set_interface]] {
// addr: nil
// addrlen: len = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// vec: ptr[in, iovec[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_SET_INTERFACE, nl80211_wdev_payload], nl80211_policy$set_interface]]] {
// iovec[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_SET_INTERFACE, nl80211_wdev_payload], nl80211_policy$set_interface]] {
// addr: ptr[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_SET_INTERFACE, nl80211_wdev_payload], nl80211_policy$set_interface]] {
// netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_SET_INTERFACE, nl80211_wdev_payload], nl80211_policy$set_interface] {
// len: len = 0x24 (4 bytes)
// type: nl80211_family_id (resource)
// flags: netlink_msg_flags = 0x5 (2 bytes)
// seq: int32 = 0x0 (4 bytes)
// pid: int32 = 0x0 (4 bytes)
// payload: msg_nl80211_payload[NL80211_CMD_SET_INTERFACE, nl80211_wdev_payload] {
// genl_hdr: genlmsghdr_t[NL80211_CMD_SET_INTERFACE] {
// cmd: const = 0x6 (1 bytes)
// version: const = 0x0 (1 bytes)
// reserved: const = 0x0 (2 bytes)
// }
// payload: nl80211_wdev_payload {
// NL80211_ATTR_IFINDEX: union optional[nlattr[NL80211_ATTR_IFINDEX, nl80211_ifindex]] {
// val: nlattr_t[const[NL80211_ATTR_IFINDEX, int16], nl80211_ifindex] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0x3 (2 bytes)
// payload: nl80211_ifindex (resource)
// size: buffer: {} (length 0x0)
// }
// }
// NL80211_ATTR_WDEV: union optional[nlattr[NL80211_ATTR_WDEV, nl80211_wdev]] {
// void: buffer: {} (length 0x0)
// }
// }
// }
// attrs: array[nl80211_policy$set_interface] {
// union nl80211_policy$set_interface {
// NL80211_ATTR_IFTYPE: nlattr_t[const[NL80211_ATTR_IFTYPE, int16], flags[nl80211_iftype, int32]] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0x5 (2 bytes)
// payload: nl80211_iftype = 0x7 (4 bytes)
// size: buffer: {} (length 0x0)
// }
// }
// }
// }
// }
// len: len = 0x24 (8 bytes)
// }
// }
// vlen: const = 0x1 (8 bytes)
// ctrl: const = 0x0 (8 bytes)
// ctrllen: const = 0x0 (8 bytes)
// f: send_flags = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// }
// }
// f: send_flags = 0x0 (8 bytes)
// ]
*(uint64_t*)0x200000000100 = 0;
*(uint32_t*)0x200000000108 = 0;
*(uint64_t*)0x200000000110 = 0x2000000001c0;
*(uint64_t*)0x2000000001c0 = 0x200000000180;
*(uint32_t*)0x200000000180 = 0x24;
*(uint16_t*)0x200000000184 = r[1];
*(uint16_t*)0x200000000186 = 5;
*(uint32_t*)0x200000000188 = 0;
*(uint32_t*)0x20000000018c = 0;
*(uint8_t*)0x200000000190 = 6;
*(uint8_t*)0x200000000191 = 0;
*(uint16_t*)0x200000000192 = 0;
*(uint16_t*)0x200000000194 = 8;
*(uint16_t*)0x200000000196 = 3;
*(uint32_t*)0x200000000198 = r[2];
*(uint16_t*)0x20000000019c = 8;
*(uint16_t*)0x20000000019e = 5;
*(uint32_t*)0x2000000001a0 = 7;
*(uint64_t*)0x2000000001c8 = 0x24;
*(uint64_t*)0x200000000118 = 1;
*(uint64_t*)0x200000000120 = 0;
*(uint64_t*)0x200000000128 = 0;
*(uint32_t*)0x200000000130 = 0;
syscall(__NR_sendmsg, /*fd=*/r[0], /*msg=*/0x200000000100ul, /*f=*/0ul);
// ioctl$sock_inet_SIOCSIFFLAGS arguments: [
// fd: sock (resource)
// cmd: const = 0x8914 (4 bytes)
// arg: ptr[in, ifreq_dev_t[devnames, flags[ifru_flags, int16]]] {
// ifreq_dev_t[devnames, flags[ifru_flags, int16]] {
// ifr_ifrn: buffer: {77 6c 61 6e 30 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// elem: ifru_flags = 0x1 (2 bytes)
// pad = 0x0 (22 bytes)
// }
// }
// ]
memcpy((void*)0x200000000000, "wlan0\000\000\000\000\000\000\000\000\000\000\000", 16);
*(uint16_t*)0x200000000010 = 1;
syscall(__NR_ioctl, /*fd=*/r[3], /*cmd=*/0x8914, /*arg=*/0x200000000000ul);
// sendmsg$NL80211_CMD_JOIN_MESH arguments: [
// fd: sock_nl_generic (resource)
// msg: ptr[in, msghdr_netlink[netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_JOIN_MESH, nl80211_wdev_payload], nl80211_policy$join_mesh]]] {
// msghdr_netlink[netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_JOIN_MESH, nl80211_wdev_payload], nl80211_policy$join_mesh]] {
// addr: nil
// addrlen: len = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// vec: ptr[in, iovec[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_JOIN_MESH, nl80211_wdev_payload], nl80211_policy$join_mesh]]] {
// iovec[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_JOIN_MESH, nl80211_wdev_payload], nl80211_policy$join_mesh]] {
// addr: ptr[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_JOIN_MESH, nl80211_wdev_payload], nl80211_policy$join_mesh]] {
// netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_JOIN_MESH, nl80211_wdev_payload], nl80211_policy$join_mesh] {
// len: len = 0x28 (4 bytes)
// type: nl80211_family_id (resource)
// flags: netlink_msg_flags = 0x1 (2 bytes)
// seq: int32 = 0x70bd28 (4 bytes)
// pid: int32 = 0x25dfdbfb (4 bytes)
// payload: msg_nl80211_payload[NL80211_CMD_JOIN_MESH, nl80211_wdev_payload] {
// genl_hdr: genlmsghdr_t[NL80211_CMD_JOIN_MESH] {
// cmd: const = 0x44 (1 bytes)
// version: const = 0x0 (1 bytes)
// reserved: const = 0x0 (2 bytes)
// }
// payload: nl80211_wdev_payload {
// NL80211_ATTR_IFINDEX: union optional[nlattr[NL80211_ATTR_IFINDEX, nl80211_ifindex]] {
// val: nlattr_t[const[NL80211_ATTR_IFINDEX, int16], nl80211_ifindex] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0x3 (2 bytes)
// payload: nl80211_ifindex (resource)
// size: buffer: {} (length 0x0)
// }
// }
// NL80211_ATTR_WDEV: union optional[nlattr[NL80211_ATTR_WDEV, nl80211_wdev]] {
// void: buffer: {} (length 0x0)
// }
// }
// }
// attrs: array[nl80211_policy$join_mesh] {
// union nl80211_policy$join_mesh {
// NL80211_ATTR_MESH_ID: nlattr_t[const[NL80211_ATTR_MESH_ID, int16], ieee80211_mesh_id] {
// nla_len: offsetof = 0xa (2 bytes)
// nla_type: const = 0x18 (2 bytes)
// payload: union ieee80211_mesh_id {
// default: buffer: {03 03 03 03 03 03} (length 0x6)
// }
// size: buffer: {} (length 0x0)
// }
// }
// }
// }
// }
// len: len = 0x28 (8 bytes)
// }
// }
// vlen: const = 0x1 (8 bytes)
// ctrl: const = 0x0 (8 bytes)
// ctrllen: const = 0x0 (8 bytes)
// f: send_flags = 0x85 (4 bytes)
// pad = 0x0 (4 bytes)
// }
// }
// f: send_flags = 0x4c040 (8 bytes)
// ]
*(uint64_t*)0x200000000040 = 0;
*(uint32_t*)0x200000000048 = 0;
*(uint64_t*)0x200000000050 = 0x200000000240;
*(uint64_t*)0x200000000240 = 0x200000000dc0;
*(uint32_t*)0x200000000dc0 = 0x28;
*(uint16_t*)0x200000000dc4 = r[1];
*(uint16_t*)0x200000000dc6 = 1;
*(uint32_t*)0x200000000dc8 = 0x70bd28;
*(uint32_t*)0x200000000dcc = 0x25dfdbfb;
*(uint8_t*)0x200000000dd0 = 0x44;
*(uint8_t*)0x200000000dd1 = 0;
*(uint16_t*)0x200000000dd2 = 0;
*(uint16_t*)0x200000000dd4 = 8;
*(uint16_t*)0x200000000dd6 = 3;
*(uint32_t*)0x200000000dd8 = r[2];
*(uint16_t*)0x200000000ddc = 0xa;
*(uint16_t*)0x200000000dde = 0x18;
memset((void*)0x200000000de0, 3, 6);
*(uint64_t*)0x200000000248 = 0x28;
*(uint64_t*)0x200000000058 = 1;
*(uint64_t*)0x200000000060 = 0;
*(uint64_t*)0x200000000068 = 0;
*(uint32_t*)0x200000000070 = 0x85;
syscall(__NR_sendmsg, /*fd=*/r[0], /*msg=*/0x200000000040ul, /*f=MSG_BATCH|MSG_NOSIGNAL|MSG_MORE|MSG_DONTWAIT*/0x4c040ul);
// syz_genetlink_get_family_id$nl80211 arguments: [
// name: ptr[in, buffer] {
// buffer: {6e 6c 38 30 32 31 31 00} (length 0x8)
// }
// fd: sock_nl_generic (resource)
// ]
// returns nl80211_family_id
memcpy((void*)0x200000000040, "nl80211\000", 8);
res = -1;
res = syz_genetlink_get_family_id(/*name=*/0x200000000040, /*fd=*/-1);
if (res != -1)
r[4] = res;
// socket$nl_generic arguments: [
// domain: const = 0x10 (8 bytes)
// type: const = 0x3 (8 bytes)
// proto: const = 0x10 (4 bytes)
// ]
// returns sock_nl_generic
res = syscall(__NR_socket, /*domain=*/0x10ul, /*type=*/3ul, /*proto=*/0x10);
if (res != -1)
r[5] = res;
// ioctl$sock_SIOCGIFINDEX_80211 arguments: [
// fd: sock (resource)
// cmd: const = 0x8933 (4 bytes)
// arg: ptr[out, ifreq_dev_t[nl80211_devnames, nl80211_ifindex]] {
// ifreq_dev_t[nl80211_devnames, nl80211_ifindex] {
// ifr_ifrn: buffer: {77 6c 61 6e 30 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// elem: nl80211_ifindex (resource)
// pad = 0x0 (20 bytes)
// }
// }
// ]
memcpy((void*)0x2000000003c0, "wlan0\000\000\000\000\000\000\000\000\000\000\000", 16);
res = syscall(__NR_ioctl, /*fd=*/r[5], /*cmd=*/0x8933, /*arg=*/0x2000000003c0ul);
if (res != -1)
r[6] = *(uint32_t*)0x2000000003d0;
// sendmsg$NL80211_CMD_CHANNEL_SWITCH arguments: [
// fd: sock_nl_generic (resource)
// msg: ptr[in, msghdr_netlink[netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_CHANNEL_SWITCH, nl80211_wdev_payload], nl80211_policy$chsw]]] {
// msghdr_netlink[netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_CHANNEL_SWITCH, nl80211_wdev_payload], nl80211_policy$chsw]] {
// addr: nil
// addrlen: len = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// vec: ptr[in, iovec[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_CHANNEL_SWITCH, nl80211_wdev_payload], nl80211_policy$chsw]]] {
// iovec[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_CHANNEL_SWITCH, nl80211_wdev_payload], nl80211_policy$chsw]] {
// addr: ptr[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_CHANNEL_SWITCH, nl80211_wdev_payload], nl80211_policy$chsw]] {
// netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_CHANNEL_SWITCH, nl80211_wdev_payload], nl80211_policy$chsw] {
// len: len = 0x2c (4 bytes)
// type: nl80211_family_id (resource)
// flags: netlink_msg_flags = 0x1 (2 bytes)
// seq: int32 = 0x70bd2a (4 bytes)
// pid: int32 = 0x0 (4 bytes)
// payload: msg_nl80211_payload[NL80211_CMD_CHANNEL_SWITCH, nl80211_wdev_payload] {
// genl_hdr: genlmsghdr_t[NL80211_CMD_CHANNEL_SWITCH] {
// cmd: const = 0x66 (1 bytes)
// version: const = 0x0 (1 bytes)
// reserved: const = 0x0 (2 bytes)
// }
// payload: nl80211_wdev_payload {
// NL80211_ATTR_IFINDEX: union optional[nlattr[NL80211_ATTR_IFINDEX, nl80211_ifindex]] {
// val: nlattr_t[const[NL80211_ATTR_IFINDEX, int16], nl80211_ifindex] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0x3 (2 bytes)
// payload: nl80211_ifindex (resource)
// size: buffer: {} (length 0x0)
// }
// }
// NL80211_ATTR_WDEV: union optional[nlattr[NL80211_ATTR_WDEV, nl80211_wdev]] {
// void: buffer: {} (length 0x0)
// }
// }
// }
// attrs: array[nl80211_policy$chsw] {
// union nl80211_policy$chsw {
// chandef_params: array[nl80211_policy$chandef_params] {
// union nl80211_policy$chandef_params {
// NL80211_ATTR_WIPHY_FREQ: nlattr_t[const[NL80211_ATTR_WIPHY_FREQ, int16], ieee80211_frequency_mhz[int32]] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0x26 (2 bytes)
// payload: union ieee80211_frequency_mhz[int32] {
// default: const = 0x96c (4 bytes)
// }
// size: buffer: {} (length 0x0)
// }
// }
// }
// }
// union nl80211_policy$chsw {
// NL80211_ATTR_CH_SWITCH_COUNT: nlattr_t[const[NL80211_ATTR_CH_SWITCH_COUNT, int16], int32[0:255]] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0xb7 (2 bytes)
// payload: int32 = 0xf9 (4 bytes)
// size: buffer: {} (length 0x0)
// }
// }
// }
// }
// }
// len: len = 0x2c (8 bytes)
// }
// }
// vlen: const = 0x1 (8 bytes)
// ctrl: const = 0x0 (8 bytes)
// ctrllen: const = 0x0 (8 bytes)
// f: send_flags = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// }
// }
// f: send_flags = 0x0 (8 bytes)
// ]
*(uint64_t*)0x200000000200 = 0;
*(uint32_t*)0x200000000208 = 0;
*(uint64_t*)0x200000000210 = 0x2000000001c0;
*(uint64_t*)0x2000000001c0 = 0x2000000032c0;
*(uint32_t*)0x2000000032c0 = 0x2c;
*(uint16_t*)0x2000000032c4 = r[4];
*(uint16_t*)0x2000000032c6 = 1;
*(uint32_t*)0x2000000032c8 = 0x70bd2a;
*(uint32_t*)0x2000000032cc = 0;
*(uint8_t*)0x2000000032d0 = 0x66;
*(uint8_t*)0x2000000032d1 = 0;
*(uint16_t*)0x2000000032d2 = 0;
*(uint16_t*)0x2000000032d4 = 8;
*(uint16_t*)0x2000000032d6 = 3;
*(uint32_t*)0x2000000032d8 = r[6];
*(uint16_t*)0x2000000032dc = 8;
*(uint16_t*)0x2000000032de = 0x26;
*(uint32_t*)0x2000000032e0 = 0x96c;
*(uint16_t*)0x2000000032e4 = 8;
*(uint16_t*)0x2000000032e6 = 0xb7;
*(uint32_t*)0x2000000032e8 = 0xf9;
*(uint64_t*)0x2000000001c8 = 0x2c;
*(uint64_t*)0x200000000218 = 1;
*(uint64_t*)0x200000000220 = 0;
*(uint64_t*)0x200000000228 = 0;
*(uint32_t*)0x200000000230 = 0;
syscall(__NR_sendmsg, /*fd=*/r[5], /*msg=*/0x200000000200ul, /*f=*/0ul);
return 0;
}
]
|
| 2/1 |
2026/08/19 16:45 |
action |
kernel-checkouter |
1m
Results: map[KernelSrc:/app/workdir/cache/src/e9cd96c099aac719e9ecf0353eca7c0eaa3d0f48]
|
| 3/1 |
2026/08/19 16:46 |
action |
kernel-builder |
15m
Results: map[KernelObj:/app/workdir/cache/build/c5b75a73c0c9b2930ed5860eded38fa6aa57e8a2]
|
| 4/1 |
2026/08/19 17:02 |
action |
codesearch-prepare |
11m
Results: map[Index:codesearch-index]
|
| 5/1 |
2026/08/19 17:13 |
agent |
expert |
8m
Model:
Results: map[DenialOfService:true Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:false UserNamespace:true 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:
BUG: memory leak
unreferenced object 0xffff88812b7f6c00 (size 1024):
comm "syz.1.18", pid 6113, jiffies 4294942706
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
d8 a3 92 2d 81 88 ff ff 00 00 00 00 00 00 00 00 ...-............
backtrace (crc 53faf87c):
kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
slab_post_alloc_hook mm/slub.c:4597 [inline]
slab_alloc_node mm/slub.c:4917 [inline]
__kmalloc_cache_noprof+0x359/0x440 mm/slub.c:5485
_kmalloc_noprof include/linux/slab.h:988 [inline]
ieee80211_mesh_csa_beacon+0x2e/0x100 net/mac80211/mesh.c:1547
ieee80211_set_csa_beacon net/mac80211/cfg.c:4674 [inline]
__ieee80211_channel_switch+0xb22/0xed0 net/mac80211/cfg.c:4795
rdev_channel_switch net/wireless/rdev-ops.h:1168 [inline]
nl80211_channel_switch+0x39b/0x780 net/wireless/nl80211.c:12234
genl_family_rcv_msg_doit+0x12e/0x1a0 net/netlink/genetlink.c:1114
genl_family_rcv_msg net/netlink/genetlink.c:1194 [inline]
genl_rcv_msg+0x302/0x440 net/netlink/genetlink.c:1209
netlink_rcv_skb+0x89/0x1c0 net/netlink/af_netlink.c:2556
genl_rcv+0x28/0x40 net/netlink/genetlink.c:1218
netlink_unicast_kernel net/netlink/af_netlink.c:1319 [inline]
netlink_unicast+0x38f/0x4e0 net/netlink/af_netlink.c:1345
netlink_sendmsg+0x335/0x690 net/netlink/af_netlink.c:1900
sock_sendmsg_nosec net/socket.c:800 [inline]
__sock_sendmsg net/socket.c:815 [inline]
____sys_sendmsg+0x54a/0x580 net/socket.c:2709
___sys_sendmsg+0x101/0x140 net/socket.c:2763
__sys_sendmsg+0xcd/0x140 net/socket.c:2795
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0xe9/0x530 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
BUG: memory leak
unreferenced object 0xffff88812b7f5000 (size 1024):
comm "syz.0.17", pid 6117, jiffies 4294942719
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
d8 23 0d 29 81 88 ff ff 00 00 00 00 00 00 00 00 .#.)............
backtrace (crc 6afe8711):
kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
slab_post_alloc_hook mm/slub.c:4597 [inline]
slab_alloc_node mm/slub.c:4917 [inline]
__kmalloc_cache_noprof+0x359/0x440 mm/slub.c:5485
_kmalloc_noprof include/linux/slab.h:988 [inline]
ieee80211_mesh_csa_beacon+0x2e/0x100 net/mac80211/mesh.c:1547
ieee80211_set_csa_beacon net/mac80211/cfg.c:4674 [inline]
__ieee80211_channel_switch+0xb22/0xed0 net/mac80211/cfg.c:4795
rdev_channel_switch net/wireless/rdev-ops.h:1168 [inline]
nl80211_channel_switch+0x39b/0x780 net/wireless/nl80211.c:12234
genl_family_rcv_msg_doit+0x12e/0x1a0 net/netlink/genetlink.c:1114
genl_family_rcv_msg net/netlink/genetlink.c:1194 [inline]
genl_rcv_msg+0x302/0x440 net/netlink/genetlink.c:1209
netlink_rcv_skb+0x89/0x1c0 net/netlink/af_netlink.c:2556
genl_rcv+0x28/0x40 net/netlink/genetlink.c:1218
netlink_unicast_kernel net/netlink/af_netlink.c:1319 [inline]
netlink_unicast+0x38f/0x4e0 net/netlink/af_netlink.c:1345
netlink_sendmsg+0x335/0x690 net/netlink/af_netlink.c:1900
sock_sendmsg_nosec net/socket.c:800 [inline]
__sock_sendmsg net/socket.c:815 [inline]
____sys_sendmsg+0x54a/0x580 net/socket.c:2709
___sys_sendmsg+0x101/0x140 net/socket.c:2763
__sys_sendmsg+0xcd/0x140 net/socket.c:2795
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0xe9/0x530 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
BUG: memory leak
unreferenced object 0xffff88812da3c000 (size 1024):
comm "syz.1.24", pid 6118, jiffies 4294942722
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
d8 a3 92 2d 81 88 ff ff 00 00 00 00 00 00 00 00 ...-............
backtrace (crc 53faf87c):
kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
slab_post_alloc_hook mm/slub.c:4597 [inline]
slab_alloc_node mm/slub.c:4917 [inline]
__kmalloc_cache_noprof+0x359/0x440 mm/slub.c:5485
_kmalloc_noprof include/linux/slab.h:988 [inline]
ieee80211_mesh_csa_beacon+0x2e/0x100 net/mac80211/mesh.c:1547
ieee80211_set_csa_beacon net/mac80211/cfg.c:4674 [inline]
__ieee80211_channel_switch+0xb22/0xed0 net/mac80211/cfg.c:4795
rdev_channel_switch net/wireless/rdev-ops.h:1168 [inline]
nl80211_channel_switch+0x39b/0x780 net/wireless/nl80211.c:12234
genl_family_rcv_msg_doit+0x12e/0x1a0 net/netlink/genetlink.c:1114
genl_family_rcv_msg net/netlink/genetlink.c:1194 [inline]
genl_rcv_msg+0x302/0x440 net/netlink/genetlink.c:1209
netlink_rcv_skb+0x89/0x1c0 net/netlink/af_netlink.c:2556
genl_rcv+0x28/0x40 net/netlink/genetlink.c:1218
netlink_unicast_kernel net/netlink/af_netlink.c:1319 [inline]
netlink_unicast+0x38f/0x4e0 net/netlink/af_netlink.c:1345
netlink_sendmsg+0x335/0x690 net/netlink/af_netlink.c:1900
sock_sendmsg_nosec net/socket.c:800 [inline]
__sock_sendmsg net/socket.c:815 [inline]
____sys_sendmsg+0x54a/0x580 net/socket.c:2709
___sys_sendmsg+0x101/0x140 net/socket.c:2763
__sys_sendmsg+0xcd/0x140 net/socket.c:2795
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0xe9/0x530 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
BUG: memory leak
unreferenced object 0xffff88810b478800 (size 1024):
comm "syz.3.20", pid 6120, jiffies 4294942726
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
d8 a3 19 29 81 88 ff ff 00 00 00 00 00 00 00 00 ...)............
backtrace (crc d3159a3):
kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
slab_post_alloc_hook mm/slub.c:4597 [inline]
slab_alloc_node mm/slub.c:4917 [inline]
__kmalloc_cache_noprof+0x359/0x440 mm/slub.c:5485
_kmalloc_noprof include/linux/slab.h:988 [inline]
ieee80211_mesh_csa_beacon+0x2e/0x100 net/mac80211/mesh.c:1547
ieee80211_set_csa_beacon net/mac80211/cfg.c:4674 [inline]
__ieee80211_channel_switch+0xb22/0xed0 net/mac80211/cfg.c:4795
rdev_channel_switch net/wireless/rdev-ops.h:1168 [inline]
nl80211_channel_switch+0x39b/0x780 net/wireless/nl80211.c:12234
genl_family_rcv_msg_doit+0x12e/0x1a0 net/netlink/genetlink.c:1114
genl_family_rcv_msg net/netlink/genetlink.c:1194 [inline]
genl_rcv_msg+0x302/0x440 net/netlink/genetlink.c:1209
netlink_rcv_skb+0x89/0x1c0 net/netlink/af_netlink.c:2556
genl_rcv+0x28/0x40 net/netlink/genetlink.c:1218
netlink_unicast_kernel net/netlink/af_netlink.c:1319 [inline]
netlink_unicast+0x38f/0x4e0 net/netlink/af_netlink.c:1345
netlink_sendmsg+0x335/0x690 net/netlink/af_netlink.c:1900
sock_sendmsg_nosec net/socket.c:800 [inline]
__sock_sendmsg net/socket.c:815 [inline]
____sys_sendmsg+0x54a/0x580 net/socket.c:2709
___sys_sendmsg+0x101/0x140 net/socket.c:2763
__sys_sendmsg+0xcd/0x140 net/socket.c:2795
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0xe9/0x530 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
BUG: memory leak
unreferenced object 0xffff88812da3c400 (size 1024):
comm "syz.0.25", pid 6123, jiffies 4294942728
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
d8 23 0d 29 81 88 ff ff 00 00 00 00 00 00 00 00 .#.)............
backtrace (crc 6afe8711):
kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
slab_post_alloc_hook mm/slub.c:4597 [inline]
slab_alloc_node mm/slub.c:4917 [inline]
__kmalloc_cache_noprof+0x359/0x440 mm/slub.c:5485
_kmalloc_noprof include/linux/slab.h:988 [inline]
ieee80211_mesh_csa_beacon+0x2e/0x100 net/mac80211/mesh.c:1547
ieee80211_set_csa_beacon net/mac80211/cfg.c:4674 [inline]
__ieee80211_channel_switch+0xb22/0xed0 net/mac80211/cfg.c:4795
rdev_channel_switch net/wireless/rdev-ops.h:1168 [inline]
nl80211_channel_switch+0x39b/0x780 net/wireless/nl80211.c:12234
genl_family_rcv_msg_doit+0x12e/0x1a0 net/netlink/genetlink.c:1114
genl_family_rcv_msg net/netlink/genetlink.c:1194 [inline]
genl_rcv_msg+0x302/0x440 net/netlink/genetlink.c:1209
netlink_rcv_skb+0x89/0x1c0 net/netlink/af_netlink.c:2556
genl_rcv+0x28/0x40 net/netlink/genetlink.c:1218
netlink_unicast_kernel net/netlink/af_netlink.c:1319 [inline]
netlink_unicast+0x38f/0x4e0 net/netlink/af_netlink.c:1345
netlink_sendmsg+0x335/0x690 net/netlink/af_netlink.c:1900
sock_sendmsg_nosec net/socket.c:800 [inline]
__sock_sendmsg net/socket.c:815 [inline]
____sys_sendmsg+0x54a/0x580 net/socket.c:2709
___sys_sendmsg+0x101/0x140 net/socket.c:2763
__sys_sendmsg+0xcd/0x140 net/socket.c:2795
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0xe9/0x530 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
connection error: failed to recv *flatrpc.ExecutorMessageRawT: EOF
It is reproducible with the followint program.
Keep in mind that it may lack the precise threading, sandboxing, and some arguments of a working reproducer.
But it should give an idea of the involved syscalls.
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <endian.h>
#include <errno.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/genetlink.h>
#include <linux/if_addr.h>
#include <linux/if_link.h>
#include <linux/in6.h>
#include <linux/neighbour.h>
#include <linux/net.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/veth.h>
struct nlmsg {
char* pos;
int nesting;
struct nlattr* nested[8];
char buf[4096];
};
static void netlink_init(struct nlmsg* nlmsg, int typ, int flags,
const void* data, int size)
{
memset(nlmsg, 0, sizeof(*nlmsg));
struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf;
hdr->nlmsg_type = typ;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
memcpy(hdr + 1, data, size);
nlmsg->pos = (char*)(hdr + 1) + NLMSG_ALIGN(size);
}
static void netlink_attr(struct nlmsg* nlmsg, int typ,
const void* data, int size)
{
struct nlattr* attr = (struct nlattr*)nlmsg->pos;
attr->nla_len = sizeof(*attr) + size;
attr->nla_type = typ;
if (size > 0)
memcpy(attr + 1, data, size);
nlmsg->pos += NLMSG_ALIGN(attr->nla_len);
}
static int netlink_send_ext(struct nlmsg* nlmsg, int sock,
uint16_t reply_type, int* reply_len, bool dofail)
{
if (nlmsg->pos > nlmsg->buf + sizeof(nlmsg->buf) || nlmsg->nesting)
exit(1);
struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf;
hdr->nlmsg_len = nlmsg->pos - nlmsg->buf;
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
ssize_t n = sendto(sock, nlmsg->buf, hdr->nlmsg_len, 0, (struct sockaddr*)&addr, sizeof(addr));
if (n != (ssize_t)hdr->nlmsg_len) {
if (dofail)
exit(1);
return -1;
}
n = recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0);
if (reply_len)
*reply_len = 0;
if (n < 0) {
if (dofail)
exit(1);
return -1;
}
if (n < (ssize_t)sizeof(struct nlmsghdr)) {
errno = EINVAL;
if (dofail)
exit(1);
return -1;
}
if (hdr->nlmsg_type == NLMSG_DONE)
return 0;
if (reply_len && hdr->nlmsg_type == reply_type) {
*reply_len = n;
return 0;
}
if (n < (ssize_t)(sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr))) {
errno = EINVAL;
if (dofail)
exit(1);
return -1;
}
if (hdr->nlmsg_type != NLMSG_ERROR) {
errno = EINVAL;
if (dofail)
exit(1);
return -1;
}
errno = -((struct nlmsgerr*)(hdr + 1))->error;
return -errno;
}
static int netlink_query_family_id(struct nlmsg* nlmsg, int sock, const char* family_name, bool dofail)
{
struct genlmsghdr genlhdr;
memset(&genlhdr, 0, sizeof(genlhdr));
genlhdr.cmd = CTRL_CMD_GETFAMILY;
netlink_init(nlmsg, GENL_ID_CTRL, 0, &genlhdr, sizeof(genlhdr));
netlink_attr(nlmsg, CTRL_ATTR_FAMILY_NAME, family_name, strnlen(family_name, GENL_NAMSIZ - 1) + 1);
int n = 0;
int err = netlink_send_ext(nlmsg, sock, GENL_ID_CTRL, &n, dofail);
if (err < 0) {
return -1;
}
uint16_t id = 0;
struct nlattr* attr = (struct nlattr*)(nlmsg->buf + NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(genlhdr)));
for (; (char*)attr < nlmsg->buf + n; attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) {
if (attr->nla_type == CTRL_ATTR_FAMILY_ID) {
id = *(uint16_t*)(attr + 1);
break;
}
}
if (!id) {
errno = EINVAL;
return -1;
}
recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0);
return id;
}
static long syz_genetlink_get_family_id(volatile long name, volatile long sock_arg)
{
int fd = sock_arg;
if (fd < 0) {
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
if (fd == -1) {
return -1;
}
}
struct nlmsg nlmsg_tmp;
int ret = netlink_query_family_id(&nlmsg_tmp, fd, (char*)name, false);
if ((int)sock_arg < 0)
close(fd);
if (ret < 0) {
return -1;
}
return ret;
}
uint64_t r[7] = {0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x0};
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200001000000ul, /*len=*/0x1000, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
const char* reason;
(void)reason;
intptr_t res = 0;
if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {}
// socket$nl_generic arguments: [
// domain: const = 0x10 (8 bytes)
// type: const = 0x3 (8 bytes)
// proto: const = 0x10 (4 bytes)
// ]
// returns sock_nl_generic
res = syscall(__NR_socket, /*domain=*/0x10ul, /*type=*/3ul, /*proto=*/0x10);
if (res != -1)
r[0] = res;
// syz_genetlink_get_family_id$nl80211 arguments: [
// name: ptr[in, buffer] {
// buffer: {6e 6c 38 30 32 31 31 00} (length 0x8)
// }
// fd: sock_nl_generic (resource)
// ]
// returns nl80211_family_id
memcpy((void*)0x200000000080, "nl80211\000", 8);
res = -1;
res = syz_genetlink_get_family_id(/*name=*/0x200000000080, /*fd=*/-1);
if (res != -1)
r[1] = res;
// ioctl$sock_SIOCGIFINDEX_80211 arguments: [
// fd: sock (resource)
// cmd: const = 0x8933 (4 bytes)
// arg: ptr[out, ifreq_dev_t[nl80211_devnames, nl80211_ifindex]] {
// ifreq_dev_t[nl80211_devnames, nl80211_ifindex] {
// ifr_ifrn: buffer: {77 6c 61 6e 30 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// elem: nl80211_ifindex (resource)
// pad = 0x0 (20 bytes)
// }
// }
// ]
memcpy((void*)0x2000000000c0, "wlan0\000\000\000\000\000\000\000\000\000\000\000", 16);
res = syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/0x8933, /*arg=*/0x2000000000c0ul);
if (res != -1)
r[2] = *(uint32_t*)0x2000000000d0;
// socket$inet arguments: [
// domain: const = 0x2 (8 bytes)
// type: socket_type = 0x2 (8 bytes)
// proto: int32 = 0x0 (4 bytes)
// ]
// returns sock_in
res = syscall(__NR_socket, /*domain=*/2ul, /*type=SOCK_DGRAM*/2ul, /*proto=*/0);
if (res != -1)
r[3] = res;
// ioctl$sock_inet_SIOCSIFFLAGS arguments: [
// fd: sock (resource)
// cmd: const = 0x8914 (4 bytes)
// arg: ptr[in, ifreq_dev_t[devnames, flags[ifru_flags, int16]]] {
// ifreq_dev_t[devnames, flags[ifru_flags, int16]] {
// ifr_ifrn: buffer: {77 6c 61 6e 30 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// elem: ifru_flags = 0x1000 (2 bytes)
// pad = 0x0 (22 bytes)
// }
// }
// ]
memcpy((void*)0x200000000300, "wlan0\000\000\000\000\000\000\000\000\000\000\000", 16);
*(uint16_t*)0x200000000310 = 0x1000;
syscall(__NR_ioctl, /*fd=*/r[3], /*cmd=*/0x8914, /*arg=*/0x200000000300ul);
// sendmsg$NL80211_CMD_SET_INTERFACE arguments: [
// fd: sock_nl_generic (resource)
// msg: ptr[in, msghdr_netlink[netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_SET_INTERFACE, nl80211_wdev_payload], nl80211_policy$set_interface]]] {
// msghdr_netlink[netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_SET_INTERFACE, nl80211_wdev_payload], nl80211_policy$set_interface]] {
// addr: nil
// addrlen: len = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// vec: ptr[in, iovec[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_SET_INTERFACE, nl80211_wdev_payload], nl80211_policy$set_interface]]] {
// iovec[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_SET_INTERFACE, nl80211_wdev_payload], nl80211_policy$set_interface]] {
// addr: ptr[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_SET_INTERFACE, nl80211_wdev_payload], nl80211_policy$set_interface]] {
// netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_SET_INTERFACE, nl80211_wdev_payload], nl80211_policy$set_interface] {
// len: len = 0x24 (4 bytes)
// type: nl80211_family_id (resource)
// flags: netlink_msg_flags = 0x5 (2 bytes)
// seq: int32 = 0x0 (4 bytes)
// pid: int32 = 0x0 (4 bytes)
// payload: msg_nl80211_payload[NL80211_CMD_SET_INTERFACE, nl80211_wdev_payload] {
// genl_hdr: genlmsghdr_t[NL80211_CMD_SET_INTERFACE] {
// cmd: const = 0x6 (1 bytes)
// version: const = 0x0 (1 bytes)
// reserved: const = 0x0 (2 bytes)
// }
// payload: nl80211_wdev_payload {
// NL80211_ATTR_IFINDEX: union optional[nlattr[NL80211_ATTR_IFINDEX, nl80211_ifindex]] {
// val: nlattr_t[const[NL80211_ATTR_IFINDEX, int16], nl80211_ifindex] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0x3 (2 bytes)
// payload: nl80211_ifindex (resource)
// size: buffer: {} (length 0x0)
// }
// }
// NL80211_ATTR_WDEV: union optional[nlattr[NL80211_ATTR_WDEV, nl80211_wdev]] {
// void: buffer: {} (length 0x0)
// }
// }
// }
// attrs: array[nl80211_policy$set_interface] {
// union nl80211_policy$set_interface {
// NL80211_ATTR_IFTYPE: nlattr_t[const[NL80211_ATTR_IFTYPE, int16], flags[nl80211_iftype, int32]] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0x5 (2 bytes)
// payload: nl80211_iftype = 0x7 (4 bytes)
// size: buffer: {} (length 0x0)
// }
// }
// }
// }
// }
// len: len = 0x24 (8 bytes)
// }
// }
// vlen: const = 0x1 (8 bytes)
// ctrl: const = 0x0 (8 bytes)
// ctrllen: const = 0x0 (8 bytes)
// f: send_flags = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// }
// }
// f: send_flags = 0x0 (8 bytes)
// ]
*(uint64_t*)0x200000000100 = 0;
*(uint32_t*)0x200000000108 = 0;
*(uint64_t*)0x200000000110 = 0x2000000001c0;
*(uint64_t*)0x2000000001c0 = 0x200000000180;
*(uint32_t*)0x200000000180 = 0x24;
*(uint16_t*)0x200000000184 = r[1];
*(uint16_t*)0x200000000186 = 5;
*(uint32_t*)0x200000000188 = 0;
*(uint32_t*)0x20000000018c = 0;
*(uint8_t*)0x200000000190 = 6;
*(uint8_t*)0x200000000191 = 0;
*(uint16_t*)0x200000000192 = 0;
*(uint16_t*)0x200000000194 = 8;
*(uint16_t*)0x200000000196 = 3;
*(uint32_t*)0x200000000198 = r[2];
*(uint16_t*)0x20000000019c = 8;
*(uint16_t*)0x20000000019e = 5;
*(uint32_t*)0x2000000001a0 = 7;
*(uint64_t*)0x2000000001c8 = 0x24;
*(uint64_t*)0x200000000118 = 1;
*(uint64_t*)0x200000000120 = 0;
*(uint64_t*)0x200000000128 = 0;
*(uint32_t*)0x200000000130 = 0;
syscall(__NR_sendmsg, /*fd=*/r[0], /*msg=*/0x200000000100ul, /*f=*/0ul);
// ioctl$sock_inet_SIOCSIFFLAGS arguments: [
// fd: sock (resource)
// cmd: const = 0x8914 (4 bytes)
// arg: ptr[in, ifreq_dev_t[devnames, flags[ifru_flags, int16]]] {
// ifreq_dev_t[devnames, flags[ifru_flags, int16]] {
// ifr_ifrn: buffer: {77 6c 61 6e 30 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// elem: ifru_flags = 0x1 (2 bytes)
// pad = 0x0 (22 bytes)
// }
// }
// ]
memcpy((void*)0x200000000000, "wlan0\000\000\000\000\000\000\000\000\000\000\000", 16);
*(uint16_t*)0x200000000010 = 1;
syscall(__NR_ioctl, /*fd=*/r[3], /*cmd=*/0x8914, /*arg=*/0x200000000000ul);
// sendmsg$NL80211_CMD_JOIN_MESH arguments: [
// fd: sock_nl_generic (resource)
// msg: ptr[in, msghdr_netlink[netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_JOIN_MESH, nl80211_wdev_payload], nl80211_policy$join_mesh]]] {
// msghdr_netlink[netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_JOIN_MESH, nl80211_wdev_payload], nl80211_policy$join_mesh]] {
// addr: nil
// addrlen: len = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// vec: ptr[in, iovec[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_JOIN_MESH, nl80211_wdev_payload], nl80211_policy$join_mesh]]] {
// iovec[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_JOIN_MESH, nl80211_wdev_payload], nl80211_policy$join_mesh]] {
// addr: ptr[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_JOIN_MESH, nl80211_wdev_payload], nl80211_policy$join_mesh]] {
// netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_JOIN_MESH, nl80211_wdev_payload], nl80211_policy$join_mesh] {
// len: len = 0x28 (4 bytes)
// type: nl80211_family_id (resource)
// flags: netlink_msg_flags = 0x1 (2 bytes)
// seq: int32 = 0x70bd28 (4 bytes)
// pid: int32 = 0x25dfdbfb (4 bytes)
// payload: msg_nl80211_payload[NL80211_CMD_JOIN_MESH, nl80211_wdev_payload] {
// genl_hdr: genlmsghdr_t[NL80211_CMD_JOIN_MESH] {
// cmd: const = 0x44 (1 bytes)
// version: const = 0x0 (1 bytes)
// reserved: const = 0x0 (2 bytes)
// }
// payload: nl80211_wdev_payload {
// NL80211_ATTR_IFINDEX: union optional[nlattr[NL80211_ATTR_IFINDEX, nl80211_ifindex]] {
// val: nlattr_t[const[NL80211_ATTR_IFINDEX, int16], nl80211_ifindex] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0x3 (2 bytes)
// payload: nl80211_ifindex (resource)
// size: buffer: {} (length 0x0)
// }
// }
// NL80211_ATTR_WDEV: union optional[nlattr[NL80211_ATTR_WDEV, nl80211_wdev]] {
// void: buffer: {} (length 0x0)
// }
// }
// }
// attrs: array[nl80211_policy$join_mesh] {
// union nl80211_policy$join_mesh {
// NL80211_ATTR_MESH_ID: nlattr_t[const[NL80211_ATTR_MESH_ID, int16], ieee80211_mesh_id] {
// nla_len: offsetof = 0xa (2 bytes)
// nla_type: const = 0x18 (2 bytes)
// payload: union ieee80211_mesh_id {
// default: buffer: {03 03 03 03 03 03} (length 0x6)
// }
// size: buffer: {} (length 0x0)
// }
// }
// }
// }
// }
// len: len = 0x28 (8 bytes)
// }
// }
// vlen: const = 0x1 (8 bytes)
// ctrl: const = 0x0 (8 bytes)
// ctrllen: const = 0x0 (8 bytes)
// f: send_flags = 0x85 (4 bytes)
// pad = 0x0 (4 bytes)
// }
// }
// f: send_flags = 0x4c040 (8 bytes)
// ]
*(uint64_t*)0x200000000040 = 0;
*(uint32_t*)0x200000000048 = 0;
*(uint64_t*)0x200000000050 = 0x200000000240;
*(uint64_t*)0x200000000240 = 0x200000000dc0;
*(uint32_t*)0x200000000dc0 = 0x28;
*(uint16_t*)0x200000000dc4 = r[1];
*(uint16_t*)0x200000000dc6 = 1;
*(uint32_t*)0x200000000dc8 = 0x70bd28;
*(uint32_t*)0x200000000dcc = 0x25dfdbfb;
*(uint8_t*)0x200000000dd0 = 0x44;
*(uint8_t*)0x200000000dd1 = 0;
*(uint16_t*)0x200000000dd2 = 0;
*(uint16_t*)0x200000000dd4 = 8;
*(uint16_t*)0x200000000dd6 = 3;
*(uint32_t*)0x200000000dd8 = r[2];
*(uint16_t*)0x200000000ddc = 0xa;
*(uint16_t*)0x200000000dde = 0x18;
memset((void*)0x200000000de0, 3, 6);
*(uint64_t*)0x200000000248 = 0x28;
*(uint64_t*)0x200000000058 = 1;
*(uint64_t*)0x200000000060 = 0;
*(uint64_t*)0x200000000068 = 0;
*(uint32_t*)0x200000000070 = 0x85;
syscall(__NR_sendmsg, /*fd=*/r[0], /*msg=*/0x200000000040ul, /*f=MSG_BATCH|MSG_NOSIGNAL|MSG_MORE|MSG_DONTWAIT*/0x4c040ul);
// syz_genetlink_get_family_id$nl80211 arguments: [
// name: ptr[in, buffer] {
// buffer: {6e 6c 38 30 32 31 31 00} (length 0x8)
// }
// fd: sock_nl_generic (resource)
// ]
// returns nl80211_family_id
memcpy((void*)0x200000000040, "nl80211\000", 8);
res = -1;
res = syz_genetlink_get_family_id(/*name=*/0x200000000040, /*fd=*/-1);
if (res != -1)
r[4] = res;
// socket$nl_generic arguments: [
// domain: const = 0x10 (8 bytes)
// type: const = 0x3 (8 bytes)
// proto: const = 0x10 (4 bytes)
// ]
// returns sock_nl_generic
res = syscall(__NR_socket, /*domain=*/0x10ul, /*type=*/3ul, /*proto=*/0x10);
if (res != -1)
r[5] = res;
// ioctl$sock_SIOCGIFINDEX_80211 arguments: [
// fd: sock (resource)
// cmd: const = 0x8933 (4 bytes)
// arg: ptr[out, ifreq_dev_t[nl80211_devnames, nl80211_ifindex]] {
// ifreq_dev_t[nl80211_devnames, nl80211_ifindex] {
// ifr_ifrn: buffer: {77 6c 61 6e 30 00 00 00 00 00 00 00 00 00 00 00} (length 0x10)
// elem: nl80211_ifindex (resource)
// pad = 0x0 (20 bytes)
// }
// }
// ]
memcpy((void*)0x2000000003c0, "wlan0\000\000\000\000\000\000\000\000\000\000\000", 16);
res = syscall(__NR_ioctl, /*fd=*/r[5], /*cmd=*/0x8933, /*arg=*/0x2000000003c0ul);
if (res != -1)
r[6] = *(uint32_t*)0x2000000003d0;
// sendmsg$NL80211_CMD_CHANNEL_SWITCH arguments: [
// fd: sock_nl_generic (resource)
// msg: ptr[in, msghdr_netlink[netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_CHANNEL_SWITCH, nl80211_wdev_payload], nl80211_policy$chsw]]] {
// msghdr_netlink[netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_CHANNEL_SWITCH, nl80211_wdev_payload], nl80211_policy$chsw]] {
// addr: nil
// addrlen: len = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// vec: ptr[in, iovec[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_CHANNEL_SWITCH, nl80211_wdev_payload], nl80211_policy$chsw]]] {
// iovec[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_CHANNEL_SWITCH, nl80211_wdev_payload], nl80211_policy$chsw]] {
// addr: ptr[in, netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_CHANNEL_SWITCH, nl80211_wdev_payload], nl80211_policy$chsw]] {
// netlink_msg_t[nl80211_family_id, msg_nl80211_payload[NL80211_CMD_CHANNEL_SWITCH, nl80211_wdev_payload], nl80211_policy$chsw] {
// len: len = 0x2c (4 bytes)
// type: nl80211_family_id (resource)
// flags: netlink_msg_flags = 0x1 (2 bytes)
// seq: int32 = 0x70bd2a (4 bytes)
// pid: int32 = 0x0 (4 bytes)
// payload: msg_nl80211_payload[NL80211_CMD_CHANNEL_SWITCH, nl80211_wdev_payload] {
// genl_hdr: genlmsghdr_t[NL80211_CMD_CHANNEL_SWITCH] {
// cmd: const = 0x66 (1 bytes)
// version: const = 0x0 (1 bytes)
// reserved: const = 0x0 (2 bytes)
// }
// payload: nl80211_wdev_payload {
// NL80211_ATTR_IFINDEX: union optional[nlattr[NL80211_ATTR_IFINDEX, nl80211_ifindex]] {
// val: nlattr_t[const[NL80211_ATTR_IFINDEX, int16], nl80211_ifindex] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0x3 (2 bytes)
// payload: nl80211_ifindex (resource)
// size: buffer: {} (length 0x0)
// }
// }
// NL80211_ATTR_WDEV: union optional[nlattr[NL80211_ATTR_WDEV, nl80211_wdev]] {
// void: buffer: {} (length 0x0)
// }
// }
// }
// attrs: array[nl80211_policy$chsw] {
// union nl80211_policy$chsw {
// chandef_params: array[nl80211_policy$chandef_params] {
// union nl80211_policy$chandef_params {
// NL80211_ATTR_WIPHY_FREQ: nlattr_t[const[NL80211_ATTR_WIPHY_FREQ, int16], ieee80211_frequency_mhz[int32]] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0x26 (2 bytes)
// payload: union ieee80211_frequency_mhz[int32] {
// default: const = 0x96c (4 bytes)
// }
// size: buffer: {} (length 0x0)
// }
// }
// }
// }
// union nl80211_policy$chsw {
// NL80211_ATTR_CH_SWITCH_COUNT: nlattr_t[const[NL80211_ATTR_CH_SWITCH_COUNT, int16], int32[0:255]] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0xb7 (2 bytes)
// payload: int32 = 0xf9 (4 bytes)
// size: buffer: {} (length 0x0)
// }
// }
// }
// }
// }
// len: len = 0x2c (8 bytes)
// }
// }
// vlen: const = 0x1 (8 bytes)
// ctrl: const = 0x0 (8 bytes)
// ctrllen: const = 0x0 (8 bytes)
// f: send_flags = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// }
// }
// f: send_flags = 0x0 (8 bytes)
// ]
*(uint64_t*)0x200000000200 = 0;
*(uint32_t*)0x200000000208 = 0;
*(uint64_t*)0x200000000210 = 0x2000000001c0;
*(uint64_t*)0x2000000001c0 = 0x2000000032c0;
*(uint32_t*)0x2000000032c0 = 0x2c;
*(uint16_t*)0x2000000032c4 = r[4];
*(uint16_t*)0x2000000032c6 = 1;
*(uint32_t*)0x2000000032c8 = 0x70bd2a;
*(uint32_t*)0x2000000032cc = 0;
*(uint8_t*)0x2000000032d0 = 0x66;
*(uint8_t*)0x2000000032d1 = 0;
*(uint16_t*)0x2000000032d2 = 0;
*(uint16_t*)0x2000000032d4 = 8;
*(uint16_t*)0x2000000032d6 = 3;
*(uint32_t*)0x2000000032d8 = r[6];
*(uint16_t*)0x2000000032dc = 8;
*(uint16_t*)0x2000000032de = 0x26;
*(uint32_t*)0x2000000032e0 = 0x96c;
*(uint16_t*)0x2000000032e4 = 8;
*(uint16_t*)0x2000000032e6 = 0xb7;
*(uint32_t*)0x2000000032e8 = 0xf9;
*(uint64_t*)0x2000000001c8 = 0x2c;
*(uint64_t*)0x200000000218 = 1;
*(uint64_t*)0x200000000220 = 0;
*(uint64_t*)0x200000000228 = 0;
*(uint32_t*)0x200000000230 = 0;
syscall(__NR_sendmsg, /*fd=*/r[5], /*msg=*/0x200000000200ul, /*f=*/0ul);
return 0;
}
Reply: Based on the analysis of the bug report and the kernel source code, here is the assessment of the vulnerability:
**Root Cause Analysis:**
The bug is a memory leak of a `struct mesh_csa_settings` object. When a channel switch is initiated on a mesh interface (e.g., via the `NL80211_CMD_CHANNEL_SWITCH` netlink command), `ieee80211_mesh_csa_beacon()` is called. This function allocates a new `mesh_csa_settings` object and assigns it to `sdata->u.mesh.csa` (`ifmsh->csa`).
Under normal circumstances, when the channel switch completes, `ieee80211_mesh_finish_csa()` is called, which properly frees `ifmsh->csa`. However, if the mesh interface is stopped or destroyed (e.g., by bringing the interface down or destroying the network namespace) while the channel switch is still active, the cleanup routines (`ieee80211_do_stop()`, `ieee80211_stop_mesh()`, and `ieee80211_mesh_teardown_sdata()`) fail to free the pending `ifmsh->csa` pointer. This results in the memory leak reported by kmemleak.
**Exploitability:**
This is a pure memory leak. While an attacker could repeatedly trigger this to exhaust system memory (leading to an Out-Of-Memory condition and system instability), it does not lead to memory corruption (like use-after-free or out-of-bounds access), privilege escalation, or information leaks. Therefore, it is classified as a Denial of Service (DoS) but not Exploitable for code execution.
**Privilege Requirements:**
To trigger this bug, a user must be able to issue `NL80211_CMD_JOIN_MESH` and `NL80211_CMD_CHANNEL_SWITCH` commands, and subsequently bring down or destroy the interface. In the `mac80211` netlink policy (`nl80211_small_ops`), these commands are flagged with `GENL_UNS_ADMIN_PERM`. This means they require the `CAP_NET_ADMIN` capability.
- **Unprivileged Processes:** Cannot trigger the bug because they lack `CAP_NET_ADMIN`.
- **User Namespaces:** Can trigger the bug, because `GENL_UNS_ADMIN_PERM` allows the commands to be executed if the process has `CAP_NET_ADMIN` within its own user/network namespace.
**Remote/Peripheral Triggers:**
While a remote attacker could potentially send a Channel Switch Announcement (CSA) management frame over the air to initiate a channel switch on a victim's mesh node, they cannot remotely force the victim's interface to be stopped or destroyed to actually trigger the memory leak. Thus, it is not considered remotely triggerable. It also does not involve malicious filesystems or untrusted physical peripherals.
|
| 6/2 |
2026/08/19 17:13 |
llm |
expert |
0m
Model:
Tokens:
input: 21557
output: 32
thoughts: 385
Thoughts: **Memory Leak Debugging: A Deep Dive**
Okay, so we've got a memory leak report specifically targeting `ieee80211_mesh_csa_beacon`. The backtrace is pretty clear, pointing directly to that function in `net/mac80211/mesh.c`. I can see the trail: `kmalloc` is being called, which then triggers the slab allocator, and eventually, `kmemleak_alloc_recursive` is being hit. This screams "allocation without corresponding freeing" to me, as expected from the leak report. I need to take a look at the code within `ieee80211_mesh_csa_beacon` to understand what's being allocated and whether the resources are released properly. I'll start by opening up `net/mac80211/mesh.c` and zero in on that function. I'll be looking for any signs of dynamic memory allocation and where the corresponding deallocation might be missing. Given the nature of mesh networking and channel switching, there's likely some beacon or CSA (Channel Switch Announcement) related structures being managed, but where is it going wrong? I need to analyze the code flow, understand the data structures being manipulated, and identify precisely where the leaked memory is accumulating. Let's see what we can find!
|
| 7/2 |
2026/08/19 17:14 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_mesh_csa_beacon]
Results: map[SourceCode:1537: int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
1538: struct cfg80211_csa_settings *csa_settings,
1539: u64 *changed)
1540: {
1541: struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
1542: struct mesh_csa_settings *tmp_csa_settings;
1543: int ret = 0;
1544:
1545: lockdep_assert_wiphy(sdata->local->hw.wiphy);
1546:
1547: tmp_csa_settings = kmalloc_obj(*tmp_csa_settings, GFP_ATOMIC);
1548: if (!tmp_csa_settings)
1549: return -ENOMEM;
1550:
1551: memcpy(&tmp_csa_settings->settings, csa_settings,
1552: sizeof(struct cfg80211_csa_settings));
1553:
1554: rcu_assign_pointer(ifmsh->csa, tmp_csa_settings);
1555:
1556: ret = ieee80211_mesh_rebuild_beacon(sdata);
1557: if (ret) {
1558: tmp_csa_settings = rcu_dereference(ifmsh->csa);
1559: RCU_INIT_POINTER(ifmsh->csa, NULL);
1560: kfree_rcu(tmp_csa_settings, rcu_head);
1561: return ret;
1562: }
1563:
1564: *changed |= BSS_CHANGED_BEACON;
1565: return 0;
1566: }
SourceFile:net/mac80211/mesh.c]
|
| 8/2 |
2026/08/19 17:14 |
llm |
expert |
0m
Model:
Tokens:
input: 22819
output: 30
thoughts: 112
Thoughts: **Memory Leak Debugging**
Okay, so I've zeroed in on the memory leak. It looks like the culprit is this line: `tmp_csa_settings = kmalloc_obj(*tmp_csa_settings, GFP_ATOMIC);`. Wait a second… aha! The problem likely lies in the subsequent `rcu_assign_pointer(ifmsh->csa, tmp_csa_settings);` call. If `ifmsh->csa` already points to an allocated structure, this overwrite is going to orphan the previous allocation, and we have our leak! Time to verify the hypothesis. I need to get over to `net/mac80211/cfg.c` and take a look at the `__ieee80211_channel_switch` function to see exactly how this is handled.
|
| 9/2 |
2026/08/19 17:14 |
tool |
codesearch-definition-source |
0m
Args: map[Name:__ieee80211_channel_switch]
Results: map[SourceCode:4703: static int
4704: __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
4705: struct cfg80211_csa_settings *params)
4706: {
4707: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
4708: struct ieee80211_chan_req chanreq = {
4709: .oper = params->chandef,
4710: .require_npca = true,
4711: };
4712: struct ieee80211_local *local = sdata->local;
4713: struct ieee80211_channel_switch ch_switch = {
4714: .link_id = params->link_id,
4715: };
4716: struct ieee80211_chanctx_conf *conf;
4717: struct ieee80211_chanctx *chanctx;
4718: struct ieee80211_bss_conf *link_conf;
4719: struct ieee80211_link_data *link_data;
4720: u64 changed = 0;
4721: u8 link_id = params->link_id;
4722: int err;
4723:
4724: lockdep_assert_wiphy(local->hw.wiphy);
4725:
4726: if (ieee80211_is_scan_ongoing(wiphy, local, ¶ms->chandef))
4727: return -EBUSY;
4728:
4729: if (sdata->wdev.links[link_id].cac_started)
4730: return -EBUSY;
4731:
4732: if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS))
4733: return -EINVAL;
4734:
4735: link_data = wiphy_dereference(wiphy, sdata->link[link_id]);
4736: if (!link_data)
4737: return -ENOLINK;
4738:
4739: link_conf = link_data->conf;
4740:
4741: if (chanreq.oper.punctured && !link_conf->eht_support)
4742: return -EINVAL;
4743:
4744: /* don't allow another channel switch if one is already active. */
4745: if (link_conf->csa_active)
4746: return -EBUSY;
4747:
4748: conf = wiphy_dereference(wiphy, link_conf->chanctx_conf);
4749: if (!conf) {
4750: err = -EBUSY;
4751: goto out;
4752: }
4753:
4754: if (params->chandef.chan->freq_offset) {
4755: /* this may work, but is untested */
4756: err = -EOPNOTSUPP;
4757: goto out;
4758: }
4759:
4760: err = ieee80211_set_unsol_bcast_probe_resp(sdata,
4761: ¶ms->unsol_bcast_probe_resp,
4762: link_data, link_conf, &changed);
4763: if (err)
4764: goto out;
4765:
4766: chanctx = container_of(conf, struct ieee80211_chanctx, conf);
4767:
4768: ch_switch.timestamp = 0;
4769: ch_switch.device_timestamp = 0;
4770: ch_switch.block_tx = params->block_tx;
4771: ch_switch.chandef = chanreq.oper;
4772: ch_switch.count = params->count;
4773:
4774: err = drv_pre_channel_switch(sdata, &ch_switch);
4775: if (err)
4776: goto out;
4777:
4778: err = ieee80211_link_reserve_chanctx(link_data, &chanreq,
4779: chanctx->mode,
4780: params->radar_required);
4781: if (err)
4782: goto out;
4783:
4784: /* if reservation is invalid then this will fail */
4785: err = ieee80211_check_combinations(sdata, NULL, 0, 0, -1);
4786: if (err) {
4787: ieee80211_link_unreserve_chanctx(link_data);
4788: goto out;
4789: }
4790:
4791: /* if there is a color change in progress, abort it */
4792: if (link_conf->color_change_active)
4793: ieee80211_color_change_abort(link_data);
4794:
4795: err = ieee80211_set_csa_beacon(link_data, params, &changed);
4796: if (err) {
4797: ieee80211_link_unreserve_chanctx(link_data);
4798: goto out;
4799: }
4800:
4801: link_data->csa.chanreq = chanreq;
4802: link_conf->csa_active = true;
4803:
4804: if (params->block_tx)
4805: ieee80211_vif_block_queues_csa(sdata);
4806:
4807: cfg80211_ch_switch_started_notify(sdata->dev,
4808: &link_data->csa.chanreq.oper, link_id,
4809: params->count, params->block_tx);
4810:
4811: if (changed) {
4812: ieee80211_link_info_change_notify(sdata, link_data, changed);
4813: drv_channel_switch_beacon(sdata, &link_data->csa.chanreq.oper);
4814: } else {
4815: /* if the beacon didn't change, we can finalize immediately */
4816: ieee80211_csa_finalize(link_data);
4817: }
4818:
4819: out:
4820: return err;
4821: }
SourceFile:net/mac80211/cfg.c]
|
| 10/2 |
2026/08/19 17:14 |
llm |
expert |
0m
Model:
Tokens:
input: 25108
output: 32
thoughts: 142
Thoughts: **My Analysis of the Channel Switch Logic**
Okay, let me think this through. The code's using `if (link_conf->csa_active)` to block a new channel switch if one is already underway. That's good, prevents concurrent operations. But, here's the rub: what happens if `ieee80211_set_csa_beacon` gets called successfully, initiating things, but then some *other* part of the process fails later on? We could end up in an inconsistent state. Let's see...
Aha! Upon closer inspection, `ieee80211_set_csa_beacon` is the very *last* function called in `__ieee80211_channel_switch` before `link_conf->csa_active = true`. That's a key observation. So, if that succeeds, *and only if*, then we commit to the switch.
And hold on, now I remember, `ieee80211_set_csa_beacon` further calls `ieee80211_mesh_csa_beacon`. This has implications for mesh networks, for which this is likely targeting.
|
| 11/2 |
2026/08/19 17:14 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_set_csa_beacon]
Results: map[SourceCode:4563: static int ieee80211_set_csa_beacon(struct ieee80211_link_data *link_data,
4564: struct cfg80211_csa_settings *params,
4565: u64 *changed)
4566: {
4567: struct ieee80211_sub_if_data *sdata = link_data->sdata;
4568: struct ieee80211_csa_settings csa = {};
4569: int err;
4570:
4571: switch (sdata->vif.type) {
4572: case NL80211_IFTYPE_AP:
4573: link_data->u.ap.next_beacon =
4574: cfg80211_beacon_dup(¶ms->beacon_after);
4575: if (!link_data->u.ap.next_beacon)
4576: return -ENOMEM;
4577:
4578: /*
4579: * With a count of 0, we don't have to wait for any
4580: * TBTT before switching, so complete the CSA
4581: * immediately. In theory, with a count == 1 we
4582: * should delay the switch until just before the next
4583: * TBTT, but that would complicate things so we switch
4584: * immediately too. If we would delay the switch
4585: * until the next TBTT, we would have to set the probe
4586: * response here.
4587: *
4588: * TODO: A channel switch with count <= 1 without
4589: * sending a CSA action frame is kind of useless,
4590: * because the clients won't know we're changing
4591: * channels. The action frame must be implemented
4592: * either here or in the userspace.
4593: */
4594: if (params->count <= 1)
4595: break;
4596:
4597: if ((params->n_counter_offsets_beacon >
4598: IEEE80211_MAX_CNTDWN_COUNTERS_NUM) ||
4599: (params->n_counter_offsets_presp >
4600: IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) {
4601: ieee80211_free_next_beacon(link_data);
4602: return -EINVAL;
4603: }
4604:
4605: csa.counter_offsets_beacon = params->counter_offsets_beacon;
4606: csa.counter_offsets_presp = params->counter_offsets_presp;
4607: csa.n_counter_offsets_beacon = params->n_counter_offsets_beacon;
4608: csa.n_counter_offsets_presp = params->n_counter_offsets_presp;
4609: csa.count = params->count;
4610:
4611: err = ieee80211_assign_beacon(sdata, link_data,
4612: ¶ms->beacon_csa, &csa,
4613: NULL, changed);
4614: if (err < 0) {
4615: ieee80211_free_next_beacon(link_data);
4616: return err;
4617: }
4618:
4619: break;
4620: case NL80211_IFTYPE_ADHOC:
4621: if (!sdata->vif.cfg.ibss_joined)
4622: return -EINVAL;
4623:
4624: if (params->chandef.width != sdata->u.ibss.chandef.width)
4625: return -EINVAL;
4626:
4627: switch (params->chandef.width) {
4628: case NL80211_CHAN_WIDTH_40:
4629: if (cfg80211_get_chandef_type(¶ms->chandef) !=
4630: cfg80211_get_chandef_type(&sdata->u.ibss.chandef))
4631: return -EINVAL;
4632: break;
4633: case NL80211_CHAN_WIDTH_20_NOHT:
4634: case NL80211_CHAN_WIDTH_20:
4635: break;
4636: default:
4637: return -EINVAL;
4638: }
4639:
4640: /* changes into another band are not supported */
4641: if (sdata->u.ibss.chandef.chan->band !=
4642: params->chandef.chan->band)
4643: return -EINVAL;
4644:
4645: /* see comments in the NL80211_IFTYPE_AP block */
4646: if (params->count > 1) {
4647: err = ieee80211_ibss_csa_beacon(sdata, params, changed);
4648: if (err < 0)
4649: return err;
4650: }
4651:
4652: ieee80211_send_action_csa(sdata, params);
4653:
4654: break;
4655: #ifdef CONFIG_MAC80211_MESH
4656: case NL80211_IFTYPE_MESH_POINT: {
4657: struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
4658:
4659: /* changes into another band are not supported */
4660: if (sdata->vif.bss_conf.chanreq.oper.chan->band !=
4661: params->chandef.chan->band)
4662: return -EINVAL;
4663:
4664: if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_NONE) {
4665: ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_INIT;
4666: if (!ifmsh->pre_value)
4667: ifmsh->pre_value = 1;
4668: else
4669: ifmsh->pre_value++;
4670: }
4671:
4672: /* see comments in the NL80211_IFTYPE_AP block */
4673: if (params->count > 1) {
4674: err = ieee80211_mesh_csa_beacon(sdata, params, changed);
4675: if (err < 0) {
4676: ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
4677: return err;
4678: }
4679: }
4680:
4681: if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT)
4682: ieee80211_send_action_csa(sdata, params);
4683:
4684: break;
4685: }
4686: #endif
4687: default:
4688: return -EOPNOTSUPP;
4689: }
4690:
4691: return 0;
4692: }
SourceFile:net/mac80211/cfg.c]
|
| 12/2 |
2026/08/19 17:14 |
llm |
expert |
0m
Model:
Tokens:
input: 27720
output: 30
thoughts: 329
Thoughts: **Memory Leak Concerns in `ieee80211_mesh_csa_beacon`**
Okay, so I'm looking at this `ieee80211_mesh_csa_beacon` function, and my immediate concern is a potential memory leak. Specifically, the code does this:
```c
tmp_csa_settings = kmalloc_obj(*tmp_csa_settings, GFP_ATOMIC);
if (!tmp_csa_settings)
return -ENOMEM;
memcpy(&tmp_csa_settings->settings, csa_settings,
sizeof(struct cfg80211_csa_settings));
rcu_assign_pointer(ifmsh->csa, tmp_csa_settings);
```
I see it's allocating memory for `tmp_csa_settings` and then assigning it to `ifmsh->csa`. But, if `ifmsh->csa` already has a value, an old allocated pointer is just overwritten. No `kfree` here. That looks like a memory leak waiting to happen, unless something else is cleaning it up.
So, the question is, can `ifmsh->csa` already be set? Absolutely, it can. If `__ieee80211_channel_switch` gets called multiple times in rapid succession, which could reasonably happen, we're in trouble.
Now, I glance at `__ieee80211_channel_switch` and it has this check:
```c
/* don't allow another channel switch if one is already active. */
if (link_conf->csa_active)
return -EBUSY;
```
That looks like a defense, at least in theory. The code appears to prevent concurrent CSA operations. However, I'm already anticipating an issue. What if `link_conf->csa_active` is *false*, but `ifmsh->csa` isn't NULL? I think there is a race condition or a state issue.
When *is* `link_conf->csa_active` set to false? A quick search and it looks like it gets cleared in `ieee80211_csa_finalize` and `ieee80211_csa_abort`. This means that if something fails to properly finalize or abort, we're looking at a serious leak if channel switching is attempted before the system recovers from the aborted action. Gotta keep an eye on those functions, too.
|
| 13/2 |
2026/08/19 17:14 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_csa_finalize]
Results: map[SourceCode:4523: static void ieee80211_csa_finalize(struct ieee80211_link_data *link_data)
4524: {
4525: struct ieee80211_sub_if_data *sdata = link_data->sdata;
4526: int link_id = -1;
4527:
4528: if (__ieee80211_csa_finalize(link_data)) {
4529: sdata_info(sdata, "failed to finalize CSA on link %d, disconnecting\n",
4530: link_data->link_id);
4531: if (sdata->vif.type == NL80211_IFTYPE_AP ||
4532: sdata->vif.type == NL80211_IFTYPE_P2P_GO)
4533: /*
4534: * link_id is expected only for AP/P2P_GO type
4535: * currently
4536: */
4537: link_id = link_data->link_id;
4538:
4539: cfg80211_stop_link(sdata->local->hw.wiphy, &sdata->wdev,
4540: link_id, GFP_KERNEL);
4541: }
4542: }
SourceFile:net/mac80211/cfg.c]
|
| 14/2 |
2026/08/19 17:14 |
llm |
expert |
0m
Model:
Tokens:
input: 29049
output: 31
thoughts: 19
Thoughts: Okay, here we go...
**Analyzing the `__ieee80211_csa_finalize` Function**
Alright, let's dive into this `__ieee80211_csa_finalize` function. My initial thought is, given the naming convention, this likely signifies the final stages of a Channel Switch Announcement (CSA) operation within an 802.11 wireless network implementation. Based on my experience, I'd expect this function to handle critical clean-up tasks post-CSA execution. I'm imagining it's taking care of things like:
* **State Transitions:** Ensuring the driver and hardware are in the correct state after the channel switch. Perhaps it's setting flags, updating internal data structures (likely `ieee80211_vif` or similar, depending on the framework), to reflect the new operating channel. This is the first thing that comes to mind.
* **Buffer Flushing/Resource Release:** Cleaning up any temporary buffers or data structures created during the CSA process. Preventing memory leaks is paramount, especially in a driver. I bet there's some freeing of allocated resources.
* **Confirming the Switch:** It's possible it's involved in confirming that the hardware has successfully switched to the new channel. This could involve reading status registers, checking for interrupts, or some other form of hardware verification. The goal would be to verify it's switched, and update the framework so any data sent is going over the correct channel.
* **Error Handling:** Probably some error handling to manage scenarios where the channel switch fails or encounters issues. What does it do in case of a failed transition? Does it trigger a fallback mechanism, report an error, or attempt a retry? This is always important!
* **Callback/Notification:** Perhaps there's a callback function being invoked to notify other parts of the system (like higher-level networking layers or the user space) that the channel switch is complete. This is the type of function that needs to be documented well.
I'm also curious about its inputs: What parameters does this function take? Likely a pointer to the wireless interface (`ieee80211_hw` or `net_device` or something similar), and potentially some context related to the specific CSA operation (e.g., the new channel, the duration, any CSA-specific data). The function's return value will be telling: Is it a simple void return, or does it return an error code to indicate success or failure?
I need to look at the function's signature and the surrounding code to confirm these assumptions and get a clearer picture of its role within the larger 802.11 stack. I expect this function has quite an important and sensitive role, and would likely be a central part of any channel switching related bugs.
|
| 15/2 |
2026/08/19 17:14 |
tool |
codesearch-definition-source |
0m
Args: map[Name:__ieee80211_csa_finalize]
Results: map[SourceCode:4467: static int __ieee80211_csa_finalize(struct ieee80211_link_data *link_data)
4468: {
4469: struct ieee80211_sub_if_data *sdata = link_data->sdata;
4470: struct ieee80211_local *local = sdata->local;
4471: struct ieee80211_bss_conf *link_conf = link_data->conf;
4472: u64 changed = 0;
4473: int err;
4474:
4475: lockdep_assert_wiphy(local->hw.wiphy);
4476:
4477: /*
4478: * using reservation isn't immediate as it may be deferred until later
4479: * with multi-vif. once reservation is complete it will re-schedule the
4480: * work with no reserved_chanctx so verify chandef to check if it
4481: * completed successfully
4482: */
4483:
4484: if (link_data->reserved_chanctx) {
4485: /*
4486: * with multi-vif csa driver may call ieee80211_csa_finish()
4487: * many times while waiting for other interfaces to use their
4488: * reservations
4489: */
4490: if (link_data->reserved_ready)
4491: return 0;
4492:
4493: return ieee80211_link_use_reserved_context(link_data);
4494: }
4495:
4496: if (!cfg80211_chandef_identical(&link_conf->chanreq.oper,
4497: &link_data->csa.chanreq.oper))
4498: return -EINVAL;
4499:
4500: link_conf->csa_active = false;
4501:
4502: err = ieee80211_set_after_csa_beacon(link_data, &changed);
4503: if (err)
4504: return err;
4505:
4506: ieee80211_link_info_change_notify(sdata, link_data, changed);
4507:
4508: if (sdata->vif.type == NL80211_IFTYPE_AP)
4509: ieee80211_uhr_disable_dbe_all_stas(link_data);
4510:
4511: ieee80211_vif_unblock_queues_csa(sdata);
4512:
4513: err = drv_post_channel_switch(link_data);
4514: if (err)
4515: return err;
4516:
4517: cfg80211_ch_switch_notify(sdata->dev, &link_data->csa.chanreq.oper,
4518: link_data->link_id);
4519:
4520: return 0;
4521: }
SourceFile:net/mac80211/cfg.c]
|
| 16/2 |
2026/08/19 17:14 |
llm |
expert |
0m
Model:
Tokens:
input: 30630
output: 34
thoughts: 31
Thoughts: Okay, here's my interpretation of those thoughts, tailored for an expert audience, and delivered as a first-person summary:
**The CSA Beacon Conundrum**
Alright, let me think this through. I was just staring at that section of the code, specifically `ieee80211_set_after_csa_beacon`, and a potential memory management issue is nagging at me. The function's name implies it's involved in handling Channel Switch Announcements (CSAs) and beacons, which often go hand-in-hand in 802.11 networks during a channel change. My concern boils down to this: could `ieee80211_set_after_csa_beacon` be the point where `ifmsh->csa` gets freed?
If that's the case, then any subsequent attempts to access data within `ifmsh->csa` after calling `ieee80211_set_after_csa_beacon` would lead to a nasty use-after-free vulnerability, which is something I need to avoid like the plague. I need to review how the CSA structure is allocated, initialized, used, and, critically, deallocated, in relation to this function call. I need to be *absolutely* certain of the memory lifecycle here. This is crucial for maintaining the stability and security of the wireless stack. The ramifications are potentially significant, because a use-after-free can manifest in hard-to-debug crashes, or worse, can lead to security exploits. This warrants a deep dive into the call graph and surrounding code.
|
| 17/2 |
2026/08/19 17:14 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_set_after_csa_beacon]
Results: map[SourceCode:4428: static int ieee80211_set_after_csa_beacon(struct ieee80211_link_data *link_data,
4429: u64 *changed)
4430: {
4431: struct ieee80211_sub_if_data *sdata = link_data->sdata;
4432: int err;
4433:
4434: switch (sdata->vif.type) {
4435: case NL80211_IFTYPE_AP:
4436: if (!link_data->u.ap.next_beacon)
4437: return -EINVAL;
4438:
4439: err = ieee80211_assign_beacon(sdata, link_data,
4440: link_data->u.ap.next_beacon,
4441: NULL, NULL, changed);
4442: ieee80211_free_next_beacon(link_data);
4443:
4444: if (err < 0)
4445: return err;
4446: break;
4447: case NL80211_IFTYPE_ADHOC:
4448: err = ieee80211_ibss_finish_csa(sdata, changed);
4449: if (err < 0)
4450: return err;
4451: break;
4452: #ifdef CONFIG_MAC80211_MESH
4453: case NL80211_IFTYPE_MESH_POINT:
4454: err = ieee80211_mesh_finish_csa(sdata, changed);
4455: if (err < 0)
4456: return err;
4457: break;
4458: #endif
4459: default:
4460: WARN_ON(1);
4461: return -EINVAL;
4462: }
4463:
4464: return 0;
4465: }
SourceFile:net/mac80211/cfg.c]
|
| 18/2 |
2026/08/19 17:14 |
llm |
expert |
0m
Model:
Tokens:
input: 31653
output: 32
thoughts: 20
Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue:
**Diving into `ieee80211_mesh_finish_csa`**
Alright, let's pull up that `ieee80211_mesh_finish_csa` function. Sounds like we're wrapping up a Channel Switch Announcement, or CSA, in a mesh context. My gut says this is going to be about cleaning up state after a channel change, coordinating with neighboring nodes, and making sure the transition is clean and doesn't introduce any hiccups into the mesh. I’m immediately thinking about:
* **Synchronization:** How does this function signal the switch to the associated stations and other mesh nodes? Is it using a specific frame type, a callback, or something else entirely? The timing is crucial to minimize disruption. Any sort of race conditions could result in lost connectivity.
* **State Management:** What exactly is being finalized? Are we resetting timers, clearing old channel information, updating data structures to reflect the new channel, and perhaps also moving over control traffic? I'll need to check the data structures to see how they're updated.
* **Error Handling:** What happens if the channel switch fails for some reason? Is there a retry mechanism, or a rollback to the previous channel? Any robust implementation should gracefully handle failures, and not bring down the whole mesh.
* **Security Implications:** CSA events could be exploited, so I'll want to review the security aspects. Are these events protected against tampering or spoofing?
* **Concurrency:** Is this function re-entrant, or does it have proper locking mechanisms to ensure atomic updates to shared resources? I'll need to pay close attention to potential race conditions, especially if this function is called from different threads or contexts.
* **Context:** What is the calling sequence and the assumptions that this code is dependent on. This will help understand if there is the possibility of any external factors affecting the execution, and potential unexpected side effects.
Essentially, I need to see how the code handles the final steps of a channel change from a mesh perspective to confirm everything is behaving as I would expect. I'm especially interested in ensuring that the transition doesn't introduce any new vulnerabilities or performance bottlenecks into the mesh network. This is going to be important to get right!
|
| 19/2 |
2026/08/19 17:14 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_mesh_finish_csa]
Results: map[SourceCode:1511: int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata, u64 *changed)
1512: {
1513: struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
1514: struct mesh_csa_settings *tmp_csa_settings;
1515: int ret = 0;
1516:
1517: /* Reset the TTL value and Initiator flag */
1518: ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
1519: ifmsh->chsw_ttl = 0;
1520:
1521: /* Remove the CSA and MCSP elements from the beacon */
1522: tmp_csa_settings = sdata_dereference(ifmsh->csa, sdata);
1523: RCU_INIT_POINTER(ifmsh->csa, NULL);
1524: if (tmp_csa_settings)
1525: kfree_rcu(tmp_csa_settings, rcu_head);
1526: ret = ieee80211_mesh_rebuild_beacon(sdata);
1527: if (ret)
1528: return -EINVAL;
1529:
1530: *changed |= BSS_CHANGED_BEACON;
1531:
1532: mcsa_dbg(sdata, "complete switching to center freq %d MHz",
1533: sdata->vif.bss_conf.chanreq.oper.chan->center_freq);
1534: return 0;
1535: }
SourceFile:net/mac80211/mesh.c]
|
| 20/2 |
2026/08/19 17:14 |
llm |
expert |
0m
Model:
Tokens:
input: 32708
output: 30
thoughts: 88
Thoughts: Here's my take on the situation:
**CSA Beacon Management in IEEE 802.11 Mesh Networks**
Alright, so I'm thinking about `ieee80211_mesh_finish_csa`. I've just realized it's responsible for freeing up the `ifmsh->csa` resource. That makes sense, cleanup is crucial. But then a scenario pops into my head. What if, just *what if*, the `__ieee80211_channel_switch` function fails *after* we've already called `ieee80211_set_csa_beacon`? That's a critical point. We could have a memory leak or an inconsistent state. I need to revisit the internals of `__ieee80211_channel_switch`. I need to ensure that the code handles all the failure cases correctly and guarantees memory consistency. This warrants a deeper dive. Let's see how that function is implemented...
|
| 21/2 |
2026/08/19 17:14 |
tool |
codesearch-definition-source |
0m
Args: map[Name:__ieee80211_channel_switch]
Results: map[SourceCode:4703: static int
4704: __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
4705: struct cfg80211_csa_settings *params)
4706: {
4707: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
4708: struct ieee80211_chan_req chanreq = {
4709: .oper = params->chandef,
4710: .require_npca = true,
4711: };
4712: struct ieee80211_local *local = sdata->local;
4713: struct ieee80211_channel_switch ch_switch = {
4714: .link_id = params->link_id,
4715: };
4716: struct ieee80211_chanctx_conf *conf;
4717: struct ieee80211_chanctx *chanctx;
4718: struct ieee80211_bss_conf *link_conf;
4719: struct ieee80211_link_data *link_data;
4720: u64 changed = 0;
4721: u8 link_id = params->link_id;
4722: int err;
4723:
4724: lockdep_assert_wiphy(local->hw.wiphy);
4725:
4726: if (ieee80211_is_scan_ongoing(wiphy, local, ¶ms->chandef))
4727: return -EBUSY;
4728:
4729: if (sdata->wdev.links[link_id].cac_started)
4730: return -EBUSY;
4731:
4732: if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS))
4733: return -EINVAL;
4734:
4735: link_data = wiphy_dereference(wiphy, sdata->link[link_id]);
4736: if (!link_data)
4737: return -ENOLINK;
4738:
4739: link_conf = link_data->conf;
4740:
4741: if (chanreq.oper.punctured && !link_conf->eht_support)
4742: return -EINVAL;
4743:
4744: /* don't allow another channel switch if one is already active. */
4745: if (link_conf->csa_active)
4746: return -EBUSY;
4747:
4748: conf = wiphy_dereference(wiphy, link_conf->chanctx_conf);
4749: if (!conf) {
4750: err = -EBUSY;
4751: goto out;
4752: }
4753:
4754: if (params->chandef.chan->freq_offset) {
4755: /* this may work, but is untested */
4756: err = -EOPNOTSUPP;
4757: goto out;
4758: }
4759:
4760: err = ieee80211_set_unsol_bcast_probe_resp(sdata,
4761: ¶ms->unsol_bcast_probe_resp,
4762: link_data, link_conf, &changed);
4763: if (err)
4764: goto out;
4765:
4766: chanctx = container_of(conf, struct ieee80211_chanctx, conf);
4767:
4768: ch_switch.timestamp = 0;
4769: ch_switch.device_timestamp = 0;
4770: ch_switch.block_tx = params->block_tx;
4771: ch_switch.chandef = chanreq.oper;
4772: ch_switch.count = params->count;
4773:
4774: err = drv_pre_channel_switch(sdata, &ch_switch);
4775: if (err)
4776: goto out;
4777:
4778: err = ieee80211_link_reserve_chanctx(link_data, &chanreq,
4779: chanctx->mode,
4780: params->radar_required);
4781: if (err)
4782: goto out;
4783:
4784: /* if reservation is invalid then this will fail */
4785: err = ieee80211_check_combinations(sdata, NULL, 0, 0, -1);
4786: if (err) {
4787: ieee80211_link_unreserve_chanctx(link_data);
4788: goto out;
4789: }
4790:
4791: /* if there is a color change in progress, abort it */
4792: if (link_conf->color_change_active)
4793: ieee80211_color_change_abort(link_data);
4794:
4795: err = ieee80211_set_csa_beacon(link_data, params, &changed);
4796: if (err) {
4797: ieee80211_link_unreserve_chanctx(link_data);
4798: goto out;
4799: }
4800:
4801: link_data->csa.chanreq = chanreq;
4802: link_conf->csa_active = true;
4803:
4804: if (params->block_tx)
4805: ieee80211_vif_block_queues_csa(sdata);
4806:
4807: cfg80211_ch_switch_started_notify(sdata->dev,
4808: &link_data->csa.chanreq.oper, link_id,
4809: params->count, params->block_tx);
4810:
4811: if (changed) {
4812: ieee80211_link_info_change_notify(sdata, link_data, changed);
4813: drv_channel_switch_beacon(sdata, &link_data->csa.chanreq.oper);
4814: } else {
4815: /* if the beacon didn't change, we can finalize immediately */
4816: ieee80211_csa_finalize(link_data);
4817: }
4818:
4819: out:
4820: return err;
4821: }
SourceFile:net/mac80211/cfg.c]
|
| 22/2 |
2026/08/19 17:14 |
llm |
expert |
0m
Model:
Tokens:
input: 35006
output: 32
thoughts: 141
Thoughts: **Analyzing the Channel Switch Attempt**
Okay, let's think this through. `ieee80211_set_csa_beacon` is the final hurdle, the last point of failure in this whole process. If that function returns success, then, and only then, does `link_conf->csa_active = true` get assigned. This means that, in theory, `__ieee80211_channel_switch` shouldn't be called again until that `csa_active` flag is flipped back to false. But wait a minute... I need to consider a potential edge case here. What if `ieee80211_set_csa_beacon` *fails* within the `ieee80211_mesh_csa_beacon` function? That would be a problem. This is a crucial point, I can't leave this unexamined. Let's delve into the specifics of `ieee80211_mesh_csa_beacon` and verify.
|
| 23/2 |
2026/08/19 17:14 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_mesh_csa_beacon]
Results: map[SourceCode:1537: int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
1538: struct cfg80211_csa_settings *csa_settings,
1539: u64 *changed)
1540: {
1541: struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
1542: struct mesh_csa_settings *tmp_csa_settings;
1543: int ret = 0;
1544:
1545: lockdep_assert_wiphy(sdata->local->hw.wiphy);
1546:
1547: tmp_csa_settings = kmalloc_obj(*tmp_csa_settings, GFP_ATOMIC);
1548: if (!tmp_csa_settings)
1549: return -ENOMEM;
1550:
1551: memcpy(&tmp_csa_settings->settings, csa_settings,
1552: sizeof(struct cfg80211_csa_settings));
1553:
1554: rcu_assign_pointer(ifmsh->csa, tmp_csa_settings);
1555:
1556: ret = ieee80211_mesh_rebuild_beacon(sdata);
1557: if (ret) {
1558: tmp_csa_settings = rcu_dereference(ifmsh->csa);
1559: RCU_INIT_POINTER(ifmsh->csa, NULL);
1560: kfree_rcu(tmp_csa_settings, rcu_head);
1561: return ret;
1562: }
1563:
1564: *changed |= BSS_CHANGED_BEACON;
1565: return 0;
1566: }
SourceFile:net/mac80211/mesh.c]
|
| 24/2 |
2026/08/19 17:14 |
llm |
expert |
0m
Model:
Tokens:
input: 35964
output: 32
thoughts: 107
Thoughts: **Analyzing Beacon Rebuilding & CSA Settings**
Okay, so I'm looking at this function and immediately, my spider senses are tingling. I see that `ieee80211_mesh_rebuild_beacon` is setting up some beacon-related configurations, and it has this interesting behavior: if it fails, it cleans up `tmp_csa_settings` and returns an error code, `ret`. But if it succeeds, it returns 0, which is standard.
My brain immediately jumps to a potential race condition or a missed edge case. What happens if *after* `ieee80211_mesh_csa_beacon` does its thing, `ieee80211_set_csa_beacon` chokes? Is the cleanup handled then, or is there a leak? Is the state properly managed in all scenarios? This seems like a critical point where things could get messy.
I need to dive into `ieee80211_set_csa_beacon` right away and see exactly what it's doing. This is where the vulnerabilities will be. Gotta make sure there's no dangling pointer, and the memory's being managed correctly.
|
| 25/2 |
2026/08/19 17:14 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_set_csa_beacon]
Results: map[SourceCode:4563: static int ieee80211_set_csa_beacon(struct ieee80211_link_data *link_data,
4564: struct cfg80211_csa_settings *params,
4565: u64 *changed)
4566: {
4567: struct ieee80211_sub_if_data *sdata = link_data->sdata;
4568: struct ieee80211_csa_settings csa = {};
4569: int err;
4570:
4571: switch (sdata->vif.type) {
4572: case NL80211_IFTYPE_AP:
4573: link_data->u.ap.next_beacon =
4574: cfg80211_beacon_dup(¶ms->beacon_after);
4575: if (!link_data->u.ap.next_beacon)
4576: return -ENOMEM;
4577:
4578: /*
4579: * With a count of 0, we don't have to wait for any
4580: * TBTT before switching, so complete the CSA
4581: * immediately. In theory, with a count == 1 we
4582: * should delay the switch until just before the next
4583: * TBTT, but that would complicate things so we switch
4584: * immediately too. If we would delay the switch
4585: * until the next TBTT, we would have to set the probe
4586: * response here.
4587: *
4588: * TODO: A channel switch with count <= 1 without
4589: * sending a CSA action frame is kind of useless,
4590: * because the clients won't know we're changing
4591: * channels. The action frame must be implemented
4592: * either here or in the userspace.
4593: */
4594: if (params->count <= 1)
4595: break;
4596:
4597: if ((params->n_counter_offsets_beacon >
4598: IEEE80211_MAX_CNTDWN_COUNTERS_NUM) ||
4599: (params->n_counter_offsets_presp >
4600: IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) {
4601: ieee80211_free_next_beacon(link_data);
4602: return -EINVAL;
4603: }
4604:
4605: csa.counter_offsets_beacon = params->counter_offsets_beacon;
4606: csa.counter_offsets_presp = params->counter_offsets_presp;
4607: csa.n_counter_offsets_beacon = params->n_counter_offsets_beacon;
4608: csa.n_counter_offsets_presp = params->n_counter_offsets_presp;
4609: csa.count = params->count;
4610:
4611: err = ieee80211_assign_beacon(sdata, link_data,
4612: ¶ms->beacon_csa, &csa,
4613: NULL, changed);
4614: if (err < 0) {
4615: ieee80211_free_next_beacon(link_data);
4616: return err;
4617: }
4618:
4619: break;
4620: case NL80211_IFTYPE_ADHOC:
4621: if (!sdata->vif.cfg.ibss_joined)
4622: return -EINVAL;
4623:
4624: if (params->chandef.width != sdata->u.ibss.chandef.width)
4625: return -EINVAL;
4626:
4627: switch (params->chandef.width) {
4628: case NL80211_CHAN_WIDTH_40:
4629: if (cfg80211_get_chandef_type(¶ms->chandef) !=
4630: cfg80211_get_chandef_type(&sdata->u.ibss.chandef))
4631: return -EINVAL;
4632: break;
4633: case NL80211_CHAN_WIDTH_20_NOHT:
4634: case NL80211_CHAN_WIDTH_20:
4635: break;
4636: default:
4637: return -EINVAL;
4638: }
4639:
4640: /* changes into another band are not supported */
4641: if (sdata->u.ibss.chandef.chan->band !=
4642: params->chandef.chan->band)
4643: return -EINVAL;
4644:
4645: /* see comments in the NL80211_IFTYPE_AP block */
4646: if (params->count > 1) {
4647: err = ieee80211_ibss_csa_beacon(sdata, params, changed);
4648: if (err < 0)
4649: return err;
4650: }
4651:
4652: ieee80211_send_action_csa(sdata, params);
4653:
4654: break;
4655: #ifdef CONFIG_MAC80211_MESH
4656: case NL80211_IFTYPE_MESH_POINT: {
4657: struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
4658:
4659: /* changes into another band are not supported */
4660: if (sdata->vif.bss_conf.chanreq.oper.chan->band !=
4661: params->chandef.chan->band)
4662: return -EINVAL;
4663:
4664: if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_NONE) {
4665: ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_INIT;
4666: if (!ifmsh->pre_value)
4667: ifmsh->pre_value = 1;
4668: else
4669: ifmsh->pre_value++;
4670: }
4671:
4672: /* see comments in the NL80211_IFTYPE_AP block */
4673: if (params->count > 1) {
4674: err = ieee80211_mesh_csa_beacon(sdata, params, changed);
4675: if (err < 0) {
4676: ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
4677: return err;
4678: }
4679: }
4680:
4681: if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT)
4682: ieee80211_send_action_csa(sdata, params);
4683:
4684: break;
4685: }
4686: #endif
4687: default:
4688: return -EOPNOTSUPP;
4689: }
4690:
4691: return 0;
4692: }
SourceFile:net/mac80211/cfg.c]
|
| 26/2 |
2026/08/19 17:15 |
llm |
expert |
0m
Model:
Tokens:
input: 38538
output: 32
thoughts: 467
Thoughts: **Analyzing a Potential CSA Beacon Leak**
Okay, so I'm looking at this `ieee80211_set_csa_beacon` function and something's bugging me. Specifically, if `ieee80211_mesh_csa_beacon` within it returns 0 (success, right?), it still leaves `ifmsh->csa` assigned, but what happens if that happens repeatedly? Could that be a memory leak? Yes!
I know, I know... the next thing is *can* `ieee80211_mesh_csa_beacon` be called multiple times? The key here seems to be `__ieee80211_channel_switch`. Let me think... what if `ieee80211_set_csa_beacon` works fine, but then something *after* fails within `__ieee80211_channel_switch`? Would we have a problem? Let's verify that.
I just checked `__ieee80211_channel_switch` carefully, and `ieee80211_set_csa_beacon` looks to be the last thing that can fail in that function. So I'm thinking...
Okay, I see. The code does set `link_conf->csa_active = true;` after a successful call to `ieee80211_set_csa_beacon`. That's good! So, `__ieee80211_channel_switch` *shouldn't* be able to call `ieee80211_set_csa_beacon` again until `csa_active` is back to false.
But...wait... what if `ieee80211_set_csa_beacon` is called from *somewhere else*? Is that even possible? I need to check where else this function is called. Gotta track down those call sites.
|
| 27/2 |
2026/08/19 17:15 |
tool |
codesearch-find-references |
0m
Args: map[Name:ieee80211_set_csa_beacon]
Results: map[References:[map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:__ieee80211_channel_switch SourceFile:net/mac80211/cfg.c SourceLine:4795]] TruncatedOutput:false]
|
| 28/2 |
2026/08/19 17:15 |
llm |
expert |
0m
Model:
Tokens:
input: 39552
output: 32
thoughts: 47
Thoughts: Okay, here's my interpretation of those thoughts, summarized from my perspective as someone deeply familiar with this code:
**Channel Switch Call Context Concerns**
Alright, so the initial assumption is that this code path is exclusively triggered by `__ieee80211_channel_switch`. That's the expected scenario and where I'd start my debugging. But, hang on a second... is there a potential *unexpected* call scenario here? Specifically, I need to consider `ieee80211_mesh_csa_beacon`. While *I* don't immediately see it being called from elsewhere, I need to verify that. There's always the possibility of some other function or process mistakenly or purposefully attempting a channel switch that I haven't considered. I need to explicitly confirm that the expected call path is the *only* call path to avoid potential future bugs. Let's dig deeper.
|
| 29/2 |
2026/08/19 17:15 |
tool |
codesearch-find-references |
0m
Args: map[Name:ieee80211_mesh_csa_beacon]
Results: map[References:[map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:ieee80211_set_csa_beacon SourceFile:net/mac80211/cfg.c SourceLine:4674]] TruncatedOutput:false]
|
| 30/2 |
2026/08/19 17:15 |
llm |
expert |
0m
Model:
Tokens:
input: 39908
output: 32
thoughts: 107
Thoughts: **Investigating a Potential Memory Leak in the 802.11 Mesh Context**
Okay, so I'm seeing this potential leak stemming specifically from `ieee80211_set_csa_beacon`. That's the only place I'm setting this `ifmsh->csa` variable. The question then becomes, how could this `ifmsh->csa` get into a state where it's not managed properly, leading to a leak? My gut feeling is that it's not being properly freed at interface shutdown or when the interface itself is destroyed. Let's dig deeper. I'll check `ieee80211_mesh_finish_csa` immediately, as that function *should* be handling the cleanup of `ifmsh->csa`. Now, the critical question is, where exactly is `ieee80211_mesh_finish_csa` getting called? I need to trace the call paths to confirm the deallocation happens at the appropriate times.
|
| 31/2 |
2026/08/19 17:15 |
tool |
codesearch-find-references |
0m
Args: map[Name:ieee80211_mesh_finish_csa]
Results: map[References:[map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:ieee80211_set_after_csa_beacon SourceFile:net/mac80211/cfg.c SourceLine:4454]] TruncatedOutput:false]
|
| 32/2 |
2026/08/19 17:15 |
llm |
expert |
0m
Model:
Tokens:
input: 40354
output: 34
thoughts: 43
Thoughts: Here's my thought process, as requested:
**Debugging Beacon Transitions: A Targeted Inquiry**
Alright, I'm digging into this `ieee80211_set_after_csa_beacon` function. My initial question is: Where exactly *is* this thing being called? I need to trace its execution path. Knowing the call sites will be critical to understanding its role in the context of a Channel Switch Announcement (CSA) beacon, and frankly, figure out what's going awry. I'm assuming, given the name, it's involved in setting up something after a CSA event, but I need solid confirmation of that, alongside how it's *supposed* to behave, and more importantly how it *actually* behaves. Let's see if I can find a straightforward code path, or if I'm going to have to do some deeper digging through related functions. Time to break out the xref tool!
|
| 33/2 |
2026/08/19 17:15 |
tool |
codesearch-find-references |
0m
Args: map[Name:ieee80211_set_after_csa_beacon]
Results: map[References:[map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:__ieee80211_csa_finalize SourceFile:net/mac80211/cfg.c SourceLine:4502]] TruncatedOutput:false]
|
| 34/2 |
2026/08/19 17:15 |
llm |
expert |
0m
Model:
Tokens:
input: 40713
output: 30
thoughts: 45
Thoughts: Okay, here's my take on those thoughts, framed as my own mental process, given my expertise:
**Examining CSA Abort Mechanisms**
Right, I'm digging into `__ieee80211_csa_finalize` and as usual, I'm thinking about edge cases and potential failure points. My immediate question is: are there *any* alternative methods for aborting a Channel Switch Announcement (CSA) beyond what's handled here? We need to be absolutely certain we've covered all the bases to avoid unexpected behavior or, worse, a complete system lockup in a bad situation.
The obvious place to start is the other relevant function, `ieee80211_csa_abort`. I need to review its logic, how it's called, and the conditions under which it's triggered. I need to understand if this is *the* definitive abort path, or if there are other, more subtle ways a CSA could be prematurely terminated, perhaps due to interrupt handling or other concurrent operations. I need to make certain this covers all the ground and accounts for all scenarios. I need to confirm whether any other states can trigger an abort outside of this function.
|
| 35/2 |
2026/08/19 17:15 |
tool |
codesearch-definition-source |
0m
Error:
Args: map[Name:ieee80211_csa_abort]
Results: map[SourceCode: SourceFile:]
|
| 36/2 |
2026/08/19 17:15 |
llm |
expert |
0m
Model:
Tokens:
input: 41062
output: 20
thoughts: 40
Thoughts: Okay, here's my summary, presented as a stream of thought:
**Checking for CSA Abort Mechanisms in mac80211**
Right, so I'm troubleshooting a CSA issue and it just hit me – maybe `ieee80211_csa_abort` isn't actually a thing, or at least, not implemented the way I'm expecting. It's a valid possibility that I missed something. I need to make absolutely sure the right function is being called, or exists at all. Time to dive into the `mac80211` codebase. I'll need to confirm what the proper method is for aborting Channel Switch Announcements within that framework. There's probably a well-defined way to handle this, and I need to find the specific function or method it employs. I'll have to meticulously search and trace the relevant code paths to locate how CSA abortions are initiated and processed. Hopefully the naming is intuitive, but I'll have to stay flexible with the keywords I'm searching for.
|
| 37/2 |
2026/08/19 17:15 |
tool |
grepper |
0m
Args: map[Expression:csa_active = false]
Results: map[Output:net/mac80211/cfg.c=2011=static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/cfg.c-2044- /* abort any running channel switch or color change */
net/mac80211/cfg.c:2045: link_conf->csa_active = false;
net/mac80211/cfg.c-2046- link_conf->color_change_active = false;
--
net/mac80211/cfg.c=4467=static int __ieee80211_csa_finalize(struct ieee80211_link_data *link_data)
--
net/mac80211/cfg.c-4499-
net/mac80211/cfg.c:4500: link_conf->csa_active = false;
net/mac80211/cfg.c-4501-
--
net/mac80211/iface.c=479=static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_down)
--
net/mac80211/iface.c-566-
net/mac80211/iface.c:567: sdata->vif.bss_conf.csa_active = false;
net/mac80211/iface.c-568- if (sdata->vif.type == NL80211_IFTYPE_STATION)
--
net/mac80211/mlme.c=2876=static void ieee80211_csa_switch_work(struct wiphy *wiphy,
--
net/mac80211/mlme.c-2909- link->link_id);
net/mac80211/mlme.c:2910: link->conf->csa_active = false;
net/mac80211/mlme.c-2911- link->u.mgd.conn.dbe_enabled = false;
--
net/mac80211/mlme.c=3016=static void ieee80211_chswitch_post_beacon(struct ieee80211_link_data *link)
--
net/mac80211/mlme.c-3029-
net/mac80211/mlme.c:3030: link->conf->csa_active = false;
net/mac80211/mlme.c-3031- link->u.mgd.conn.dbe_enabled = false;
--
net/mac80211/mlme.c=3095=ieee80211_sta_abort_chanswitch(struct ieee80211_link_data *link)
--
net/mac80211/mlme.c-3109-
net/mac80211/mlme.c:3110: link->conf->csa_active = false;
net/mac80211/mlme.c-3111- link->u.mgd.csa.blocked_tx = false;
--
net/mac80211/mlme.c=4508=static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
--
net/mac80211/mlme.c-4713-
net/mac80211/mlme.c:4714: sdata->vif.bss_conf.csa_active = false;
net/mac80211/mlme.c-4715- sdata->deflink.u.mgd.csa.blocked_tx = false;
--
net/mac80211/mlme.c=5034=static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
--
net/mac80211/mlme.c-5073- /* the other links will be destroyed */
net/mac80211/mlme.c:5074: sdata->vif.bss_conf.csa_active = false;
net/mac80211/mlme.c-5075- sdata->deflink.u.mgd.csa.waiting_bcn = false;
]
|
| 38/2 |
2026/08/19 17:15 |
llm |
expert |
0m
Model:
Tokens:
input: 42535
output: 29
thoughts: 33
Thoughts: Here's my take on the thought process, as if it were my own:
**Diving into the net/mac80211/iface.c Code**
Okay, I'm thinking I need to understand how a specific interface is stopped within the mac80211 framework. The logic is probably going to be in the interface-specific file, and given my prior experience with the structure, `net/mac80211/iface.c` is the logical place to start. Specifically, I need to look closely at the function `ieee80211_do_stop`. That function name itself is pretty explicit - it should hold the core of the interface shutdown process, which is exactly what I'm interested in understanding. This will hopefully show me how the mac80211 layer handles deactivating an interface and cleaning up associated resources.
|
| 39/2 |
2026/08/19 17:15 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_do_stop]
Results: map[SourceCode: 479: static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_down)
480: {
481: struct ieee80211_local *local = sdata->local;
482: struct ieee80211_sub_if_data *iter;
483: unsigned long flags;
484: struct sk_buff_head freeq;
485: struct sk_buff *skb, *tmp;
486: u32 hw_reconf_flags = 0;
487: int i, flushed;
488: struct ps_data *ps;
489: struct cfg80211_chan_def chandef;
490: bool cancel_scan;
491: struct cfg80211_nan_func *func;
492:
493: lockdep_assert_wiphy(local->hw.wiphy);
494:
495: clear_bit(SDATA_STATE_RUNNING, &sdata->state);
496: synchronize_rcu(); /* flush _ieee80211_wake_txqs() */
497:
498: cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata;
499: if (cancel_scan)
500: ieee80211_scan_cancel(local);
501:
502: ieee80211_roc_purge(local, sdata);
503:
504: switch (sdata->vif.type) {
505: case NL80211_IFTYPE_STATION:
506: ieee80211_mgd_stop(sdata);
507: break;
508: case NL80211_IFTYPE_ADHOC:
509: ieee80211_ibss_stop(sdata);
510: break;
511: case NL80211_IFTYPE_MONITOR:
512: list_del_rcu(&sdata->u.mntr.list);
513: break;
514: case NL80211_IFTYPE_AP_VLAN:
515: ieee80211_apvlan_link_clear(sdata);
516: break;
517: default:
518: break;
519: }
520:
521: /*
522: * Remove all stations associated with this interface.
523: *
524: * This must be done before calling ops->remove_interface()
525: * because otherwise we can later invoke ops->sta_notify()
526: * whenever the STAs are removed, and that invalidates driver
527: * assumptions about always getting a vif pointer that is valid
528: * (because if we remove a STA after ops->remove_interface()
529: * the driver will have removed the vif info already!)
530: *
531: * For AP_VLANs, NAN and NAN_DATA stations may exist since there's
532: * nothing else that would have removed them, but in other modes there
533: * shouldn't be any stations.
534: */
535: flushed = sta_info_flush(sdata, -1);
536: WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
537: sdata->vif.type != NL80211_IFTYPE_NAN &&
538: sdata->vif.type != NL80211_IFTYPE_NAN_DATA && flushed > 0);
539:
540: /* don't count this interface for allmulti while it is down */
541: if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
542: atomic_dec(&local->iff_allmultis);
543:
544: if (sdata->vif.type == NL80211_IFTYPE_AP) {
545: local->fif_pspoll--;
546: local->fif_probe_req--;
547: } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
548: local->fif_probe_req--;
549: }
550:
551: if (sdata->dev) {
552: netif_addr_lock_bh(sdata->dev);
553: spin_lock_bh(&local->filter_lock);
554: __hw_addr_unsync(&local->mc_list, &sdata->dev->mc,
555: sdata->dev->addr_len);
556: spin_unlock_bh(&local->filter_lock);
557: netif_addr_unlock_bh(sdata->dev);
558: }
559:
560: timer_delete_sync(&local->dynamic_ps_timer);
561: wiphy_work_cancel(local->hw.wiphy, &local->dynamic_ps_enable_work);
562:
563: WARN(ieee80211_vif_is_mld(&sdata->vif),
564: "destroying interface with valid links 0x%04x\n",
565: sdata->vif.valid_links);
566:
567: sdata->vif.bss_conf.csa_active = false;
568: if (sdata->vif.type == NL80211_IFTYPE_STATION)
569: sdata->deflink.u.mgd.csa.waiting_bcn = false;
570: ieee80211_vif_unblock_queues_csa(sdata);
571:
572: wiphy_work_cancel(local->hw.wiphy, &sdata->deflink.csa.finalize_work);
573: wiphy_work_cancel(local->hw.wiphy,
574: &sdata->deflink.color_change_finalize_work);
575: wiphy_hrtimer_work_cancel(local->hw.wiphy,
576: &sdata->deflink.dfs_cac_timer_work);
577:
578: if (sdata->wdev.links[0].cac_started) {
579: chandef = sdata->vif.bss_conf.chanreq.oper;
580: WARN_ON(local->suspended);
581: ieee80211_link_release_channel(&sdata->deflink);
582: cfg80211_cac_event(sdata->dev, &chandef,
583: NL80211_RADAR_CAC_ABORTED,
584: GFP_KERNEL, 0);
585: }
586:
587: if (sdata->vif.type == NL80211_IFTYPE_AP) {
588: WARN_ON(!list_empty(&sdata->u.ap.vlans));
589: } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
590: /* remove all packets in parent bc_buf pointing to this dev */
591: __skb_queue_head_init(&freeq);
592: ps = &sdata->bss->ps;
593:
594: spin_lock_irqsave(&ps->bc_buf.lock, flags);
595: skb_queue_walk_safe(&ps->bc_buf, skb, tmp) {
596: if (skb->dev == sdata->dev) {
597: __skb_unlink(skb, &ps->bc_buf);
598: local->total_ps_buffered--;
599: __skb_queue_tail(&freeq, skb);
600: }
601: }
602: spin_unlock_irqrestore(&ps->bc_buf.lock, flags);
603:
604: skb_queue_walk_safe(&freeq, skb, tmp) {
605: __skb_unlink(skb, &freeq);
606: ieee80211_free_txskb(&local->hw, skb);
607: }
608: }
609:
610: if (going_down)
611: local->open_count--;
612:
613: switch (sdata->vif.type) {
614: case NL80211_IFTYPE_AP_VLAN:
615: list_del(&sdata->u.vlan.list);
616: RCU_INIT_POINTER(sdata->vif.bss_conf.chanctx_conf, NULL);
617: /* see comment in the default case below */
618: ieee80211_free_keys(sdata, true);
619: /* no need to tell driver */
620: break;
621: case NL80211_IFTYPE_MONITOR:
622: local->monitors--;
623:
624: if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) &&
625: !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
626:
627: local->virt_monitors--;
628: if (local->virt_monitors == 0) {
629: local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;
630: hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
631: }
632:
633: ieee80211_adjust_monitor_flags(sdata, -1);
634: }
635: break;
636: case NL80211_IFTYPE_NAN:
637: /* Check if any open NAN_DATA interfaces */
638: list_for_each_entry(iter, &local->interfaces, list) {
639: WARN_ON(iter->vif.type == NL80211_IFTYPE_NAN_DATA &&
640: ieee80211_sdata_running(iter));
641: }
642:
643: /* clean all the functions */
644: if (!(local->hw.wiphy->nan_capa.flags &
645: WIPHY_NAN_FLAGS_USERSPACE_DE)) {
646: spin_lock_bh(&sdata->u.nan.de.func_lock);
647:
648: idr_for_each_entry(&sdata->u.nan.de.function_inst_ids,
649: func, i) {
650: idr_remove(&sdata->u.nan.de.function_inst_ids, i);
651: cfg80211_free_nan_func(func);
652: }
653: idr_destroy(&sdata->u.nan.de.function_inst_ids);
654:
655: spin_unlock_bh(&sdata->u.nan.de.func_lock);
656: }
657:
658: /*
659: * Free the remaining keys that might be associated with the
660: * NAN interface, e.g., IGTK and BIGTK used for Tx.
661: */
662: ieee80211_free_keys(sdata, true);
663: break;
664: case NL80211_IFTYPE_NAN_DATA:
665: RCU_INIT_POINTER(sdata->u.nan_data.nmi, NULL);
666: fallthrough;
667: default:
668: wiphy_work_cancel(sdata->local->hw.wiphy, &sdata->work);
669: /*
670: * When we get here, the interface is marked down.
671: * Free the remaining keys, if there are any
672: * (which can happen in AP mode if userspace sets
673: * keys before the interface is operating)
674: *
675: * Force the key freeing to always synchronize_net()
676: * to wait for the RX path in case it is using this
677: * interface enqueuing frames at this very time on
678: * another CPU.
679: */
680: ieee80211_free_keys(sdata, true);
681: skb_queue_purge(&sdata->skb_queue);
682: skb_queue_purge(&sdata->status_queue);
683: }
684:
685: /*
686: * Since ieee80211_free_txskb() may issue __dev_queue_xmit()
687: * which should be called with interrupts enabled, reclamation
688: * is done in two phases:
689: */
690: __skb_queue_head_init(&freeq);
691:
692: /* unlink from local queues... */
693: spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
694: for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
695: skb_queue_walk_safe(&local->pending[i], skb, tmp) {
696: struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
697: if (info->control.vif == &sdata->vif) {
698: __skb_unlink(skb, &local->pending[i]);
699: __skb_queue_tail(&freeq, skb);
700: }
701: }
702: }
703: spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
704:
705: /* ... and perform actual reclamation with interrupts enabled. */
706: skb_queue_walk_safe(&freeq, skb, tmp) {
707: __skb_unlink(skb, &freeq);
708: ieee80211_free_txskb(&local->hw, skb);
709: }
710:
711: if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
712: ieee80211_txq_remove_vlan(local, sdata);
713:
714: if (sdata->vif.txq)
715: ieee80211_txq_purge(sdata->local, to_txq_info(sdata->vif.txq));
716:
717: if (sdata->vif.txq_mgmt)
718: ieee80211_txq_purge(sdata->local,
719: to_txq_info(sdata->vif.txq_mgmt));
720:
721: sdata->bss = NULL;
722:
723: if (local->open_count == 0)
724: ieee80211_clear_tx_pending(local);
725:
726: sdata->vif.bss_conf.beacon_int = 0;
727:
728: /*
729: * If the interface goes down while suspended, presumably because
730: * the device was unplugged and that happens before our resume,
731: * then the driver is already unconfigured and the remainder of
732: * this function isn't needed.
733: * XXX: what about WoWLAN? If the device has software state, e.g.
734: * memory allocated, it might expect teardown commands from
735: * mac80211 here?
736: */
737: if (local->suspended) {
738: WARN_ON(local->wowlan);
739: WARN_ON(rcu_access_pointer(local->monitor_sdata));
740: return;
741: }
742:
743: switch (sdata->vif.type) {
744: case NL80211_IFTYPE_AP_VLAN:
745: break;
746: case NL80211_IFTYPE_MONITOR:
747: if (local->virt_monitors == 0)
748: ieee80211_del_virtual_monitor(local);
749:
750: ieee80211_recalc_idle(local);
751: ieee80211_recalc_offload(local);
752:
753: if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) &&
754: !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
755: break;
756:
757: ieee80211_link_release_channel(&sdata->deflink);
758: fallthrough;
759: default:
760: if (!going_down)
761: break;
762: drv_remove_interface(local, sdata);
763:
764: /* Clear private driver data to prevent reuse */
765: memset(sdata->vif.drv_priv, 0, local->hw.vif_data_size);
766: }
767:
768: ieee80211_recalc_ps(local);
769:
770: if (cancel_scan)
771: wiphy_delayed_work_flush(local->hw.wiphy, &local->scan_work);
772:
773: if (local->open_count == 0) {
774: ieee80211_stop_device(local, false);
775:
776: /* no reconfiguring after stop! */
777: return;
778: }
779:
780: /* do after stop to avoid reconfiguring when we stop anyway */
781: ieee80211_configure_filter(local);
782: ieee80211_hw_config(local, -1, hw_reconf_flags);
783:
784: /* Passing NULL means an interface is picked for configuration */
785: if (local->virt_monitors == local->open_count)
786: ieee80211_add_virtual_monitor(local, NULL);
787: }
SourceFile:net/mac80211/iface.c]
|
| 40/2 |
2026/08/19 17:15 |
llm |
expert |
0m
Model:
Tokens:
input: 48264
output: 30
thoughts: 78
Thoughts: Here's my thought process, as it went down:
**A Potential Memory Leak Concern**
Okay, so I'm looking at `ieee80211_do_stop` and something's immediately bothering me. I'm seeing that it *doesn't* appear to free `ifmsh->csa`. That's a red flag. I know `csa` has to be managed, so this is a potential memory leak if not handled elsewhere.
Let me see... right, `ifmsh` is a field within `sdata->u.mesh`. Okay, so `ifmsh` is part of `sdata`. Now the critical question: When is `sdata` freed? I need to trace the lifecycle here.
Alright, I've got it. I recall that `sdata` is explicitly freed in `ieee80211_sdata_free`. This is likely where the clean-up occurs. I need to examine `ieee80211_sdata_free` and confirm that it properly handles `csa`.
|
| 41/2 |
2026/08/19 17:15 |
tool |
codesearch-definition-source |
0m
Error:
Args: map[Name:ieee80211_sdata_free]
Results: map[SourceCode: SourceFile:]
|
| 42/2 |
2026/08/19 17:16 |
llm |
expert |
0m
Model:
Tokens:
input: 48628
output: 19
thoughts: 21
Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience:
**Investigating a Potential Memory Management Issue**
Okay, so I'm getting a hunch about a potential memory leak or corruption related to the station data structure (`sdata`) in the 802.11 code. My first instinct is to dig into the deallocation path. Specifically, I need to verify how `sdata` is freed, and the best place to start is likely `ieee80211_free_sdata` (or a function with a similar name if the codebase uses a slightly different naming convention). I need to ensure all resources allocated within the `sdata` struct, and any data it points to, are being properly released. I'll need to scrutinize all the calls to this function (or equivalent) for any potential missed release points, incorrect reference counting, or double-frees. The context here is key. I'll be looking for scenarios that trigger the release, and then make sure all potential scenarios are covered.
|
| 43/2 |
2026/08/19 17:16 |
tool |
grepper |
0m
Args: map[Expression:kfree.*sdata]
Results: map[Output:arch/riscv/kvm/vcpu_pmu.c=416=static void kvm_pmu_clear_snapshot_area(struct kvm_vcpu *vcpu)
--
arch/riscv/kvm/vcpu_pmu.c-419-
arch/riscv/kvm/vcpu_pmu.c:420: kfree(kvpmu->sdata);
arch/riscv/kvm/vcpu_pmu.c-421- kvpmu->sdata = NULL;
--
arch/riscv/kvm/vcpu_pmu.c=425=int kvm_riscv_vcpu_pmu_snapshot_set_shmem(struct kvm_vcpu *vcpu, unsigned long saddr_low,
--
arch/riscv/kvm/vcpu_pmu.c-462- if (kvm_vcpu_write_guest(vcpu, saddr, kvpmu->sdata, snapshot_area_size)) {
arch/riscv/kvm/vcpu_pmu.c:463: kfree(kvpmu->sdata);
arch/riscv/kvm/vcpu_pmu.c-464- kvpmu->sdata = NULL;
--
drivers/input/touchscreen/edt-ft5x06.c=591=static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
--
drivers/input/touchscreen/edt-ft5x06.c-643-err_out:
drivers/input/touchscreen/edt-ft5x06.c:644: kfree(tsdata->raw_buffer);
drivers/input/touchscreen/edt-ft5x06.c-645- tsdata->raw_buffer = NULL;
--
drivers/input/touchscreen/edt-ft5x06.c=652=static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata)
--
drivers/input/touchscreen/edt-ft5x06.c-683-
drivers/input/touchscreen/edt-ft5x06.c:684: kfree(tsdata->raw_buffer);
drivers/input/touchscreen/edt-ft5x06.c-685- tsdata->raw_buffer = NULL;
--
drivers/input/touchscreen/edt-ft5x06.c=807=static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
--
drivers/input/touchscreen/edt-ft5x06.c-810-
drivers/input/touchscreen/edt-ft5x06.c:811: kfree(tsdata->raw_buffer);
drivers/input/touchscreen/edt-ft5x06.c-812- tsdata->raw_buffer = NULL;
--
drivers/pci/xen-pcifront.c=552=static void pcifront_free_roots(struct pcifront_device *pdev)
--
drivers/pci/xen-pcifront.c-563-
drivers/pci/xen-pcifront.c:564: kfree(bus_entry->bus->sysdata);
drivers/pci/xen-pcifront.c-565-
--
fs/nfs/dir.c=1854=static void block_revalidate(struct dentry *dentry)
--
fs/nfs/dir.c-1856- /* old devname - just in case */
fs/nfs/dir.c:1857: kfree(dentry->d_fsdata);
fs/nfs/dir.c-1858-
--
fs/nfs/dir.c=1967=static void nfs_d_release(struct dentry *dentry)
--
fs/nfs/dir.c-1973- else
fs/nfs/dir.c:1974: kfree(dentry->d_fsdata);
fs/nfs/dir.c-1975- }
--
net/ipv6/ioam6.c=980=static int __net_init ioam6_net_init(struct net *net)
--
net/ipv6/ioam6.c-1004-free_nsdata:
net/ipv6/ioam6.c:1005: kfree(nsdata);
net/ipv6/ioam6.c-1006- net->ipv6.ioam6_data = NULL;
--
net/ipv6/ioam6.c=1010=static void __net_exit ioam6_net_exit(struct net *net)
--
net/ipv6/ioam6.c-1016-
net/ipv6/ioam6.c:1017: kfree(nsdata);
net/ipv6/ioam6.c-1018-}
--
net/ipv6/seg6.c=423=static int __net_init seg6_net_init(struct net *net)
--
net/ipv6/seg6.c-434- if (!sdata->tun_src) {
net/ipv6/seg6.c:435: kfree(sdata);
net/ipv6/seg6.c-436- return -ENOMEM;
--
net/ipv6/seg6.c-441- if (seg6_hmac_net_init(net)) {
net/ipv6/seg6.c:442: kfree(rcu_dereference_raw(sdata->tun_src));
net/ipv6/seg6.c:443: kfree(sdata);
net/ipv6/seg6.c-444- return -ENOMEM;
--
net/ipv6/seg6.c=450=static void __net_exit seg6_net_exit(struct net *net)
--
net/ipv6/seg6.c-455-
net/ipv6/seg6.c:456: kfree(rcu_dereference_raw(sdata->tun_src));
net/ipv6/seg6.c:457: kfree(sdata);
net/ipv6/seg6.c-458-}
--
net/mac80211/cfg.c=3326=static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
--
net/mac80211/cfg.c-3333- ieee80211_link_release_channel(&sdata->deflink);
net/mac80211/cfg.c:3334: kfree(sdata->u.mesh.ie);
net/mac80211/cfg.c-3335-
--
net/mac80211/ibss.c=1782=int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
--
net/mac80211/ibss.c-1790- /* remove beacon */
net/mac80211/ibss.c:1791: kfree(sdata->u.ibss.ie);
net/mac80211/ibss.c-1792- sdata->u.ibss.ie = NULL;
--
net/mac80211/iface.c=1228=int ieee80211_add_virtual_monitor(struct ieee80211_local *local,
--
net/mac80211/iface.c-1263- /* ok .. stupid driver, it asked for this! */
net/mac80211/iface.c:1264: kfree(sdata);
net/mac80211/iface.c-1265- return ret;
--
net/mac80211/iface.c-1270- if (ret) {
net/mac80211/iface.c:1271: kfree(sdata);
net/mac80211/iface.c-1272- return ret;
--
net/mac80211/iface.c-1289- clear_bit(SDATA_STATE_RUNNING, &sdata->state);
net/mac80211/iface.c:1290: kfree(sdata);
net/mac80211/iface.c-1291- return ret;
--
net/mac80211/iface.c=1327=void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
--
net/mac80211/iface.c-1356-
net/mac80211/iface.c:1357: kfree(sdata);
net/mac80211/iface.c-1358-}
--
net/mac80211/iface.c=2414=void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata)
--
net/mac80211/iface.c-2435- ieee80211_teardown_sdata(sdata);
net/mac80211/iface.c:2436: kfree(sdata);
net/mac80211/iface.c-2437- }
--
net/mac80211/iface.c=2447=void ieee80211_remove_interfaces(struct ieee80211_local *local)
--
net/mac80211/iface.c-2494- if (!netdev)
net/mac80211/iface.c:2495: kfree(sdata);
net/mac80211/iface.c-2496- }
--
net/mac80211/mlme.c=4476=static void ieee80211_ml_reconf_reset(struct ieee80211_sub_if_data *sdata)
--
net/mac80211/mlme.c-4502-
net/mac80211/mlme.c:4503: kfree(sdata->u.mgd.reconf.add_links_data);
net/mac80211/mlme.c-4504- sdata->u.mgd.reconf.add_links_data = NULL;
--
net/mac80211/mlme.c=10872=ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata,
--
net/mac80211/mlme.c-11093- cfg80211_mlo_reconf_add_done(sdata->dev, &done_data);
net/mac80211/mlme.c:11094: kfree(sdata->u.mgd.reconf.add_links_data);
net/mac80211/mlme.c-11095- sdata->u.mgd.reconf.add_links_data = NULL;
--
net/mac80211/tests/util.c=296=void t_sdata_exit(struct kunit_resource *resource)
--
net/mac80211/tests/util.c-299-
net/mac80211/tests/util.c:300: kfree(t_sdata->band_2ghz.channels);
net/mac80211/tests/util.c:301: kfree(t_sdata->band_2ghz.bitrates);
net/mac80211/tests/util.c:302: kfree(t_sdata->band_5ghz.channels);
net/mac80211/tests/util.c:303: kfree(t_sdata->band_5ghz.bitrates);
net/mac80211/tests/util.c-304-
net/mac80211/tests/util.c:305: kfree(t_sdata->sdata);
net/mac80211/tests/util.c:306: kfree(t_sdata->wiphy);
net/mac80211/tests/util.c-307-
net/mac80211/tests/util.c:308: kfree(t_sdata);
net/mac80211/tests/util.c-309-}
--
net/mac80211/util.c=1885=int ieee80211_reconfig(struct ieee80211_local *local)
--
net/mac80211/util.c-1997- synchronize_net();
net/mac80211/util.c:1998: kfree(sdata);
net/mac80211/util.c-1999- }
]
|
| 44/2 |
2026/08/19 17:16 |
llm |
expert |
0m
Model:
Tokens:
input: 52327
output: 32
thoughts: 20
Thoughts: Okay, let's dive into this. Here's my take on `ieee80211_teardown_sdata`:
**Deconstructing the sdata**
Alright, I'm taking a look at `ieee80211_teardown_sdata`. This function is critical; it's the cleanup routine for a station data structure. I need to understand what resources it's releasing, the state transitions it's handling, and any potential side effects. What are the dependencies? What locks are involved, and what's the expected order of operations? Are there any data structures that are prone to race conditions if not properly handled during the teardown? I’ll need to make sure this function is robust and doesn't leak memory or leave the driver in an inconsistent state, causing other parts of the WLAN stack to crash or misbehave later on. I'll need to double check any calls to this in order to ensure that nothing gets missed. Finally, any recent patches need to be checked in relation to this function, just in case there were any errors that may have been introduced.
|
| 45/2 |
2026/08/19 17:16 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_teardown_sdata]
Results: map[SourceCode: 896: /*
897: * Called when the netdev is removed or, by the code below, before
898: * the interface type changes.
899: */
900: static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
901: {
902: if (WARN_ON(!list_empty(&sdata->work.entry)))
903: wiphy_work_cancel(sdata->local->hw.wiphy, &sdata->work);
904:
905: /* free extra data */
906: ieee80211_free_keys(sdata, false);
907:
908: ieee80211_debugfs_remove_netdev(sdata);
909:
910: ieee80211_destroy_frag_cache(&sdata->frags);
911:
912: if (ieee80211_vif_is_mesh(&sdata->vif))
913: ieee80211_mesh_teardown_sdata(sdata);
914:
915: ieee80211_vif_clear_links(sdata);
916: ieee80211_link_stop(&sdata->deflink);
917:
918: if (sdata->vif.type == NL80211_IFTYPE_NAN) {
919: struct ieee80211_nan_sched_cfg *nan_sched =
920: &sdata->vif.cfg.nan_sched;
921:
922: for (int i = 0; i < ARRAY_SIZE(nan_sched->channels); i++)
923: WARN_ON(nan_sched->channels[i].chanreq.oper.chan);
924: }
925: }
SourceFile:net/mac80211/iface.c]
|
| 46/2 |
2026/08/19 17:16 |
llm |
expert |
0m
Model:
Tokens:
input: 53201
output: 34
thoughts: 22
Thoughts: Okay, let's dive into this. Here's my perspective on that thought process:
**Diving into `ieee80211_mesh_teardown_sdata`**
Alright, my brain is already churning. Let's start with a systematic look. The name itself, `ieee80211_mesh_teardown_sdata`, immediately tells me it's related to 802.11 mesh networking and the teardown or cleanup process for a station data structure (`sdata`). So, I'm expecting this function to be the critical point where resources associated with a mesh station are released or cleaned up when the station is disconnecting or being de-associated.
I need to understand what 'teardown' means in this context. Is it just freeing memory, or are there other cleanup tasks involved? Perhaps it's unregistering the station from the mesh network, removing it from internal data structures, and possibly signaling the PHY layer about the station's departure. I'm assuming there's more to it than just a simple `free()`.
My immediate questions are:
* What are the core data structures affected by this function?
* What resources are allocated and freed specifically for each mesh station?
* Are there any locking mechanisms used to protect the data structures during teardown, and if so, how are they handled to avoid deadlocks?
* Is there a specific order of operations? Are there dependencies between cleanup steps that I need to be aware of?
* What error conditions could arise during this process, and how are they handled? Is there any logging or error reporting?
I need to quickly assess how this function interacts with other parts of the mesh networking stack. Knowing its place in the broader picture is going to be crucial. This means tracing the call stack and considering the possible call sites. I want to have a mental map of what calls `ieee80211_mesh_teardown_sdata`, and how that calling chain effects overall.
This is going to be a fascinating journey to see this cleanup process in action.
|
| 47/2 |
2026/08/19 17:16 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_mesh_teardown_sdata]
Results: map[SourceCode:1790: void ieee80211_mesh_teardown_sdata(struct ieee80211_sub_if_data *sdata)
1791: {
1792: mesh_rmc_free(sdata);
1793: mesh_pathtbl_unregister(sdata);
1794: }
SourceFile:net/mac80211/mesh.c]
|
| 48/2 |
2026/08/19 17:16 |
llm |
expert |
0m
Model:
Tokens:
input: 53836
output: 20
thoughts: 51
Thoughts: Okay, here's my take on those thoughts, framed as my own mental process:
**A Critical Code Review Moment**
Wait a second... *`ieee80211_mesh_teardown_sdata`* isn't freeing `ifmsh->csa`! That's a potential memory leak right there. This function is supposed to be the *teardown*, the cleanup, so if it's not freeing something allocated, we have a serious problem. My spidey-sense is tingling. I need to figure out where else, if anywhere, `ifmsh->csa` *is* actually freed. Let's dig deeper and verify that the memory is handled correctly somewhere in this mesh management system. Gotta be thorough.
|
| 49/2 |
2026/08/19 17:16 |
tool |
codesearch-find-references |
0m
Error:
Args:
Results: map[References:<nil> TruncatedOutput:false]
|
| 50/2 |
2026/08/19 17:16 |
llm |
expert |
0m
Model:
Tokens:
input: 54091
output: 19
thoughts: 12
Thoughts: Here's my summary, as though I'm thinking these thoughts:
**Investigating Memory Allocation with Grep**
Okay, so I need to dive into some memory allocation issues, and I'm thinking the best place to start is with `kfree`. That function is critical for freeing up memory blocks, and when I'm chasing down potential leaks or corruption, that's often a prime suspect. And the "csa" part? That's likely related to the Control Structure Area, often used in kernel allocations for metadata. Putting them together, `kfree.*csa` is probably the right place to begin searching. I want to see where `kfree` is being called and potentially what context it's operating in when it deals with these CSA-related structures. A quick grep should give me a good lay of the land, highlight any unusual patterns, and hopefully, point me toward the root cause of whatever is going on.
|
| 51/2 |
2026/08/19 17:16 |
tool |
grepper |
0m
Args: map[Expression:kfree.*csa]
Results: map[Output:fs/nfs/callback_proc.c=503=__be32 nfs4_callback_sequence(void *argp, void *resp,
--
fs/nfs/callback_proc.c-590- for (i = 0; i < args->csa_nrclists; i++)
fs/nfs/callback_proc.c:591: kfree(args->csa_rclists[i].rcl_refcalls);
fs/nfs/callback_proc.c:592: kfree(args->csa_rclists);
fs/nfs/callback_proc.c-593-
--
fs/nfs/callback_xdr.c=395=static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp,
--
fs/nfs/callback_xdr.c-436- for (i = 0; i < args->csa_nrclists; i++)
fs/nfs/callback_xdr.c:437: kfree(args->csa_rclists[i].rcl_refcalls);
fs/nfs/callback_xdr.c:438: kfree(args->csa_rclists);
fs/nfs/callback_xdr.c-439- return status;
--
kernel/cgroup/cpuset-v1.c=629=int cpuset1_generate_sched_domains(cpumask_var_t **domains,
--
kernel/cgroup/cpuset-v1.c-755-done:
kernel/cgroup/cpuset-v1.c:756: kfree(csa);
kernel/cgroup/cpuset-v1.c-757-
--
kernel/cgroup/cpuset.c=811=static int generate_sched_domains(cpumask_var_t **domains,
--
kernel/cgroup/cpuset.c-901-done:
kernel/cgroup/cpuset.c:902: kfree(csa);
kernel/cgroup/cpuset.c-903-
--
net/mac80211/mesh.c=1511=int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata, u64 *changed)
--
net/mac80211/mesh.c-1524- if (tmp_csa_settings)
net/mac80211/mesh.c:1525: kfree_rcu(tmp_csa_settings, rcu_head);
net/mac80211/mesh.c-1526- ret = ieee80211_mesh_rebuild_beacon(sdata);
--
net/mac80211/mesh.c=1537=int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
--
net/mac80211/mesh.c-1559- RCU_INIT_POINTER(ifmsh->csa, NULL);
net/mac80211/mesh.c:1560: kfree_rcu(tmp_csa_settings, rcu_head);
net/mac80211/mesh.c-1561- return ret;
--
net/wireless/nl80211.c=12072=static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
--
net/wireless/nl80211.c-12237- kfree(params.beacon_after.mbssid_ies);
net/wireless/nl80211.c:12238: kfree(params.beacon_csa.mbssid_ies);
net/wireless/nl80211.c-12239- kfree(params.beacon_after.rnr_ies);
net/wireless/nl80211.c:12240: kfree(params.beacon_csa.rnr_ies);
net/wireless/nl80211.c:12241: kfree(csa_attrs);
net/wireless/nl80211.c-12242- return err;
]
|
| 52/2 |
2026/08/19 17:16 |
llm |
expert |
0m
Model:
Tokens:
input: 55423
output: 30
thoughts: 235
Thoughts: **Channel Switch Concerns**
Okay, so I'm digging into this channel switch process for mesh networks, and something's bugging me. It looks like `ifmsh->csa` is only ever freed in two places: `ieee80211_mesh_finish_csa` and, in the event of an error, within `ieee80211_mesh_csa_beacon`. If `ieee80211_mesh_csa_beacon` is successful, it assigns a new value to `ifmsh->csa`. And if that function returns zero, then that means it was successful. That's good. After a successful CSA beacon, `__ieee80211_channel_switch` goes on to set `link_conf->csa_active = true`.
But here's the potential issue: what happens if `ieee80211_set_csa_beacon` *succeeds*, yet something *fails* in `__ieee80211_channel_switch` after that point? I need to make sure that condition is handled properly. Hold on, `ieee80211_set_csa_beacon` is the last thing that can fail in `__ieee80211_channel_switch`, so that condition cannot occur. Okay, I'm going to re-examine `__ieee80211_channel_switch` now to ensure I haven't missed anything.
|
| 53/2 |
2026/08/19 17:16 |
tool |
codesearch-definition-source |
0m
Args: map[Name:__ieee80211_channel_switch]
Results: map[SourceCode:4703: static int
4704: __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
4705: struct cfg80211_csa_settings *params)
4706: {
4707: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
4708: struct ieee80211_chan_req chanreq = {
4709: .oper = params->chandef,
4710: .require_npca = true,
4711: };
4712: struct ieee80211_local *local = sdata->local;
4713: struct ieee80211_channel_switch ch_switch = {
4714: .link_id = params->link_id,
4715: };
4716: struct ieee80211_chanctx_conf *conf;
4717: struct ieee80211_chanctx *chanctx;
4718: struct ieee80211_bss_conf *link_conf;
4719: struct ieee80211_link_data *link_data;
4720: u64 changed = 0;
4721: u8 link_id = params->link_id;
4722: int err;
4723:
4724: lockdep_assert_wiphy(local->hw.wiphy);
4725:
4726: if (ieee80211_is_scan_ongoing(wiphy, local, ¶ms->chandef))
4727: return -EBUSY;
4728:
4729: if (sdata->wdev.links[link_id].cac_started)
4730: return -EBUSY;
4731:
4732: if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS))
4733: return -EINVAL;
4734:
4735: link_data = wiphy_dereference(wiphy, sdata->link[link_id]);
4736: if (!link_data)
4737: return -ENOLINK;
4738:
4739: link_conf = link_data->conf;
4740:
4741: if (chanreq.oper.punctured && !link_conf->eht_support)
4742: return -EINVAL;
4743:
4744: /* don't allow another channel switch if one is already active. */
4745: if (link_conf->csa_active)
4746: return -EBUSY;
4747:
4748: conf = wiphy_dereference(wiphy, link_conf->chanctx_conf);
4749: if (!conf) {
4750: err = -EBUSY;
4751: goto out;
4752: }
4753:
4754: if (params->chandef.chan->freq_offset) {
4755: /* this may work, but is untested */
4756: err = -EOPNOTSUPP;
4757: goto out;
4758: }
4759:
4760: err = ieee80211_set_unsol_bcast_probe_resp(sdata,
4761: ¶ms->unsol_bcast_probe_resp,
4762: link_data, link_conf, &changed);
4763: if (err)
4764: goto out;
4765:
4766: chanctx = container_of(conf, struct ieee80211_chanctx, conf);
4767:
4768: ch_switch.timestamp = 0;
4769: ch_switch.device_timestamp = 0;
4770: ch_switch.block_tx = params->block_tx;
4771: ch_switch.chandef = chanreq.oper;
4772: ch_switch.count = params->count;
4773:
4774: err = drv_pre_channel_switch(sdata, &ch_switch);
4775: if (err)
4776: goto out;
4777:
4778: err = ieee80211_link_reserve_chanctx(link_data, &chanreq,
4779: chanctx->mode,
4780: params->radar_required);
4781: if (err)
4782: goto out;
4783:
4784: /* if reservation is invalid then this will fail */
4785: err = ieee80211_check_combinations(sdata, NULL, 0, 0, -1);
4786: if (err) {
4787: ieee80211_link_unreserve_chanctx(link_data);
4788: goto out;
4789: }
4790:
4791: /* if there is a color change in progress, abort it */
4792: if (link_conf->color_change_active)
4793: ieee80211_color_change_abort(link_data);
4794:
4795: err = ieee80211_set_csa_beacon(link_data, params, &changed);
4796: if (err) {
4797: ieee80211_link_unreserve_chanctx(link_data);
4798: goto out;
4799: }
4800:
4801: link_data->csa.chanreq = chanreq;
4802: link_conf->csa_active = true;
4803:
4804: if (params->block_tx)
4805: ieee80211_vif_block_queues_csa(sdata);
4806:
4807: cfg80211_ch_switch_started_notify(sdata->dev,
4808: &link_data->csa.chanreq.oper, link_id,
4809: params->count, params->block_tx);
4810:
4811: if (changed) {
4812: ieee80211_link_info_change_notify(sdata, link_data, changed);
4813: drv_channel_switch_beacon(sdata, &link_data->csa.chanreq.oper);
4814: } else {
4815: /* if the beacon didn't change, we can finalize immediately */
4816: ieee80211_csa_finalize(link_data);
4817: }
4818:
4819: out:
4820: return err;
4821: }
SourceFile:net/mac80211/cfg.c]
|
| 54/2 |
2026/08/19 17:16 |
llm |
expert |
0m
Model:
Tokens:
input: 57983
output: 29
thoughts: 419
Thoughts: **My Analysis of a Potential CSA Beacon Leak**
Okay, let me trace this through. So, `ieee80211_set_csa_beacon` calls `ieee80211_mesh_csa_beacon`. If that mesh function works, `ifmsh->csa` gets set, and `ieee80211_set_csa_beacon` signals success. Then, `__ieee80211_channel_switch` marks `link_conf->csa_active = true`. Great, everything seems fine; the channel switch initiates successfully.
But, hang on a second, what if `ieee80211_mesh_csa_beacon` gets called *again*? It can only be called again when `link_conf->csa_active` is false. So, when does that happen? Aha, `__ieee80211_csa_finalize`, which in turn calls `ieee80211_set_after_csa_beacon`, which calls `ieee80211_mesh_finish_csa` and *that* frees `ifmsh->csa`! So, `ifmsh->csa` is freed when `csa_active` becomes false, which is the expected behavior.
However... what if the interface is brought down abruptly? `ieee80211_do_stop` *does* set `sdata->vif.bss_conf.csa_active = false;`, which is good, but it does *NOT* call `ieee80211_mesh_finish_csa`. This is a problem. If the interface is taken down *while* a CSA is active, `ifmsh->csa` is leaked. We need to go back and double-check `ieee80211_do_stop`. This is a definite vulnerability.
|
| 55/2 |
2026/08/19 17:17 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_do_stop]
Results: map[SourceCode: 479: static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_down)
480: {
481: struct ieee80211_local *local = sdata->local;
482: struct ieee80211_sub_if_data *iter;
483: unsigned long flags;
484: struct sk_buff_head freeq;
485: struct sk_buff *skb, *tmp;
486: u32 hw_reconf_flags = 0;
487: int i, flushed;
488: struct ps_data *ps;
489: struct cfg80211_chan_def chandef;
490: bool cancel_scan;
491: struct cfg80211_nan_func *func;
492:
493: lockdep_assert_wiphy(local->hw.wiphy);
494:
495: clear_bit(SDATA_STATE_RUNNING, &sdata->state);
496: synchronize_rcu(); /* flush _ieee80211_wake_txqs() */
497:
498: cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata;
499: if (cancel_scan)
500: ieee80211_scan_cancel(local);
501:
502: ieee80211_roc_purge(local, sdata);
503:
504: switch (sdata->vif.type) {
505: case NL80211_IFTYPE_STATION:
506: ieee80211_mgd_stop(sdata);
507: break;
508: case NL80211_IFTYPE_ADHOC:
509: ieee80211_ibss_stop(sdata);
510: break;
511: case NL80211_IFTYPE_MONITOR:
512: list_del_rcu(&sdata->u.mntr.list);
513: break;
514: case NL80211_IFTYPE_AP_VLAN:
515: ieee80211_apvlan_link_clear(sdata);
516: break;
517: default:
518: break;
519: }
520:
521: /*
522: * Remove all stations associated with this interface.
523: *
524: * This must be done before calling ops->remove_interface()
525: * because otherwise we can later invoke ops->sta_notify()
526: * whenever the STAs are removed, and that invalidates driver
527: * assumptions about always getting a vif pointer that is valid
528: * (because if we remove a STA after ops->remove_interface()
529: * the driver will have removed the vif info already!)
530: *
531: * For AP_VLANs, NAN and NAN_DATA stations may exist since there's
532: * nothing else that would have removed them, but in other modes there
533: * shouldn't be any stations.
534: */
535: flushed = sta_info_flush(sdata, -1);
536: WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
537: sdata->vif.type != NL80211_IFTYPE_NAN &&
538: sdata->vif.type != NL80211_IFTYPE_NAN_DATA && flushed > 0);
539:
540: /* don't count this interface for allmulti while it is down */
541: if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
542: atomic_dec(&local->iff_allmultis);
543:
544: if (sdata->vif.type == NL80211_IFTYPE_AP) {
545: local->fif_pspoll--;
546: local->fif_probe_req--;
547: } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
548: local->fif_probe_req--;
549: }
550:
551: if (sdata->dev) {
552: netif_addr_lock_bh(sdata->dev);
553: spin_lock_bh(&local->filter_lock);
554: __hw_addr_unsync(&local->mc_list, &sdata->dev->mc,
555: sdata->dev->addr_len);
556: spin_unlock_bh(&local->filter_lock);
557: netif_addr_unlock_bh(sdata->dev);
558: }
559:
560: timer_delete_sync(&local->dynamic_ps_timer);
561: wiphy_work_cancel(local->hw.wiphy, &local->dynamic_ps_enable_work);
562:
563: WARN(ieee80211_vif_is_mld(&sdata->vif),
564: "destroying interface with valid links 0x%04x\n",
565: sdata->vif.valid_links);
566:
567: sdata->vif.bss_conf.csa_active = false;
568: if (sdata->vif.type == NL80211_IFTYPE_STATION)
569: sdata->deflink.u.mgd.csa.waiting_bcn = false;
570: ieee80211_vif_unblock_queues_csa(sdata);
571:
572: wiphy_work_cancel(local->hw.wiphy, &sdata->deflink.csa.finalize_work);
573: wiphy_work_cancel(local->hw.wiphy,
574: &sdata->deflink.color_change_finalize_work);
575: wiphy_hrtimer_work_cancel(local->hw.wiphy,
576: &sdata->deflink.dfs_cac_timer_work);
577:
578: if (sdata->wdev.links[0].cac_started) {
579: chandef = sdata->vif.bss_conf.chanreq.oper;
580: WARN_ON(local->suspended);
581: ieee80211_link_release_channel(&sdata->deflink);
582: cfg80211_cac_event(sdata->dev, &chandef,
583: NL80211_RADAR_CAC_ABORTED,
584: GFP_KERNEL, 0);
585: }
586:
587: if (sdata->vif.type == NL80211_IFTYPE_AP) {
588: WARN_ON(!list_empty(&sdata->u.ap.vlans));
589: } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
590: /* remove all packets in parent bc_buf pointing to this dev */
591: __skb_queue_head_init(&freeq);
592: ps = &sdata->bss->ps;
593:
594: spin_lock_irqsave(&ps->bc_buf.lock, flags);
595: skb_queue_walk_safe(&ps->bc_buf, skb, tmp) {
596: if (skb->dev == sdata->dev) {
597: __skb_unlink(skb, &ps->bc_buf);
598: local->total_ps_buffered--;
599: __skb_queue_tail(&freeq, skb);
600: }
601: }
602: spin_unlock_irqrestore(&ps->bc_buf.lock, flags);
603:
604: skb_queue_walk_safe(&freeq, skb, tmp) {
605: __skb_unlink(skb, &freeq);
606: ieee80211_free_txskb(&local->hw, skb);
607: }
608: }
609:
610: if (going_down)
611: local->open_count--;
612:
613: switch (sdata->vif.type) {
614: case NL80211_IFTYPE_AP_VLAN:
615: list_del(&sdata->u.vlan.list);
616: RCU_INIT_POINTER(sdata->vif.bss_conf.chanctx_conf, NULL);
617: /* see comment in the default case below */
618: ieee80211_free_keys(sdata, true);
619: /* no need to tell driver */
620: break;
621: case NL80211_IFTYPE_MONITOR:
622: local->monitors--;
623:
624: if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) &&
625: !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
626:
627: local->virt_monitors--;
628: if (local->virt_monitors == 0) {
629: local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;
630: hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
631: }
632:
633: ieee80211_adjust_monitor_flags(sdata, -1);
634: }
635: break;
636: case NL80211_IFTYPE_NAN:
637: /* Check if any open NAN_DATA interfaces */
638: list_for_each_entry(iter, &local->interfaces, list) {
639: WARN_ON(iter->vif.type == NL80211_IFTYPE_NAN_DATA &&
640: ieee80211_sdata_running(iter));
641: }
642:
643: /* clean all the functions */
644: if (!(local->hw.wiphy->nan_capa.flags &
645: WIPHY_NAN_FLAGS_USERSPACE_DE)) {
646: spin_lock_bh(&sdata->u.nan.de.func_lock);
647:
648: idr_for_each_entry(&sdata->u.nan.de.function_inst_ids,
649: func, i) {
650: idr_remove(&sdata->u.nan.de.function_inst_ids, i);
651: cfg80211_free_nan_func(func);
652: }
653: idr_destroy(&sdata->u.nan.de.function_inst_ids);
654:
655: spin_unlock_bh(&sdata->u.nan.de.func_lock);
656: }
657:
658: /*
659: * Free the remaining keys that might be associated with the
660: * NAN interface, e.g., IGTK and BIGTK used for Tx.
661: */
662: ieee80211_free_keys(sdata, true);
663: break;
664: case NL80211_IFTYPE_NAN_DATA:
665: RCU_INIT_POINTER(sdata->u.nan_data.nmi, NULL);
666: fallthrough;
667: default:
668: wiphy_work_cancel(sdata->local->hw.wiphy, &sdata->work);
669: /*
670: * When we get here, the interface is marked down.
671: * Free the remaining keys, if there are any
672: * (which can happen in AP mode if userspace sets
673: * keys before the interface is operating)
674: *
675: * Force the key freeing to always synchronize_net()
676: * to wait for the RX path in case it is using this
677: * interface enqueuing frames at this very time on
678: * another CPU.
679: */
680: ieee80211_free_keys(sdata, true);
681: skb_queue_purge(&sdata->skb_queue);
682: skb_queue_purge(&sdata->status_queue);
683: }
684:
685: /*
686: * Since ieee80211_free_txskb() may issue __dev_queue_xmit()
687: * which should be called with interrupts enabled, reclamation
688: * is done in two phases:
689: */
690: __skb_queue_head_init(&freeq);
691:
692: /* unlink from local queues... */
693: spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
694: for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
695: skb_queue_walk_safe(&local->pending[i], skb, tmp) {
696: struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
697: if (info->control.vif == &sdata->vif) {
698: __skb_unlink(skb, &local->pending[i]);
699: __skb_queue_tail(&freeq, skb);
700: }
701: }
702: }
703: spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
704:
705: /* ... and perform actual reclamation with interrupts enabled. */
706: skb_queue_walk_safe(&freeq, skb, tmp) {
707: __skb_unlink(skb, &freeq);
708: ieee80211_free_txskb(&local->hw, skb);
709: }
710:
711: if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
712: ieee80211_txq_remove_vlan(local, sdata);
713:
714: if (sdata->vif.txq)
715: ieee80211_txq_purge(sdata->local, to_txq_info(sdata->vif.txq));
716:
717: if (sdata->vif.txq_mgmt)
718: ieee80211_txq_purge(sdata->local,
719: to_txq_info(sdata->vif.txq_mgmt));
720:
721: sdata->bss = NULL;
722:
723: if (local->open_count == 0)
724: ieee80211_clear_tx_pending(local);
725:
726: sdata->vif.bss_conf.beacon_int = 0;
727:
728: /*
729: * If the interface goes down while suspended, presumably because
730: * the device was unplugged and that happens before our resume,
731: * then the driver is already unconfigured and the remainder of
732: * this function isn't needed.
733: * XXX: what about WoWLAN? If the device has software state, e.g.
734: * memory allocated, it might expect teardown commands from
735: * mac80211 here?
736: */
737: if (local->suspended) {
738: WARN_ON(local->wowlan);
739: WARN_ON(rcu_access_pointer(local->monitor_sdata));
740: return;
741: }
742:
743: switch (sdata->vif.type) {
744: case NL80211_IFTYPE_AP_VLAN:
745: break;
746: case NL80211_IFTYPE_MONITOR:
747: if (local->virt_monitors == 0)
748: ieee80211_del_virtual_monitor(local);
749:
750: ieee80211_recalc_idle(local);
751: ieee80211_recalc_offload(local);
752:
753: if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) &&
754: !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
755: break;
756:
757: ieee80211_link_release_channel(&sdata->deflink);
758: fallthrough;
759: default:
760: if (!going_down)
761: break;
762: drv_remove_interface(local, sdata);
763:
764: /* Clear private driver data to prevent reuse */
765: memset(sdata->vif.drv_priv, 0, local->hw.vif_data_size);
766: }
767:
768: ieee80211_recalc_ps(local);
769:
770: if (cancel_scan)
771: wiphy_delayed_work_flush(local->hw.wiphy, &local->scan_work);
772:
773: if (local->open_count == 0) {
774: ieee80211_stop_device(local, false);
775:
776: /* no reconfiguring after stop! */
777: return;
778: }
779:
780: /* do after stop to avoid reconfiguring when we stop anyway */
781: ieee80211_configure_filter(local);
782: ieee80211_hw_config(local, -1, hw_reconf_flags);
783:
784: /* Passing NULL means an interface is picked for configuration */
785: if (local->virt_monitors == local->open_count)
786: ieee80211_add_virtual_monitor(local, NULL);
787: }
SourceFile:net/mac80211/iface.c]
|
| 56/2 |
2026/08/19 17:17 |
llm |
expert |
0m
Model:
Tokens:
input: 64333
output: 29
thoughts: 62
Thoughts: **Investigating the CSA Memory Leak**
Okay, so I'm looking at this `ieee80211_do_stop` function, and something's bugging me. It doesn't seem to be freeing `ifmsh->csa`. That's a classic memory leak in the making. Let's see... is this handled anywhere else? I need to track down where this memory is supposed to be released. My first thought is to check `ieee80211_mesh_stop`. That seems like the most logical place to start looking for the corresponding cleanup. It’s got to be freed somewhere, or we're going to have a growing problem on our hands.
|
| 57/2 |
2026/08/19 17:17 |
tool |
codesearch-definition-source |
0m
Error:
Args: map[Name:ieee80211_mesh_stop]
Results: map[SourceCode: SourceFile:]
|
| 58/2 |
2026/08/19 17:17 |
llm |
expert |
0m
Model:
Tokens:
input: 64596
output: 17
thoughts: 11
Thoughts: Okay, here's my summary, presented as a stream of thought:
**Mesh Query Conundrum**
Hmm, I'm working with this mesh, and I'm trying to figure out how to cleanly interrupt its processing or perhaps check for a specific stopping condition within a loop or recursive process. Basically, is there a built-in function or a flag, something akin to a `mesh_stop` command that I can utilize to gracefully halt the current mesh operation without creating a lot of messy side effects? I know my way around meshes, so I'm thinking a quick command that says, "Hey, stop processing the mesh," would be ideal and prevent me from manually setting up flags and conditionals that get out of hand.
|
| 59/2 |
2026/08/19 17:17 |
tool |
grepper |
0m
Args: map[Expression:mesh_stop]
Results: map[Output:drivers/net/wireless/marvell/libertas/mesh.c=885=int lbs_deinit_mesh(struct lbs_private *priv)
--
drivers/net/wireless/marvell/libertas/mesh.c-899-/**
drivers/net/wireless/marvell/libertas/mesh.c:900: * lbs_mesh_stop - close the mshX interface
drivers/net/wireless/marvell/libertas/mesh.c-901- *
--
drivers/net/wireless/marvell/libertas/mesh.c-904- */
drivers/net/wireless/marvell/libertas/mesh.c:905:static int lbs_mesh_stop(struct net_device *dev)
drivers/net/wireless/marvell/libertas/mesh.c-906-{
--
drivers/net/wireless/marvell/libertas/mesh.c=965=static const struct net_device_ops mesh_netdev_ops = {
drivers/net/wireless/marvell/libertas/mesh.c-966- .ndo_open = lbs_mesh_dev_open,
drivers/net/wireless/marvell/libertas/mesh.c:967: .ndo_stop = lbs_mesh_stop,
drivers/net/wireless/marvell/libertas/mesh.c-968- .ndo_start_xmit = lbs_hard_start_xmit,
]
|
| 60/2 |
2026/08/19 17:17 |
llm |
expert |
0m
Model:
Tokens:
input: 65135
output: 29
thoughts: 17
Thoughts: Okay, here's my attempt at summarizing that thought process, tailored for an expert audience:
**Analyzing the `ieee80211_leave_mesh` Function**
Alright, let's dive into this `ieee80211_leave_mesh` function. I need to refresh my memory on what that particular mesh leave function entails. It's likely involved in dismantling a mesh network connection, but I want to be sure I understand the precise implications within the broader 802.11 framework. I need to consider all possible cleanup operations the function handles when a mesh node wants to disconnect from a mesh network. Are we dealing with deauthentication, key exchange cleanup, route table removal, neighbor discovery, or something else entirely? A quick review of the code will clarify the core responsibilities of this module and determine whether there are any memory leaks or performance implications. I am trying to determine if anything obvious stands out from the start, as I know my time is valuable and it would save effort if I don't have to trace a very long and complex interaction sequence. I need to be efficient about this initial assessment.
|
| 61/2 |
2026/08/19 17:17 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_leave_mesh]
Results: map[SourceCode:3326: static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
3327: {
3328: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
3329:
3330: lockdep_assert_wiphy(sdata->local->hw.wiphy);
3331:
3332: ieee80211_stop_mesh(sdata);
3333: ieee80211_link_release_channel(&sdata->deflink);
3334: kfree(sdata->u.mesh.ie);
3335:
3336: return 0;
3337: }
SourceFile:net/mac80211/cfg.c]
|
| 62/2 |
2026/08/19 17:17 |
llm |
expert |
0m
Model:
Tokens:
input: 65672
output: 29
thoughts: 17
Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience:
**Analyzing `ieee80211_stop_mesh` Function**
Okay, let's dive into this `ieee80211_stop_mesh` function. I need to understand exactly what happens here when we're shutting down the mesh interface. Presumably, this is where we're cleaning up resources, disconnecting from the mesh network, and maybe disabling certain functionalities to prevent interference or data corruption during the shutdown process.
I'm expecting to see a sequence of calls. First, I want to check for resource deallocation – memory, sockets, timers, any mesh-specific data structures. We probably have to ensure that all associated stations or peers are gracefully handled and detached. Error handling will be critical here: what happens if some cleanup fails? Are there retries, logging, or fallback mechanisms?
I also need to see how the function interacts with the hardware. Is there a call to disable the radio interface, or maybe a specific command to the MAC layer to stop mesh transmission? Is it a clean shutdown or an abrupt one? I need to look for any potential race conditions during this process as it could leave the system in an unstable state.
I'll be looking carefully at how this function integrates with the broader `ieee80211` framework. Where does it fit in the mesh lifecycle? Is it called from the main mesh interface shutdown sequence or a lower-level driver-specific routine? Is it called synchronously or asynchronously? These things are all going to give me a better understanding of the overall robustness of the mesh implementation. I need to make sure this function doesn't introduce vulnerabilities or unexpected side effects.
|
| 63/2 |
2026/08/19 17:17 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_stop_mesh]
Results: map[SourceCode:1199: void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
1200: {
1201: struct ieee80211_local *local = sdata->local;
1202: struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
1203: struct beacon_data *bcn;
1204:
1205: netif_carrier_off(sdata->dev);
1206:
1207: /* flush STAs and mpaths on this iface */
1208: sta_info_flush(sdata, -1);
1209: ieee80211_free_keys(sdata, true);
1210: mesh_path_flush_by_iface(sdata);
1211:
1212: /* stop the beacon */
1213: ifmsh->mesh_id_len = 0;
1214: sdata->vif.bss_conf.enable_beacon = false;
1215: sdata->beacon_rate_set = false;
1216: clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
1217: ieee80211_link_info_change_notify(sdata, &sdata->deflink,
1218: BSS_CHANGED_BEACON_ENABLED);
1219:
1220: /* remove beacon */
1221: bcn = sdata_dereference(ifmsh->beacon, sdata);
1222: RCU_INIT_POINTER(ifmsh->beacon, NULL);
1223: kfree_rcu(bcn, rcu_head);
1224:
1225: /* free all potentially still buffered group-addressed frames */
1226: local->total_ps_buffered -= skb_queue_len(&ifmsh->ps.bc_buf);
1227: skb_queue_purge(&ifmsh->ps.bc_buf);
1228:
1229: timer_delete_sync(&sdata->u.mesh.housekeeping_timer);
1230: timer_delete_sync(&sdata->u.mesh.mesh_path_root_timer);
1231: timer_delete_sync(&sdata->u.mesh.mesh_path_timer);
1232:
1233: /* clear any mesh work (for next join) we may have accrued */
1234: ifmsh->wrkq_flags = 0;
1235: memset(ifmsh->mbss_changed, 0, sizeof(ifmsh->mbss_changed));
1236:
1237: local->fif_other_bss--;
1238: atomic_dec(&local->iff_allmultis);
1239: ieee80211_configure_filter(local);
1240: }
SourceFile:net/mac80211/mesh.c]
|
| 64/2 |
2026/08/19 17:17 |
llm |
expert |
0m
Model:
Tokens:
input: 66913
output: 16
thoughts: 828
Thoughts: **The Mesh CSA Leak**
Okay, here's the situation. It looks like `ieee80211_stop_mesh` *doesn't* free `ifmsh->csa`. That's a problem. If we stop a mesh interface while a CSA (Channel Switch Announcement) is active, we've got a leak – `ifmsh->csa` just stays allocated.
The question is, can we *actually* trigger this condition? And yes, the reproducer demonstrates we can. It sets things up with a series of ioctls and netlink messages: socket, interface index, a DGRAM socket, setting IFF_MULTICAST (0x1000, huh? IFF_UP should be 1, got it). Then there's the critical bit:
```c
syscall(__NR_ioctl, /*fd=*/r[3], /*cmd=*/0x8914, /*arg=*/0x200000000300ul); // IFF_MULTICAST
syscall(__NR_sendmsg, /*fd=*/r[0], /*msg=*/0x200000000100ul, /*f=*/0ul); // NL80211_CMD_SET_INTERFACE (type=7, NL80211_IFTYPE_MESH_POINT)
syscall(__NR_ioctl, /*fd=*/r[3], /*cmd=*/0x8914, /*arg=*/0x200000000000ul); // IFF_UP
syscall(__NR_sendmsg, /*fd=*/r[0], /*msg=*/0x200000000040ul, /*f=...); // NL80211_CMD_JOIN_MESH
syscall(__NR_sendmsg, /*fd=*/r[5], /*msg=*/0x200000000200ul, /*f=*/0ul); // NL80211_CMD_CHANNEL_SWITCH
```
The reproducer just exits after a `NL80211_CMD_CHANNEL_SWITCH`. When the process dies, the netlink sockets close, but the interface, "wlan0", sticks around. That's likely a mac80211_hwsim interface created by syzkaller. When syzkaller is done, it destroys the interface or the network namespace. This triggers `ieee80211_teardown_sdata`, which, in turn, calls `ieee80211_mesh_teardown_sdata`. And here's the kicker: `ieee80211_mesh_teardown_sdata` *still* doesn't free `ifmsh->csa`. Also, `ieee80211_leave_mesh` also calls `ieee80211_stop_mesh` which does the same!
So, to be absolutely sure, it looks like `ifmsh->csa` is leaked. I already grepped for `kfree.*csa`, and that came up empty. Just to be thorough, I should grep for `csa` in `net/mac80211/mesh.c`.
|
| 65/2 |
2026/08/19 17:17 |
tool |
grepper |
0m
Args:
Results: map[Output:
Full output is too long, showing 500 out of 12371 lines.
Use more precise expression if possible.
CREDITS=409=N: Srivatsa S. Bhat
CREDITS:410:E: srivatsa@csail.mit.edu
CREDITS-411-D: Maintainer of Generic Paravirt-Ops subsystem
--
CREDITS=4322=E: wendling@ganymede.isdn.uiuc.edu
CREDITS:4323:W: http://www.ncsa.uiuc.edu/~wendling/
CREDITS-4324-D: Various random hacks. Mostly on poll/select logic.
--
Documentation/RCU/RTFP.txt=2042=lot of {Linux} into your technology!!!"
--
Documentation/RCU/RTFP.txt-2679-,address = {London, UK}
Documentation/RCU/RTFP.txt:2680:,url="http://people.csail.mit.edu/nickolai/papers/clements-bonsai.pdf"
Documentation/RCU/RTFP.txt-2681-}
--
Documentation/RCU/torture.rst=209=parameter to kvm.sh may be used, for example, ``--kconfig 'CONFIG_RCU_EQS_DEBUG=y'``.
Documentation/RCU/torture.rst:210:In addition, there are the --gdb, --kasan, and --kcsan parameters.
Documentation/RCU/torture.rst-211-Note that --gdb limits you to one scenario per kvm.sh run and requires
--
Documentation/admin-guide/devices.txt-183- 127 = /dev/vcsu63 tty63 text (unicode) contents
Documentation/admin-guide/devices.txt:184: 128 = /dev/vcsa Current vc text/attribute (glyph) contents
Documentation/admin-guide/devices.txt:185: 129 = /dev/vcsa1 tty1 text/attribute (glyph) contents
Documentation/admin-guide/devices.txt-186- ...
Documentation/admin-guide/devices.txt:187: 191 = /dev/vcsa63 tty63 text/attribute (glyph) contents
Documentation/admin-guide/devices.txt-188-
--
Documentation/admin-guide/devices.txt-2374- 168 char Eracom CSA7000 PCI encryption adaptor
Documentation/admin-guide/devices.txt:2375: 0 = /dev/ecsa0 First CSA7000
Documentation/admin-guide/devices.txt:2376: 1 = /dev/ecsa1 Second CSA7000
Documentation/admin-guide/devices.txt-2377- ...
--
Documentation/admin-guide/devices.txt-2379- 169 char Eracom CSA8000 PCI encryption adaptor
Documentation/admin-guide/devices.txt:2380: 0 = /dev/ecsa8-0 First CSA8000
Documentation/admin-guide/devices.txt:2381: 1 = /dev/ecsa8-1 Second CSA8000
Documentation/admin-guide/devices.txt-2382- ...
--
Documentation/arch/x86/resume.svg-3-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
Documentation/arch/x86/resume.svg:4:<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="582px" height="1152px" viewBox="-0.5 -0.5 582 1152" content=...
--
Documentation/dev-tools/index.rst=14=Documentation/process/debugging/index.rst
--
Documentation/dev-tools/index.rst-31- kmemleak
Documentation/dev-tools/index.rst:32: kcsan
Documentation/dev-tools/index.rst-33- lkmm/index
--
Documentation/dev-tools/kcsan.rst=21=KCSAN provides several other configuration options to customize behaviour (see
Documentation/dev-tools/kcsan.rst:22:the respective help text in ``lib/Kconfig.kcsan`` for more info).
Documentation/dev-tools/kcsan.rst-23-
--
Documentation/dev-tools/kcsan.rst=87=the below options are available:
--
Documentation/dev-tools/kcsan.rst-104-* Disabling data race detection for entire functions can be accomplished by
Documentation/dev-tools/kcsan.rst:105: using the function attribute ``__no_kcsan``::
Documentation/dev-tools/kcsan.rst-106-
Documentation/dev-tools/kcsan.rst:107: __no_kcsan
Documentation/dev-tools/kcsan.rst-108- void foo(void) {
--
Documentation/dev-tools/kcsan.rst=128=Kconfig options:
--
Documentation/dev-tools/kcsan.rst-143- option depends on ``CONFIG_KCSAN_REPORT_VALUE_CHANGE_ONLY=y``. For details
Documentation/dev-tools/kcsan.rst:144: please see the ``kernel/kcsan/permissive.h``. Testers and maintainers that
Documentation/dev-tools/kcsan.rst-145- only focus on reports from specific subsystems and not the whole kernel are
--
Documentation/dev-tools/kcsan.rst=152=DebugFS interface
--
Documentation/dev-tools/kcsan.rst-154-
Documentation/dev-tools/kcsan.rst:155:The file ``/sys/kernel/debug/kcsan`` provides the following interface:
Documentation/dev-tools/kcsan.rst-156-
Documentation/dev-tools/kcsan.rst:157:* Reading ``/sys/kernel/debug/kcsan`` returns various runtime statistics.
Documentation/dev-tools/kcsan.rst-158-
Documentation/dev-tools/kcsan.rst:159:* Writing ``on`` or ``off`` to ``/sys/kernel/debug/kcsan`` allows turning KCSAN
Documentation/dev-tools/kcsan.rst-160- on or off, respectively.
Documentation/dev-tools/kcsan.rst-161-
Documentation/dev-tools/kcsan.rst:162:* Writing ``!some_func_name`` to ``/sys/kernel/debug/kcsan`` adds
Documentation/dev-tools/kcsan.rst-163- ``some_func_name`` to the report filter list, which (by default) blacklists
--
Documentation/dev-tools/kcsan.rst-166-
Documentation/dev-tools/kcsan.rst:167:* Writing either ``blacklist`` or ``whitelist`` to ``/sys/kernel/debug/kcsan``
Documentation/dev-tools/kcsan.rst-168- changes the report filtering behaviour. For example, the blacklist feature
--
Documentation/dev-tools/kcsan.rst=177=changed via the corresponding Kconfig options.
Documentation/dev-tools/kcsan.rst-178-
Documentation/dev-tools/kcsan.rst:179:* ``kcsan.skip_watch`` (``CONFIG_KCSAN_SKIP_WATCH``): Number of per-CPU memory
Documentation/dev-tools/kcsan.rst-180- operations to skip, before another watchpoint is set up. Setting up
--
Documentation/dev-tools/kcsan.rst-184-
Documentation/dev-tools/kcsan.rst:185:* ``kcsan.udelay_task`` (``CONFIG_KCSAN_UDELAY_TASK``): For tasks, the
Documentation/dev-tools/kcsan.rst-186- microsecond delay to stall execution after a watchpoint has been set up.
--
Documentation/dev-tools/kcsan.rst-189-
Documentation/dev-tools/kcsan.rst:190:* ``kcsan.udelay_interrupt`` (``CONFIG_KCSAN_UDELAY_INTERRUPT``): For
Documentation/dev-tools/kcsan.rst-191- interrupts, the microsecond delay to stall execution after a watchpoint has
--
Documentation/dev-tools/kcsan.rst-194-
Documentation/dev-tools/kcsan.rst:195:They may be tweaked at runtime via ``/sys/module/kcsan/parameters/``.
Documentation/dev-tools/kcsan.rst-196-
--
Documentation/dev-tools/kcsan.rst=236=properties of concurrent code where bugs would not manifest as data races.
Documentation/dev-tools/kcsan.rst-237-
Documentation/dev-tools/kcsan.rst:238:.. kernel-doc:: include/linux/kcsan-checks.h
Documentation/dev-tools/kcsan.rst-239- :functions: ASSERT_EXCLUSIVE_WRITER ASSERT_EXCLUSIVE_WRITER_SCOPED
--
Documentation/dev-tools/testing-overview.rst=94=Some of these tools are listed below:
--
Documentation/dev-tools/testing-overview.rst-101- overflows. See Documentation/dev-tools/ubsan.rst
Documentation/dev-tools/testing-overview.rst:102:* KCSAN detects data races. See Documentation/dev-tools/kcsan.rst
Documentation/dev-tools/testing-overview.rst-103-* KFENCE is a low-overhead detector of memory issues, which is much faster than
--
Documentation/devicetree/bindings/hsi/client-devices.txt=26=hsi-controller {
--
Documentation/devicetree/bindings/hsi/client-devices.txt-31- hsi-channel-ids = <0>, <1>, <2>, <3>;
Documentation/devicetree/bindings/hsi/client-devices.txt:32: hsi-channel-names = "mcsaab-control",
Documentation/devicetree/bindings/hsi/client-devices.txt-33- "speech-control",
Documentation/devicetree/bindings/hsi/client-devices.txt-34- "speech-data",
Documentation/devicetree/bindings/hsi/client-devices.txt:35: "mcsaab-data";
Documentation/devicetree/bindings/hsi/client-devices.txt-36- hsi-speed-kbps = <55000>;
--
Documentation/devicetree/bindings/hsi/nokia-modem.txt=7=Required properties:
--
Documentation/devicetree/bindings/hsi/nokia-modem.txt-12-- hsi-channel-names: Should contain the following strings
Documentation/devicetree/bindings/hsi/nokia-modem.txt:13: "mcsaab-control"
Documentation/devicetree/bindings/hsi/nokia-modem.txt-14- "speech-control"
Documentation/devicetree/bindings/hsi/nokia-modem.txt-15- "speech-data"
Documentation/devicetree/bindings/hsi/nokia-modem.txt:16: "mcsaab-data"
Documentation/devicetree/bindings/hsi/nokia-modem.txt-17-- gpios: Should provide a GPIO handler for each GPIO listed in
--
Documentation/devicetree/bindings/hsi/nokia-modem.txt=27=Example:
--
Documentation/devicetree/bindings/hsi/nokia-modem.txt-36- hsi-channel-ids = <0>, <1>, <2>, <3>;
Documentation/devicetree/bindings/hsi/nokia-modem.txt:37: hsi-channel-names = "mcsaab-control",
Documentation/devicetree/bindings/hsi/nokia-modem.txt-38- "speech-control",
Documentation/devicetree/bindings/hsi/nokia-modem.txt-39- "speech-data",
Documentation/devicetree/bindings/hsi/nokia-modem.txt:40: "mcsaab-data";
Documentation/devicetree/bindings/hsi/nokia-modem.txt-41- hsi-speed-kbps = <55000>;
--
Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.yaml=12=description: |
--
Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.yaml-27-
Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.yaml:28: [1] https://pdos.csail.mit.edu/6.828/2008/readings/ia32/IA32-3A.pdf
Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.yaml-29-
--
Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml=12=description: |
--
Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml-27-
Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml:28: [1] https://pdos.csail.mit.edu/6.828/2008/readings/ia32/IA32-3A.pdf
Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml-29-
--
Documentation/devicetree/bindings/leds/backlight/arc,arc2c0608.yaml=17=maintainers:
Documentation/devicetree/bindings/leds/backlight/arc,arc2c0608.yaml:18: - Brian Dodge <bdodge@arcticsand.com>
Documentation/devicetree/bindings/leds/backlight/arc,arc2c0608.yaml-19-
--
Documentation/devicetree/bindings/spi/fsl,espi.yaml=12=properties:
--
Documentation/devicetree/bindings/spi/fsl,espi.yaml-32-
Documentation/devicetree/bindings/spi/fsl,espi.yaml:33: fsl,csaft:
Documentation/devicetree/bindings/spi/fsl,espi.yaml-34- $ref: /schemas/types.yaml#/definitions/uint32
--
Documentation/devicetree/bindings/spi/fsl,espi.yaml=50=examples:
--
Documentation/devicetree/bindings/spi/fsl,espi.yaml-61- fsl,csbef = <1>;
Documentation/devicetree/bindings/spi/fsl,espi.yaml:62: fsl,csaft = <1>;
Documentation/devicetree/bindings/spi/fsl,espi.yaml-63- };
--
Documentation/fb/matroxfb.rst=361=It is time to redraw whole screen 1000 times in 1024x768, 60Hz. It is
Documentation/fb/matroxfb.rst:362:time for draw 6144000 characters on screen through /dev/vcsa
Documentation/fb/matroxfb.rst-363-(for 32bpp it is about 3GB of data (exactly 3000 MB); for 8x16 font in
--
Documentation/netlink/specs/nl80211.yaml=230=attribute-sets:
--
Documentation/netlink/specs/nl80211.yaml-808- -
Documentation/netlink/specs/nl80211.yaml:809: name: csa-ies
Documentation/netlink/specs/nl80211.yaml-810- type: binary # TODO: nest
--
Documentation/netlink/specs/nl80211.yaml-869- -
Documentation/netlink/specs/nl80211.yaml:870: name: csa-c-offsets-tx
Documentation/netlink/specs/nl80211.yaml-871- type: binary
Documentation/netlink/specs/nl80211.yaml-872- -
Documentation/netlink/specs/nl80211.yaml:873: name: max-csa-counters
Documentation/netlink/specs/nl80211.yaml-874- type: u8
--
Documentation/netlink/specs/nl80211.yaml=1796=operations:
--
Documentation/netlink/specs/nl80211.yaml-1826- - mac
Documentation/netlink/specs/nl80211.yaml:1827: - max-csa-counters
Documentation/netlink/specs/nl80211.yaml-1828- - max-match-sets
--
Documentation/sphinx/kerneldoc-preamble.sty-104- }
Documentation/sphinx/kerneldoc-preamble.sty:105: \newCJKfontfamily[SCsans]\scsans{Noto Sans CJK SC}[AutoFakeSlant]
Documentation/sphinx/kerneldoc-preamble.sty-106- \newCJKfontfamily[SCmono]\scmono{Noto Sans Mono CJK SC}[AutoFakeSlant]
--
Documentation/sphinx/kerneldoc-preamble.sty-114- }
Documentation/sphinx/kerneldoc-preamble.sty:115: \newCJKfontfamily[TCsans]\tcsans{Noto Sans CJK TC}[AutoFakeSlant]
Documentation/sphinx/kerneldoc-preamble.sty-116- \newCJKfontfamily[TCmono]\tcmono{Noto Sans Mono CJK TC}[AutoFakeSlant]
--
Documentation/translations/it_IT/RCU/torture.rst=202=usare il parametro --kconfig, per esempio, ``--kconfig
Documentation/translations/it_IT/RCU/torture.rst-203-'CONFIG_RCU_EQS_DEBUG=y'``. In aggiunta, ci sono i parametri --gdb, --kasan, and
Documentation/translations/it_IT/RCU/torture.rst:204:kcsan. Da notare che --gdb vi limiterà all'uso di un solo scenario per
Documentation/translations/it_IT/RCU/torture.rst-205-esecuzione di kvm.sh e richiede di avere anche un'altra finestra aperta dalla
--
Documentation/translations/zh_CN/dev-tools/index.rst=15=Documentation/translations/zh_CN/dev-tools/testing-overview.rst
--
Documentation/translations/zh_CN/dev-tools/index.rst-23- kcov
Documentation/translations/zh_CN/dev-tools/index.rst:24: kcsan
Documentation/translations/zh_CN/dev-tools/index.rst-25- kmsan
--
Documentation/translations/zh_CN/dev-tools/kcsan.rst-4-
Documentation/translations/zh_CN/dev-tools/kcsan.rst:5::Original: Documentation/dev-tools/kcsan.rst
Documentation/translations/zh_CN/dev-tools/kcsan.rst-6-:Translator: 刘浩阳 Haoyang Liu <tttturtleruss@hust.edu.cn>
--
Documentation/translations/zh_CN/dev-tools/kcsan.rst=17=KCSAN 受 GCC 和 Clang 支持。使用 GCC 需要版本 11 或更高,使用 Clang 也需要
--
Documentation/translations/zh_CN/dev-tools/kcsan.rst-23-
Documentation/translations/zh_CN/dev-tools/kcsan.rst:24:KCSAN 提供了几个其他的配置选项来自定义行为(见 ``lib/Kconfig.kcsan`` 中的各自的
Documentation/translations/zh_CN/dev-tools/kcsan.rst-25-帮助文档以获取更多信息)。
--
Documentation/translations/zh_CN/dev-tools/kcsan.rst-100-
Documentation/translations/zh_CN/dev-tools/kcsan.rst:101:* 使用函数属性 ``__no_kcsan`` 可以对整个函数禁用数据竞争检测::
Documentation/translations/zh_CN/dev-tools/kcsan.rst-102-
Documentation/translations/zh_CN/dev-tools/kcsan.rst:103: __no_kcsan
Documentation/translations/zh_CN/dev-tools/kcsan.rst-104- void foo(void) {
--
Documentation/translations/zh_CN/dev-tools/kcsan.rst=121=Kconfig 参数进行更改:
--
Documentation/translations/zh_CN/dev-tools/kcsan.rst-134- 选项依赖编译选项 ``CONFIG_KCSAN_REPORT_VALUE_CHANGE_ONLY=y``。请查看
Documentation/translations/zh_CN/dev-tools/kcsan.rst:135: ``kernel/kcsan/permissive.h`` 获取更多细节。对于只侧重于特定子系统而不是整个
Documentation/translations/zh_CN/dev-tools/kcsan.rst-136- 内核报告的测试者和维护者,建议禁用该选项。
--
Documentation/translations/zh_CN/dev-tools/kcsan.rst=141=Debug 文件系统接口
--
Documentation/translations/zh_CN/dev-tools/kcsan.rst-143-
Documentation/translations/zh_CN/dev-tools/kcsan.rst:144:文件 ``/sys/kernel/debug/kcsan`` 提供了如下接口:
Documentation/translations/zh_CN/dev-tools/kcsan.rst-145-
Documentation/translations/zh_CN/dev-tools/kcsan.rst:146:* 读 ``/sys/kernel/debug/kcsan`` 返回不同的运行时统计数据。
Documentation/translations/zh_CN/dev-tools/kcsan.rst-147-
Documentation/translations/zh_CN/dev-tools/kcsan.rst:148:* 将 ``on`` 或 ``off`` 写入 ``/sys/kernel/debug/kcsan`` 允许打开或关闭 KCSAN。
Documentation/translations/zh_CN/dev-tools/kcsan.rst-149-
Documentation/translations/zh_CN/dev-tools/kcsan.rst:150:* 将 ``!some_func_name`` 写入 ``/sys/kernel/debug/kcsan`` 会将
Documentation/translations/zh_CN/dev-tools/kcsan.rst-151- ``some_func_name`` 添加到报告过滤列表中,该列表(默认)会将数据竞争报告中的顶
--
Documentation/translations/zh_CN/dev-tools/kcsan.rst-153-
Documentation/translations/zh_CN/dev-tools/kcsan.rst:154:* 将 ``blacklist`` 或 ``whitelist`` 写入 ``/sys/kernel/debug/kcsan`` 会改变报告
Documentation/translations/zh_CN/dev-tools/kcsan.rst-155- 过滤行为。例如,黑名单的特性可以用来过滤掉经常发生的数据竞争。白名单特性可以帮
--
Documentation/translations/zh_CN/dev-tools/kcsan.rst-163-
Documentation/translations/zh_CN/dev-tools/kcsan.rst:164:* ``kcsan.skip_watch`` (``CONFIG_KCSAN_SKIP_WATCH``): 在另一个观测点设置之前每
Documentation/translations/zh_CN/dev-tools/kcsan.rst-165- 个 CPU 要跳过的内存操作次数。更加频繁的设置观测点将增加观察到竞争情况的可能性
--
Documentation/translations/zh_CN/dev-tools/kcsan.rst-167-
Documentation/translations/zh_CN/dev-tools/kcsan.rst:168:* ``kcsan.udelay_task`` (``CONFIG_KCSAN_UDELAY_TASK``): 对于任务,观测点设置之
Documentation/translations/zh_CN/dev-tools/kcsan.rst-169- 后暂停执行的微秒延迟。值越大,检测到竞争情况的可能性越高。
Documentation/translations/zh_CN/dev-tools/kcsan.rst-170-
Documentation/translations/zh_CN/dev-tools/kcsan.rst:171:* ``kcsan.udelay_interrupt`` (``CONFIG_KCSAN_UDELAY_INTERRUPT``): 对于中断,
Documentation/translations/zh_CN/dev-tools/kcsan.rst-172- 观测点设置之后暂停执行的微秒延迟。中断对于延迟的要求更加严格,其延迟通常应该小
--
Documentation/translations/zh_CN/dev-tools/kcsan.rst-174-
Documentation/translations/zh_CN/dev-tools/kcsan.rst:175:它们可以通过 ``/sys/module/kcsan/parameters/`` 在运行时进行调整。
Documentation/translations/zh_CN/dev-tools/kcsan.rst-176-
--
Documentation/translations/zh_CN/dev-tools/kcsan.rst=193=KCSAN 可以识别 *被标记的原子操作* ( ``READ_ONCE``, ``WRITE_ONCE`` , ``atomic_*``
--
Documentation/translations/zh_CN/dev-tools/kcsan.rst-211- 为了不引入新的文档编译警告,这里不展示宏定义的具体内容,如果想查看具体
Documentation/translations/zh_CN/dev-tools/kcsan.rst:212: 宏定义可以结合原文(Documentation/dev-tools/kcsan.rst)阅读。
Documentation/translations/zh_CN/dev-tools/kcsan.rst-213-
--
Documentation/translations/zh_CN/dev-tools/testing-overview.rst=78=Documentation/dev-tools/kcov.rst 是能够构建在内核之中,用于在每个任务
--
Documentation/translations/zh_CN/dev-tools/testing-overview.rst-96- Documentation/dev-tools/ubsan.rst
Documentation/translations/zh_CN/dev-tools/testing-overview.rst:97:* KCSAN检测数据竞争。参阅 Documentation/dev-tools/kcsan.rst
Documentation/translations/zh_CN/dev-tools/testing-overview.rst-98-* KFENCE是一个低开销的内存问题检测器,比KASAN更快且能被用于批量构建。
--
Documentation/translations/zh_TW/dev-tools/index.rst=32=Todolist:
--
Documentation/translations/zh_TW/dev-tools/index.rst-37- - kmemleak
Documentation/translations/zh_TW/dev-tools/index.rst:38: - kcsan
Documentation/translations/zh_TW/dev-tools/index.rst-39- - kfence
--
Documentation/translations/zh_TW/dev-tools/testing-overview.rst=78=Documentation/dev-tools/kcov.rst 是能夠構建在內核之中,用於在每個任務
--
Documentation/translations/zh_TW/dev-tools/testing-overview.rst-96- Documentation/dev-tools/ubsan.rst
Documentation/translations/zh_TW/dev-tools/testing-overview.rst:97:* KCSAN檢測數據競爭。參閱 Documentation/dev-tools/kcsan.rst
Documentation/translations/zh_TW/dev-tools/testing-overview.rst-98-* KFENCE是一個低開銷的內存問題檢測器,比KASAN更快且能被用於批量構建。
--
MAINTAINERS=13975=S: Maintained
MAINTAINERS:13976:F: Documentation/dev-tools/kcsan.rst
MAINTAINERS:13977:F: include/linux/kcsan*.h
MAINTAINERS:13978:F: kernel/kcsan/
MAINTAINERS:13979:F: lib/Kconfig.kcsan
MAINTAINERS:13980:F: scripts/Makefile.kcsan
MAINTAINERS-13981-
--
Makefile=1201=include-$(CONFIG_KASAN) += scripts/Makefile.kasan
Makefile:1202:include-$(CONFIG_KCSAN) += scripts/Makefile.kcsan
Makefile-1203-include-$(CONFIG_KMSAN) += scripts/Makefile.kmsan
--
arch/arm/boot/dts/ti/omap/omap3-n900.dts=1124= modem: hsi-client {
--
arch/arm/boot/dts/ti/omap/omap3-n900.dts-1130- hsi-channel-ids = <0>, <1>, <2>, <3>;
arch/arm/boot/dts/ti/omap/omap3-n900.dts:1131: hsi-channel-names = "mcsaab-control",
arch/arm/boot/dts/ti/omap/omap3-n900.dts-1132- "speech-control",
arch/arm/boot/dts/ti/omap/omap3-n900.dts-1133- "speech-data",
arch/arm/boot/dts/ti/omap/omap3-n900.dts:1134: "mcsaab-data";
arch/arm/boot/dts/ti/omap/omap3-n900.dts-1135- hsi-speed-kbps = <55000>;
--
arch/arm/boot/dts/ti/omap/omap3-n950-n9.dtsi=453= modem: hsi-client {
--
arch/arm/boot/dts/ti/omap/omap3-n950-n9.dtsi-457- hsi-channel-ids = <0>, <1>, <2>, <3>;
arch/arm/boot/dts/ti/omap/omap3-n950-n9.dtsi:458: hsi-channel-names = "mcsaab-control",
arch/arm/boot/dts/ti/omap/omap3-n950-n9.dtsi-459- "speech-control",
arch/arm/boot/dts/ti/omap/omap3-n950-n9.dtsi-460- "speech-data",
arch/arm/boot/dts/ti/omap/omap3-n950-n9.dtsi:461: "mcsaab-data";
arch/arm/boot/dts/ti/omap/omap3-n950-n9.dtsi-462- hsi-speed-kbps = <96000>;
--
arch/arm/boot/dts/ti/omap/omap4-var-om44customboard.dtsi=77= OMAP4_IOPAD(0x138, PIN_INPUT | MUX_MODE0) /* mcspi1_cs0.mcspi1_cs0 */
--
arch/arm/boot/dts/ti/omap/omap4-var-om44customboard.dtsi-80-
arch/arm/boot/dts/ti/omap/omap4-var-om44customboard.dtsi:81: mcasp_pins: mcsasp-pins {
arch/arm/boot/dts/ti/omap/omap4-var-om44customboard.dtsi-82- pinctrl-single,pins = <
--
arch/arm/mach-pxa/smemc.c=18=static unsigned long sxcnfg, memclkcfg;
arch/arm/mach-pxa/smemc.c:19:static unsigned long csadrcfg[4];
arch/arm/mach-pxa/smemc.c-20-
arch/arm/mach-pxa/smemc.c=21=static int pxa3xx_smemc_suspend(void *data)
--
arch/arm/mach-pxa/smemc.c-26- memclkcfg = __raw_readl(MEMCLKCFG);
arch/arm/mach-pxa/smemc.c:27: csadrcfg[0] = __raw_readl(CSADRCFG0);
arch/arm/mach-pxa/smemc.c:28: csadrcfg[1] = __raw_readl(CSADRCFG1);
arch/arm/mach-pxa/smemc.c:29: csadrcfg[2] = __raw_readl(CSADRCFG2);
arch/arm/mach-pxa/smemc.c:30: csadrcfg[3] = __raw_readl(CSADRCFG3);
arch/arm/mach-pxa/smemc.c-31-
--
arch/arm/mach-pxa/smemc.c=35=static void pxa3xx_smemc_resume(void *data)
--
arch/arm/mach-pxa/smemc.c-40- __raw_writel(memclkcfg, MEMCLKCFG);
arch/arm/mach-pxa/smemc.c:41: __raw_writel(csadrcfg[0], CSADRCFG0);
arch/arm/mach-pxa/smemc.c:42: __raw_writel(csadrcfg[1], CSADRCFG1);
arch/arm/mach-pxa/smemc.c:43: __raw_writel(csadrcfg[2], CSADRCFG2);
arch/arm/mach-pxa/smemc.c:44: __raw_writel(csadrcfg[3], CSADRCFG3);
arch/arm/mach-pxa/smemc.c-45- /* CSMSADRCFG wakes up in its default state (0), so we need to set it */
--
arch/arm64/boot/dts/renesas/r8a779md-geist.dts=399= adv7482_txa: endpoint {
--
arch/arm64/boot/dts/renesas/r8a779md-geist.dts-407-
arch/arm64/boot/dts/renesas/r8a779md-geist.dts:408: csa_vdd: adc@7c {
arch/arm64/boot/dts/renesas/r8a779md-geist.dts-409- compatible = "maxim,max9611";
--
arch/arm64/boot/dts/renesas/r8a779md-geist.dts-414-
arch/arm64/boot/dts/renesas/r8a779md-geist.dts:415: csa_dvfs: adc@7f {
arch/arm64/boot/dts/renesas/r8a779md-geist.dts-416- compatible = "maxim,max9611";
--
arch/arm64/boot/dts/renesas/salvator-common.dtsi=585= adv7482_txb: endpoint {
--
arch/arm64/boot/dts/renesas/salvator-common.dtsi-593-
arch/arm64/boot/dts/renesas/salvator-common.dtsi:594: csa_vdd: adc@7c {
arch/arm64/boot/dts/renesas/salvator-common.dtsi-595- compatible = "maxim,max9611";
--
arch/arm64/boot/dts/renesas/salvator-common.dtsi-600-
arch/arm64/boot/dts/renesas/salvator-common.dtsi:601: csa_dvfs: adc@7f {
arch/arm64/boot/dts/renesas/salvator-common.dtsi-602- compatible = "maxim,max9611";
--
arch/powerpc/include/asm/interrupt.h=81=do { \
--
arch/powerpc/include/asm/interrupt.h-95- */
arch/powerpc/include/asm/interrupt.h:96:#define interrupt_handler __visible noinline notrace __no_kcsan __no_sanitize_address
arch/powerpc/include/asm/interrupt.h-97-
--
arch/powerpc/include/asm/interrupt.h-129-#define DEFINE_INTERRUPT_HANDLER_RAW(func) \
arch/powerpc/include/asm/interrupt.h:130:static __always_inline __no_sanitize_address __no_kcsan long \
arch/powerpc/include/asm/interrupt.h-131-____##func(struct pt_regs *regs); \
--
arch/powerpc/include/asm/interrupt.h=143=NOKPROBE_SYMBOL(func); \
arch/powerpc/include/asm/interrupt.h-144- \
arch/powerpc/include/asm/interrupt.h:145:static __always_inline __no_sanitize_address __no_kcsan long \
arch/powerpc/include/asm/interrupt.h-146-____##func(struct pt_regs *regs)
--
arch/powerpc/include/asm/interrupt.h=257=static __always_inline void ____##func(struct pt_regs *regs)
--
arch/powerpc/include/asm/interrupt.h-277-#define DEFINE_INTERRUPT_HANDLER_NMI(func) \
arch/powerpc/include/asm/interrupt.h:278:static __always_inline __no_sanitize_address __no_kcsan long \
arch/powerpc/include/asm/interrupt.h-279-____##func(struct pt_regs *regs); \
--
arch/powerpc/include/asm/interrupt.h=323=NOKPROBE_SYMBOL(func); \
arch/powerpc/include/asm/interrupt.h-324- \
arch/powerpc/include/asm/interrupt.h:325:static __always_inline __no_sanitize_address __no_kcsan long \
arch/powerpc/include/asm/interrupt.h-326-____##func(struct pt_regs *regs)
--
arch/powerpc/include/asm/simple_spinlock.h-17-#include <linux/irqflags.h>
arch/powerpc/include/asm/simple_spinlock.h:18:#include <linux/kcsan-checks.h>
arch/powerpc/include/asm/simple_spinlock.h-19-#include <asm/paravirt.h>
--
arch/powerpc/include/asm/simple_spinlock.h=128=static inline void arch_spin_unlock(arch_spinlock_t *lock)
arch/powerpc/include/asm/simple_spinlock.h-129-{
arch/powerpc/include/asm/simple_spinlock.h:130: kcsan_mb();
arch/powerpc/include/asm/simple_spinlock.h-131- __asm__ __volatile__("# arch_spin_unlock\n\t"
--
arch/powerpc/include/asm/spu.h=96=struct spu_runqueue;
arch/powerpc/include/asm/spu.h:97:struct spu_lscsa;
arch/powerpc/include/asm/spu.h-98-struct device_node;
--
arch/powerpc/include/asm/spu.h=191=void spu_irq_setaffinity(struct spu *spu, int cpu);
arch/powerpc/include/asm/spu.h-192-
arch/powerpc/include/asm/spu.h:193:void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa,
arch/powerpc/include/asm/spu.h-194- void *code, int code_size);
--
arch/powerpc/include/asm/spu_csa.h-2-/*
arch/powerpc/include/asm/spu_csa.h:3: * spu_csa.h: Definitions for SPU context save area (CSA).
arch/powerpc/include/asm/spu_csa.h-4- *
--
arch/powerpc/include/asm/spu_csa.h=50=struct spu_reg128 {
--
arch/powerpc/include/asm/spu_csa.h-54-/**
arch/powerpc/include/asm/spu_csa.h:55: * struct spu_lscsa - Local Store Context Save Area.
arch/powerpc/include/asm/spu_csa.h-56- * @gprs: Array of saved registers.
--
arch/powerpc/include/asm/spu_csa.h-70- */
arch/powerpc/include/asm/spu_csa.h:71:struct spu_lscsa {
arch/powerpc/include/asm/spu_csa.h-72- struct spu_reg128 gprs[128];
--
arch/powerpc/include/asm/spu_csa.h=186=struct spu_priv2_collapsed {
--
arch/powerpc/include/asm/spu_csa.h-209- * struct spu_state
arch/powerpc/include/asm/spu_csa.h:210: * @lscsa: Local Store Context Save Area.
arch/powerpc/include/asm/spu_csa.h-211- * @prob: Collapsed Problem State Area, w/o pads.
--
arch/powerpc/include/asm/spu_csa.h-223- *
arch/powerpc/include/asm/spu_csa.h:224: * The @lscsa region is by far the largest, and is
arch/powerpc/include/asm/spu_csa.h-225- * allocated separately so that it may either be
--
arch/powerpc/include/asm/spu_csa.h=229=struct spu_state {
arch/powerpc/include/asm/spu_csa.h:230: struct spu_lscsa *lscsa;
arch/powerpc/include/asm/spu_csa.h-231- struct spu_problem_collapsed prob;
--
arch/powerpc/kernel/irq_64.c=88=static inline bool irq_happened_test_and_clear(u8 irq)
--
arch/powerpc/kernel/irq_64.c-96-
arch/powerpc/kernel/irq_64.c:97:static __no_kcsan void __replay_soft_interrupts(void)
arch/powerpc/kernel/irq_64.c-98-{
--
arch/powerpc/kernel/irq_64.c-173-
arch/powerpc/kernel/irq_64.c:174:__no_kcsan void replay_soft_interrupts(void)
arch/powerpc/kernel/irq_64.c-175-{
--
arch/powerpc/kernel/irq_64.c-181-#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_KUAP)
arch/powerpc/kernel/irq_64.c:182:static inline __no_kcsan void replay_soft_interrupts_irqrestore(void)
arch/powerpc/kernel/irq_64.c-183-{
--
arch/powerpc/kernel/irq_64.c-205-
arch/powerpc/kernel/irq_64.c:206:notrace __no_kcsan void arch_local_irq_restore(unsigned long mask)
arch/powerpc/kernel/irq_64.c-207-{
--
arch/powerpc/kernel/time.c=415=void vtime_dyntick_stop(void)
--
arch/powerpc/kernel/time.c-421-
arch/powerpc/kernel/time.c:422:void __no_kcsan __delay(unsigned long loops)
arch/powerpc/kernel/time.c-423-{
--
arch/powerpc/kernel/time.c=441=EXPORT_SYMBOL(__delay);
arch/powerpc/kernel/time.c-442-
arch/powerpc/kernel/time.c:443:void __no_kcsan udelay(unsigned long usecs)
arch/powerpc/kernel/time.c-444-{
--
arch/powerpc/lib/qspinlock.c=162=static __always_inline u32 publish_tail_cpu(struct qspinlock *lock, u32 tail)
--
arch/powerpc/lib/qspinlock.c-165-
arch/powerpc/lib/qspinlock.c:166: kcsan_release();
arch/powerpc/lib/qspinlock.c-167-
--
arch/powerpc/platforms/cell/spu_base.c-25-#include <asm/spu_priv1.h>
arch/powerpc/platforms/cell/spu_base.c:26:#include <asm/spu_csa.h>
arch/powerpc/platforms/cell/spu_base.c-27-#include <asm/kexec.h>
--
arch/powerpc/platforms/cell/spu_base.c=227=static inline int __slb_present(struct copro_slb *slbs, int nr_slbs,
--
arch/powerpc/platforms/cell/spu_base.c-243- *
arch/powerpc/platforms/cell/spu_base.c:244: * Because the lscsa and code may cross segment boundaries, we check to see
arch/powerpc/platforms/cell/spu_base.c-245- * if mappings are required for the start and end of each range. We currently
--
arch/powerpc/platforms/cell/spu_base.c-248- */
arch/powerpc/platforms/cell/spu_base.c:249:void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa,
arch/powerpc/platforms/cell/spu_base.c-250- void *code, int code_size)
--
arch/powerpc/platforms/cell/spu_base.c-255- void *addrs[] = {
arch/powerpc/platforms/cell/spu_base.c:256: lscsa, (void *)lscsa + sizeof(*lscsa) - 1,
arch/powerpc/platforms/cell/spu_base.c-257- code, code + code_size - 1
--
arch/powerpc/platforms/cell/spufs/Makefile=5=spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o
arch/powerpc/platforms/cell/spufs/Makefile:6:spufs-y += switch.o fault.o lscsa_alloc.o
arch/powerpc/platforms/cell/spufs/Makefile-7-spufs-$(CONFIG_COREDUMP) += coredump.o
--
arch/powerpc/platforms/cell/spufs/backing_ops.c-22-#include <asm/spu.h>
arch/powerpc/platforms/cell/spufs/backing_ops.c:23:#include <asm/spu_csa.h>
arch/powerpc/platforms/cell/spufs/backing_ops.c-24-#include <asm/spu_info.h>
--
arch/powerpc/platforms/cell/spufs/backing_ops.c=34=static void gen_spu_event(struct spu_context *ctx, u32 event)
--
arch/powerpc/platforms/cell/spufs/backing_ops.c-39-
arch/powerpc/platforms/cell/spufs/backing_ops.c:40: ch0_cnt = ctx->csa.spu_chnlcnt_RW[0];
arch/powerpc/platforms/cell/spufs/backing_ops.c:41: ch0_data = ctx->csa.spu_chnldata_RW[0];
arch/powerpc/platforms/cell/spufs/backing_ops.c:42: ch1_data = ctx->csa.spu_chnldata_RW[1];
arch/powerpc/platforms/cell/spufs/backing_ops.c:43: ctx->csa.spu_chnldata_RW[0] |= event;
arch/powerpc/platforms/cell/spufs/backing_ops.c-44- if ((ch0_cnt == 0) && !(ch0_data & event) && (ch1_data & event)) {
arch/powerpc/platforms/cell/spufs/backing_ops.c:45: ctx->csa.spu_chnlcnt_RW[0] = 1;
]
|
| 66/2 |
2026/08/19 17:17 |
llm |
expert |
0m
Model:
Tokens:
input: 81038
output: 34
thoughts: 48
Thoughts: **Investigating the Use of "csa" in mac80211 Mesh**
Okay, so I've got a hunch. It looks like the abbreviation "csa" is used in the `net/mac80211/mesh.c` file. Interesting. Now that I have a potential location, it’s time to drill down and understand how it’s being used. I need to take a closer look at that file. Let's get right to it and search within `net/mac80211/mesh.c` for every instance of "csa". This should help me quickly identify the context and purpose of "csa" within the mesh networking implementation. Then, I can start to put together the bigger picture.
|
| 67/2 |
2026/08/19 17:18 |
tool |
grepper |
0m
Args: map[Expression:csa PathPrefix:net/mac80211/mesh.c]
Results: map[Output:net/mac80211/mesh.c=935=ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
--
net/mac80211/mesh.c-940- struct ieee80211_mgmt *mgmt;
net/mac80211/mesh.c:941: struct mesh_csa_settings *csa;
net/mac80211/mesh.c-942- const struct ieee80211_supported_band *sband;
--
net/mac80211/mesh.c-1012- rcu_read_lock();
net/mac80211/mesh.c:1013: csa = rcu_dereference(ifmsh->csa);
net/mac80211/mesh.c:1014: if (csa) {
net/mac80211/mesh.c-1015- enum nl80211_channel_type ct;
--
net/mac80211/mesh.c-1024- *pos++ = ieee80211_frequency_to_channel(
net/mac80211/mesh.c:1025: csa->settings.chandef.chan->center_freq);
net/mac80211/mesh.c:1026: bcn->cntdwn_current_counter = csa->settings.count;
net/mac80211/mesh.c-1027- bcn->cntdwn_counter_offsets[0] = hdr_len + 6;
net/mac80211/mesh.c:1028: *pos++ = csa->settings.count;
net/mac80211/mesh.c-1029- *pos++ = WLAN_EID_CHAN_SWITCH_PARAM;
net/mac80211/mesh.c-1030- *pos++ = 6;
net/mac80211/mesh.c:1031: if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) {
net/mac80211/mesh.c-1032- *pos++ = ifmsh->mshcfg.dot11MeshTTL;
--
net/mac80211/mesh.c-1036- }
net/mac80211/mesh.c:1037: *pos++ |= csa->settings.block_tx ?
net/mac80211/mesh.c-1038- WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
--
net/mac80211/mesh.c-1043-
net/mac80211/mesh.c:1044: switch (csa->settings.chandef.width) {
net/mac80211/mesh.c-1045- case NL80211_CHAN_WIDTH_40:
--
net/mac80211/mesh.c-1050- *pos++ = 1; /* len */
net/mac80211/mesh.c:1051: ct = cfg80211_get_chandef_type(&csa->settings.chandef);
net/mac80211/mesh.c-1052- if (ct == NL80211_CHAN_HT40PLUS)
--
net/mac80211/mesh.c-1067- /* put sub IE */
net/mac80211/mesh.c:1068: chandef = &csa->settings.chandef;
net/mac80211/mesh.c-1069- ieee80211_ie_build_wide_bw_cs(pos, chandef);
--
net/mac80211/mesh.c=1199=void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
--
net/mac80211/mesh.c-1241-
net/mac80211/mesh.c:1242:static void ieee80211_mesh_csa_mark_radar(struct ieee80211_sub_if_data *sdata)
net/mac80211/mesh.c-1243-{
--
net/mac80211/mesh.c=1259=ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
--
net/mac80211/mesh.c-1261-{
net/mac80211/mesh.c:1262: struct cfg80211_csa_settings params;
net/mac80211/mesh.c:1263: struct ieee80211_csa_ie csa_ie;
net/mac80211/mesh.c-1264- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
--
net/mac80211/mesh.c-1300- sdata->vif.addr, false,
net/mac80211/mesh.c:1301: &csa_ie);
net/mac80211/mesh.c-1302- if (err < 0)
--
net/mac80211/mesh.c-1309- */
net/mac80211/mesh.c:1310: if (csa_ie.reason_code == WLAN_REASON_MESH_CHAN_REGULATORY)
net/mac80211/mesh.c:1311: ieee80211_mesh_csa_mark_radar(sdata);
net/mac80211/mesh.c-1312-
net/mac80211/mesh.c:1313: params.chandef = csa_ie.chanreq.oper;
net/mac80211/mesh.c:1314: params.count = csa_ie.count;
net/mac80211/mesh.c-1315-
--
net/mac80211/mesh.c-1349- &sdata->vif.bss_conf.chanreq.oper)) {
net/mac80211/mesh.c:1350: mcsa_dbg(sdata,
net/mac80211/mesh.c:1351: "received csa with an identical chandef, ignoring\n");
net/mac80211/mesh.c-1352- return true;
--
net/mac80211/mesh.c-1354-
net/mac80211/mesh.c:1355: mcsa_dbg(sdata,
net/mac80211/mesh.c-1356- "received channel switch announcement to go to channel %d MHz\n",
--
net/mac80211/mesh.c-1358-
net/mac80211/mesh.c:1359: params.block_tx = csa_ie.mode & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT;
net/mac80211/mesh.c-1360- if (beacon) {
net/mac80211/mesh.c:1361: ifmsh->chsw_ttl = csa_ie.ttl - 1;
net/mac80211/mesh.c:1362: if (ifmsh->pre_value >= csa_ie.pre_value)
net/mac80211/mesh.c-1363- return false;
net/mac80211/mesh.c:1364: ifmsh->pre_value = csa_ie.pre_value;
net/mac80211/mesh.c-1365- }
--
net/mac80211/mesh.c-1369-
net/mac80211/mesh.c:1370: ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_REPEATER;
net/mac80211/mesh.c-1371-
--
net/mac80211/mesh.c=1444=static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
--
net/mac80211/mesh.c-1496-
net/mac80211/mesh.c:1497: if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT &&
net/mac80211/mesh.c:1498: !sdata->vif.bss_conf.csa_active)
net/mac80211/mesh.c-1499- ieee80211_mesh_process_chnswitch(sdata, elems, true);
--
net/mac80211/mesh.c-1510-
net/mac80211/mesh.c:1511:int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata, u64 *changed)
net/mac80211/mesh.c-1512-{
net/mac80211/mesh.c-1513- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
net/mac80211/mesh.c:1514: struct mesh_csa_settings *tmp_csa_settings;
net/mac80211/mesh.c-1515- int ret = 0;
--
net/mac80211/mesh.c-1517- /* Reset the TTL value and Initiator flag */
net/mac80211/mesh.c:1518: ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
net/mac80211/mesh.c-1519- ifmsh->chsw_ttl = 0;
--
net/mac80211/mesh.c-1521- /* Remove the CSA and MCSP elements from the beacon */
net/mac80211/mesh.c:1522: tmp_csa_settings = sdata_dereference(ifmsh->csa, sdata);
net/mac80211/mesh.c:1523: RCU_INIT_POINTER(ifmsh->csa, NULL);
net/mac80211/mesh.c:1524: if (tmp_csa_settings)
net/mac80211/mesh.c:1525: kfree_rcu(tmp_csa_settings, rcu_head);
net/mac80211/mesh.c-1526- ret = ieee80211_mesh_rebuild_beacon(sdata);
--
net/mac80211/mesh.c-1531-
net/mac80211/mesh.c:1532: mcsa_dbg(sdata, "complete switching to center freq %d MHz",
net/mac80211/mesh.c-1533- sdata->vif.bss_conf.chanreq.oper.chan->center_freq);
--
net/mac80211/mesh.c-1536-
net/mac80211/mesh.c:1537:int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
net/mac80211/mesh.c:1538: struct cfg80211_csa_settings *csa_settings,
net/mac80211/mesh.c-1539- u64 *changed)
--
net/mac80211/mesh.c-1541- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
net/mac80211/mesh.c:1542: struct mesh_csa_settings *tmp_csa_settings;
net/mac80211/mesh.c-1543- int ret = 0;
--
net/mac80211/mesh.c-1546-
net/mac80211/mesh.c:1547: tmp_csa_settings = kmalloc_obj(*tmp_csa_settings, GFP_ATOMIC);
net/mac80211/mesh.c:1548: if (!tmp_csa_settings)
net/mac80211/mesh.c-1549- return -ENOMEM;
net/mac80211/mesh.c-1550-
net/mac80211/mesh.c:1551: memcpy(&tmp_csa_settings->settings, csa_settings,
net/mac80211/mesh.c:1552: sizeof(struct cfg80211_csa_settings));
net/mac80211/mesh.c-1553-
net/mac80211/mesh.c:1554: rcu_assign_pointer(ifmsh->csa, tmp_csa_settings);
net/mac80211/mesh.c-1555-
--
net/mac80211/mesh.c-1557- if (ret) {
net/mac80211/mesh.c:1558: tmp_csa_settings = rcu_dereference(ifmsh->csa);
net/mac80211/mesh.c:1559: RCU_INIT_POINTER(ifmsh->csa, NULL);
net/mac80211/mesh.c:1560: kfree_rcu(tmp_csa_settings, rcu_head);
net/mac80211/mesh.c-1561- return ret;
--
net/mac80211/mesh.c-1567-
net/mac80211/mesh.c:1568:static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
net/mac80211/mesh.c-1569- struct ieee80211_mgmt *mgmt, size_t len,
--
net/mac80211/mesh.c-1594-
net/mac80211/mesh.c:1595:static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
net/mac80211/mesh.c-1596- struct ieee80211_mgmt *mgmt, size_t len)
--
net/mac80211/mesh.c-1600- u16 pre_value;
net/mac80211/mesh.c:1601: bool fwd_csa = true;
net/mac80211/mesh.c-1602- size_t baselen;
--
net/mac80211/mesh.c-1625- if (!--ifmsh->chsw_ttl)
net/mac80211/mesh.c:1626: fwd_csa = false;
net/mac80211/mesh.c-1627-
--
net/mac80211/mesh.c-1633-
net/mac80211/mesh.c:1634: if (!sdata->vif.bss_conf.csa_active &&
net/mac80211/mesh.c-1635- !ieee80211_mesh_process_chnswitch(sdata, elems, false)) {
net/mac80211/mesh.c:1636: mcsa_dbg(sdata, "Failed to process CSA action frame");
net/mac80211/mesh.c-1637- goto free;
--
net/mac80211/mesh.c-1640- /* forward or re-broadcast the CSA frame */
net/mac80211/mesh.c:1641: if (fwd_csa) {
net/mac80211/mesh.c:1642: if (mesh_fwd_csa_frame(sdata, mgmt, len, elems) < 0)
net/mac80211/mesh.c:1643: mcsa_dbg(sdata, "Failed to forward the CSA frame");
net/mac80211/mesh.c-1644- }
--
net/mac80211/mesh.c=1649=static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
--
net/mac80211/mesh.c-1668- case WLAN_CATEGORY_SPECTRUM_MGMT:
net/mac80211/mesh.c:1669: mesh_rx_csa_frame(sdata, mgmt, len);
net/mac80211/mesh.c-1670- break;
--
net/mac80211/mesh.c=1757=void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
--
net/mac80211/mesh.c-1769- ifmsh->next_perr = jiffies;
net/mac80211/mesh.c:1770: ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
net/mac80211/mesh.c-1771- ifmsh->nonpeer_pm = NL80211_MESH_POWER_ACTIVE;
]
|
| 68/2 |
2026/08/19 17:18 |
llm |
expert |
0m
Model:
Tokens:
input: 86066
output: 29
thoughts: 917
Thoughts: **Analyzing a Potential Memory Leak in the Mesh Stack**
Okay, so I'm looking at these two functions, `ieee80211_mesh_teardown_sdata` and `ieee80211_stop_mesh`, both of which seem critical for cleaning up a mesh interface (`sdata`). I see that `ieee80211_mesh_teardown_sdata` does some basic cleanup and unregisters from path tables, while `ieee80211_stop_mesh` does a more extensive teardown, flushing STAs, freeing keys, stopping beacons, and timers. The core issue here is that *neither* of them explicitly frees `ifmsh->csa`.
My understanding is that `ifmsh->csa` holds Channel Switch Announcement (CSA) settings. The reproducer steps make it very clear why this is a problem. We create a mesh interface, join a network, trigger a channel switch, which will allocate `tmp_csa_settings` and assign it to `ifmsh->csa`. The bug is triggered when we tear down the interface, for instance when the program exits, and this pointer is never freed.
This memory leak is happening because the driver is failing to free `ifmsh->csa` on interface teardown, which occurs after a CSA is initiated but before it completes.
The question then becomes: is this actually exploitable? Well, it's a memory leak, and a fairly large one. 1024 bytes isn't huge in the grand scheme of things, but it's not insignificant, especially if we can trigger this repeatedly, or in a tight loop. I need to clarify the size of `struct mesh_csa_settings` and if there are any other pointers in that struct that could be vulnerable. It's a significant leak in that it can be reliably triggered in a specific scenario.
Wait, `struct mesh_csa_settings` contains a `struct cfg80211_csa_settings`, which is *quite* large. So, in effect, this memory leak will be for the size of `struct cfg80211_csa_settings`, which is bigger than the 1024 bytes I had initially hypothesized. That makes this vulnerability all the more concerning. We definitely need to understand all the implications of a CSA not being properly cleaned up on interface teardown, especially if that channel switch is still ongoing.
|
| 69/2 |
2026/08/19 17:18 |
tool |
codesearch-struct-layout |
0m
Args: map[Name:cfg80211_csa_settings]
Results: map[Fields:[map[Name:chandef OffsetBits:0 SizeBits:384] map[Name:beacon_csa OffsetBits:384 SizeBits:1664] map[Name:counter_offsets_beacon OffsetBits:2048 SizeBits:64] map[Name:counter_offsets_presp OffsetBits:2112 SizeBits:64] map[Name:n_counter_offsets_beacon OffsetBits:2176 SizeBits:32] map[Name:n_counter_offsets_presp OffsetBits:2208 SizeBits:32] map[Name:beacon_after OffsetBits:2240 SizeBits:1664] map[Name:unsol_bcast_probe_resp OffsetBits:3904 SizeBits:192] map[Name:radar_required OffsetBits:4096 SizeBits:8] map[Name:block_tx OffsetBits:4104 SizeBits:8] map[Name:count OffsetBits:4112 SizeBits:8] map[Name:link_id OffsetBits:4120 SizeBits:8]]]
|
| 70/2 |
2026/08/19 17:18 |
llm |
expert |
0m
Model:
Tokens:
input: 87834
output: 24
thoughts: 27
Thoughts: Here's my summary, as though I'm thinking through this:
**Analyzing the Data Structure's Memory Footprint**
Okay, so I'm looking at this data structure, and the first thing that jumps out is its size. 4128 bits… that's 516 bytes. That's good to know off the bat, as it gives me a clear sense of the memory overhead we're dealing with. Knowing the size immediately constrains potential design choices, especially if we're working in a resource-constrained environment or dealing with a high volume of these structures. Now let's break down what's contained within this struct `mesh_csa_settings`. I'll have to see what each member within it contributes to this total size.
|
| 71/2 |
2026/08/19 17:18 |
tool |
codesearch-struct-layout |
0m
Args: map[Name:mesh_csa_settings]
Results: map[Fields:[map[Name:callback_head OffsetBits:0 SizeBits:128] map[Name:settings OffsetBits:128 SizeBits:4160]]]
|
| 72/2 |
2026/08/19 17:18 |
llm |
expert |
0m
Model:
Tokens:
input: 88105
output: 28
thoughts: 198
Thoughts: **Analyzing a Potential Memory Leak Vulnerability**
Okay, so I'm looking at this chunk of memory, and it's a pretty substantial size – 536 bytes, or 4288 bits. That puts it squarely within the `kmalloc-1024` slab cache, which is important to know for allocation considerations. Now, the big red flag here is the potential for a memory leak. In my experience, these are often leveraged as Denial-of-Service attacks. An attacker could exploit this repeatedly, consuming all available system memory. Ultimately, this leads to an Out-of-Memory (OOM) condition, and we're looking at a system crash or critical process termination.
The million-dollar question now is whether an unprivileged user can trigger this. That's what I really need to know. The reproducer they are using involves network operations, specifically with `socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC)` and then sending a sequence of commands: `NL80211_CMD_SET_INTERFACE`, `NL80211_CMD_JOIN_MESH`, and `NL80211_CMD_CHANNEL_SWITCH`. I see the `NL80211_*` commands, and I'm immediately thinking, those commands tend to be related to wireless network configurations, which is interesting. But those `NL80211_*` commands typically require the `CAP_NET_ADMIN` capability, don't they? So, I need to verify, specifically, if `NL80211_CMD_SET_INTERFACE` alone requires `CAP_NET_ADMIN`. That’s my next step.
|
| 73/2 |
2026/08/19 17:18 |
tool |
codesearch-definition-source |
0m
Args: map[Name:nl80211_set_interface]
Results: map[SourceCode:5044: static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
5045: {
5046: struct cfg80211_registered_device *rdev = info->user_ptr[0];
5047: struct vif_params params;
5048: int err;
5049: enum nl80211_iftype otype, ntype;
5050: struct net_device *dev = info->user_ptr[1];
5051: struct wireless_dev *wdev = dev->ieee80211_ptr;
5052: u32 radio_mask = 0;
5053: bool change = false;
5054:
5055: memset(¶ms, 0, sizeof(params));
5056:
5057: otype = ntype = dev->ieee80211_ptr->iftype;
5058:
5059: if (info->attrs[NL80211_ATTR_IFTYPE]) {
5060: ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
5061: if (otype != ntype)
5062: change = true;
5063: }
5064:
5065: if (info->attrs[NL80211_ATTR_MESH_ID]) {
5066: if (ntype != NL80211_IFTYPE_MESH_POINT)
5067: return -EINVAL;
5068: if (otype != NL80211_IFTYPE_MESH_POINT)
5069: return -EINVAL;
5070: if (netif_running(dev))
5071: return -EBUSY;
5072:
5073: wdev->u.mesh.id_up_len =
5074: nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
5075: memcpy(wdev->u.mesh.id,
5076: nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
5077: wdev->u.mesh.id_up_len);
5078: }
5079:
5080: if (info->attrs[NL80211_ATTR_4ADDR]) {
5081: params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
5082: change = true;
5083: err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
5084: if (err)
5085: return err;
5086: } else {
5087: params.use_4addr = -1;
5088: }
5089:
5090: err = nl80211_parse_mon_options(rdev, ntype, info, ¶ms);
5091: if (err < 0)
5092: return err;
5093: if (err > 0)
5094: change = true;
5095:
5096: err = nl80211_parse_vif_radio_mask(info, &radio_mask);
5097: if (err < 0)
5098: return err;
5099: if (err && netif_running(dev))
5100: return -EBUSY;
5101:
5102: if (change)
5103: err = cfg80211_change_iface(rdev, dev, ntype, ¶ms);
5104: else
5105: err = 0;
5106:
5107: if (!err && params.use_4addr != -1)
5108: dev->ieee80211_ptr->use_4addr = params.use_4addr;
5109:
5110: if (radio_mask)
5111: wdev->radio_mask = radio_mask;
5112:
5113: if (change && !err)
5114: nl80211_notify_iface(rdev, wdev, NL80211_CMD_SET_INTERFACE);
5115:
5116: return err;
5117: }
SourceFile:net/wireless/nl80211.c]
|
| 74/2 |
2026/08/19 17:18 |
llm |
expert |
0m
Model:
Tokens:
input: 89966
output: 44
thoughts: 32
Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience:
**Diving into the `nl80211_ops` Policy for Interface Settings**
Okay, time to get granular. I need to understand the policy constraints around the `NL80211_CMD_SET_INTERFACE` command within the `nl80211_ops` structure. This is a critical area, as any misconfiguration here could have significant implications for interface behavior, security, or even overall system stability. I need to know precisely what checks are in place. Are we talking about restrictions on interface type changes? Are there access control mechanisms based on the user sending the command or the intended target interface? Are certain attributes mandatory or prohibited based on the interface state (e.g., up/down, associated/disconnected)? What about regulatory domain implications - are there checks to prevent setting values that violate the current regulatory domain? I'm particularly interested in how the policy handles potential conflicts. Does it prevent setting a TX power greater than the regulatory limit? Does it correctly manage the state and locking around interface modifications? Understanding this policy is key to evaluating the robustness of any wireless interface driver or management utility. Let's see what the code reveals.
|
| 75/2 |
2026/08/19 17:18 |
tool |
grepper |
0m
Args: map[Expression:NL80211_CMD_SET_INTERFACE PathPrefix:net/wireless/nl80211.c]
Results: map[Output:net/wireless/nl80211.c=4654=static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
--
net/wireless/nl80211.c-4665- cmd != NL80211_CMD_DEL_INTERFACE &&
net/wireless/nl80211.c:4666: cmd != NL80211_CMD_SET_INTERFACE);
net/wireless/nl80211.c-4667-
--
net/wireless/nl80211.c=5044=static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
--
net/wireless/nl80211.c-5113- if (change && !err)
net/wireless/nl80211.c:5114: nl80211_notify_iface(rdev, wdev, NL80211_CMD_SET_INTERFACE);
net/wireless/nl80211.c-5115-
--
net/wireless/nl80211.c=19547=static const struct genl_small_ops nl80211_small_ops[] = {
--
net/wireless/nl80211.c-19562- {
net/wireless/nl80211.c:19563: .cmd = NL80211_CMD_SET_INTERFACE,
net/wireless/nl80211.c-19564- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
]
|
| 76/2 |
2026/08/19 17:18 |
llm |
expert |
0m
Model:
Tokens:
input: 90759
output: 28
thoughts: 31
Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person:
**Diving into the `NL80211_CMD_SET_INTERFACE` Command**
Alright, so the task at hand revolves around the `NL80211_CMD_SET_INTERFACE` command. My immediate thought is to zero in on the relevant code, specifically the `nl80211_small_ops` structure, as that's where the implementation details for this command are likely housed, I need to understand exactly how this command is handled. It's the go-to place for small operation handling functions. This command is pretty important, so I'll need to check the function calls made by it to ensure that everything is working as expected.
|
| 77/2 |
2026/08/19 17:18 |
tool |
codesearch-definition-source |
0m
Args: map[Name:nl80211_small_ops]
Results: map[SourceCode:19547: static const struct genl_small_ops nl80211_small_ops[] = {
19548: {
19549: .cmd = NL80211_CMD_SET_WIPHY,
19550: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19551: .doit = nl80211_set_wiphy,
19552: .flags = GENL_UNS_ADMIN_PERM,
19553: },
19554: {
19555: .cmd = NL80211_CMD_GET_INTERFACE,
19556: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19557: .doit = nl80211_get_interface,
19558: .dumpit = nl80211_dump_interface,
19559: /* can be retrieved by unprivileged users */
19560: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV),
19561: },
19562: {
19563: .cmd = NL80211_CMD_SET_INTERFACE,
19564: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19565: .doit = nl80211_set_interface,
19566: .flags = GENL_UNS_ADMIN_PERM,
19567: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
19568: NL80211_FLAG_NEED_RTNL),
19569: },
19570: {
19571: .cmd = NL80211_CMD_NEW_INTERFACE,
19572: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19573: .doit = nl80211_new_interface,
19574: .flags = GENL_UNS_ADMIN_PERM,
19575: .internal_flags =
19576: IFLAGS(NL80211_FLAG_NEED_WIPHY |
19577: NL80211_FLAG_NEED_RTNL |
19578: /* we take the wiphy mutex later ourselves */
19579: NL80211_FLAG_NO_WIPHY_MTX),
19580: },
19581: {
19582: .cmd = NL80211_CMD_DEL_INTERFACE,
19583: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19584: .doit = nl80211_del_interface,
19585: .flags = GENL_UNS_ADMIN_PERM,
19586: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
19587: NL80211_FLAG_NEED_RTNL),
19588: },
19589: {
19590: .cmd = NL80211_CMD_GET_KEY,
19591: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19592: .doit = nl80211_get_key,
19593: .flags = GENL_UNS_ADMIN_PERM,
19594: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
19595: },
19596: {
19597: .cmd = NL80211_CMD_SET_KEY,
19598: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19599: .doit = nl80211_set_key,
19600: .flags = GENL_UNS_ADMIN_PERM,
19601: /* cannot use NL80211_FLAG_MLO_VALID_LINK_ID, depends on key */
19602: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
19603: NL80211_FLAG_CLEAR_SKB),
19604: },
19605: {
19606: .cmd = NL80211_CMD_NEW_KEY,
19607: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19608: .doit = nl80211_new_key,
19609: .flags = GENL_UNS_ADMIN_PERM,
19610: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
19611: NL80211_FLAG_CLEAR_SKB),
19612: },
19613: {
19614: .cmd = NL80211_CMD_DEL_KEY,
19615: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19616: .doit = nl80211_del_key,
19617: .flags = GENL_UNS_ADMIN_PERM,
19618: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
19619: },
19620: {
19621: .cmd = NL80211_CMD_SET_BEACON,
19622: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19623: .flags = GENL_UNS_ADMIN_PERM,
19624: .doit = nl80211_set_beacon,
19625: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
19626: NL80211_FLAG_MLO_VALID_LINK_ID),
19627: },
19628: {
19629: .cmd = NL80211_CMD_START_AP,
19630: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19631: .flags = GENL_UNS_ADMIN_PERM,
19632: .doit = nl80211_start_ap,
19633: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
19634: NL80211_FLAG_MLO_VALID_LINK_ID),
19635: },
19636: {
19637: .cmd = NL80211_CMD_STOP_AP,
19638: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19639: .flags = GENL_UNS_ADMIN_PERM,
19640: .doit = nl80211_stop_ap,
19641: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
19642: NL80211_FLAG_MLO_VALID_LINK_ID),
19643: },
19644: {
19645: .cmd = NL80211_CMD_GET_STATION,
19646: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19647: .doit = nl80211_get_station,
19648: .dumpit = nl80211_dump_station,
19649: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV),
19650: },
19651: {
19652: .cmd = NL80211_CMD_SET_STATION,
19653: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19654: .doit = nl80211_set_station,
19655: .flags = GENL_UNS_ADMIN_PERM,
19656: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
19657: },
19658: {
19659: .cmd = NL80211_CMD_NEW_STATION,
19660: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19661: .doit = nl80211_new_station,
19662: .flags = GENL_UNS_ADMIN_PERM,
19663: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
19664: },
19665: {
19666: .cmd = NL80211_CMD_DEL_STATION,
19667: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19668: .doit = nl80211_del_station,
19669: .flags = GENL_UNS_ADMIN_PERM,
19670: /* cannot use NL80211_FLAG_MLO_VALID_LINK_ID, depends on
19671: * whether MAC address is passed or not. If MAC address is
19672: * passed, then even during MLO, link ID is not required.
19673: */
19674: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
19675: },
19676: {
19677: .cmd = NL80211_CMD_GET_MPATH,
19678: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19679: .doit = nl80211_get_mpath,
19680: .dumpit = nl80211_dump_mpath,
19681: .flags = GENL_UNS_ADMIN_PERM,
19682: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19683: },
19684: {
19685: .cmd = NL80211_CMD_GET_MPP,
19686: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19687: .doit = nl80211_get_mpp,
19688: .dumpit = nl80211_dump_mpp,
19689: .flags = GENL_UNS_ADMIN_PERM,
19690: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19691: },
19692: {
19693: .cmd = NL80211_CMD_SET_MPATH,
19694: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19695: .doit = nl80211_set_mpath,
19696: .flags = GENL_UNS_ADMIN_PERM,
19697: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19698: },
19699: {
19700: .cmd = NL80211_CMD_NEW_MPATH,
19701: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19702: .doit = nl80211_new_mpath,
19703: .flags = GENL_UNS_ADMIN_PERM,
19704: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19705: },
19706: {
19707: .cmd = NL80211_CMD_DEL_MPATH,
19708: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19709: .doit = nl80211_del_mpath,
19710: .flags = GENL_UNS_ADMIN_PERM,
19711: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19712: },
19713: {
19714: .cmd = NL80211_CMD_SET_BSS,
19715: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19716: .doit = nl80211_set_bss,
19717: .flags = GENL_UNS_ADMIN_PERM,
19718: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
19719: NL80211_FLAG_MLO_VALID_LINK_ID),
19720: },
19721: {
19722: .cmd = NL80211_CMD_GET_REG,
19723: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19724: .doit = nl80211_get_reg_do,
19725: .dumpit = nl80211_get_reg_dump,
19726: /* can be retrieved by unprivileged users */
19727: },
19728: #ifdef CONFIG_CFG80211_CRDA_SUPPORT
19729: {
19730: .cmd = NL80211_CMD_SET_REG,
19731: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19732: .doit = nl80211_set_reg,
19733: .flags = GENL_ADMIN_PERM,
19734: },
19735: #endif
19736: {
19737: .cmd = NL80211_CMD_REQ_SET_REG,
19738: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19739: .doit = nl80211_req_set_reg,
19740: .flags = GENL_ADMIN_PERM,
19741: },
19742: {
19743: .cmd = NL80211_CMD_RELOAD_REGDB,
19744: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19745: .doit = nl80211_reload_regdb,
19746: .flags = GENL_ADMIN_PERM,
19747: },
19748: {
19749: .cmd = NL80211_CMD_GET_MESH_CONFIG,
19750: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19751: .doit = nl80211_get_mesh_config,
19752: /* can be retrieved by unprivileged users */
19753: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19754: },
19755: {
19756: .cmd = NL80211_CMD_SET_MESH_CONFIG,
19757: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19758: .doit = nl80211_update_mesh_config,
19759: .flags = GENL_UNS_ADMIN_PERM,
19760: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19761: },
19762: {
19763: .cmd = NL80211_CMD_TRIGGER_SCAN,
19764: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19765: .doit = nl80211_trigger_scan,
19766: .flags = GENL_UNS_ADMIN_PERM,
19767: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
19768: },
19769: {
19770: .cmd = NL80211_CMD_ABORT_SCAN,
19771: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19772: .doit = nl80211_abort_scan,
19773: .flags = GENL_UNS_ADMIN_PERM,
19774: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
19775: },
19776: {
19777: .cmd = NL80211_CMD_GET_SCAN,
19778: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19779: .dumpit = nl80211_dump_scan,
19780: },
19781: {
19782: .cmd = NL80211_CMD_START_SCHED_SCAN,
19783: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19784: .doit = nl80211_start_sched_scan,
19785: .flags = GENL_UNS_ADMIN_PERM,
19786: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19787: },
19788: {
19789: .cmd = NL80211_CMD_STOP_SCHED_SCAN,
19790: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19791: .doit = nl80211_stop_sched_scan,
19792: .flags = GENL_UNS_ADMIN_PERM,
19793: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19794: },
19795: {
19796: .cmd = NL80211_CMD_AUTHENTICATE,
19797: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19798: .doit = nl80211_authenticate,
19799: .flags = GENL_UNS_ADMIN_PERM,
19800: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
19801: NL80211_FLAG_CLEAR_SKB),
19802: },
19803: {
19804: .cmd = NL80211_CMD_ASSOCIATE,
19805: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19806: .doit = nl80211_associate,
19807: .flags = GENL_UNS_ADMIN_PERM,
19808: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
19809: NL80211_FLAG_CLEAR_SKB),
19810: },
19811: {
19812: .cmd = NL80211_CMD_DEAUTHENTICATE,
19813: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19814: .doit = nl80211_deauthenticate,
19815: .flags = GENL_UNS_ADMIN_PERM,
19816: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19817: },
19818: {
19819: .cmd = NL80211_CMD_DISASSOCIATE,
19820: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19821: .doit = nl80211_disassociate,
19822: .flags = GENL_UNS_ADMIN_PERM,
19823: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19824: },
19825: {
19826: .cmd = NL80211_CMD_JOIN_IBSS,
19827: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19828: .doit = nl80211_join_ibss,
19829: .flags = GENL_UNS_ADMIN_PERM,
19830: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19831: },
19832: {
19833: .cmd = NL80211_CMD_LEAVE_IBSS,
19834: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19835: .doit = nl80211_leave_ibss,
19836: .flags = GENL_UNS_ADMIN_PERM,
19837: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19838: },
19839: #ifdef CONFIG_NL80211_TESTMODE
19840: {
19841: .cmd = NL80211_CMD_TESTMODE,
19842: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19843: .doit = nl80211_testmode_do,
19844: .dumpit = nl80211_testmode_dump,
19845: .flags = GENL_UNS_ADMIN_PERM,
19846: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
19847: },
19848: #endif
19849: {
19850: .cmd = NL80211_CMD_CONNECT,
19851: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19852: .doit = nl80211_connect,
19853: .flags = GENL_UNS_ADMIN_PERM,
19854: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
19855: NL80211_FLAG_CLEAR_SKB),
19856: },
19857: {
19858: .cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS,
19859: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19860: .doit = nl80211_update_connect_params,
19861: .flags = GENL_ADMIN_PERM,
19862: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
19863: NL80211_FLAG_CLEAR_SKB),
19864: },
19865: {
19866: .cmd = NL80211_CMD_DISCONNECT,
19867: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19868: .doit = nl80211_disconnect,
19869: .flags = GENL_UNS_ADMIN_PERM,
19870: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19871: },
19872: {
19873: .cmd = NL80211_CMD_SET_WIPHY_NETNS,
19874: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19875: .doit = nl80211_wiphy_netns,
19876: .flags = GENL_UNS_ADMIN_PERM,
19877: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
19878: NL80211_FLAG_NEED_RTNL |
19879: NL80211_FLAG_NO_WIPHY_MTX),
19880: },
19881: {
19882: .cmd = NL80211_CMD_GET_SURVEY,
19883: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19884: .dumpit = nl80211_dump_survey,
19885: },
19886: {
19887: .cmd = NL80211_CMD_SET_PMKSA,
19888: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19889: .doit = nl80211_set_pmksa,
19890: .flags = GENL_UNS_ADMIN_PERM,
19891: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
19892: NL80211_FLAG_CLEAR_SKB),
19893: },
19894: {
19895: .cmd = NL80211_CMD_DEL_PMKSA,
19896: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19897: .doit = nl80211_del_pmksa,
19898: .flags = GENL_UNS_ADMIN_PERM,
19899: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19900: },
19901: {
19902: .cmd = NL80211_CMD_FLUSH_PMKSA,
19903: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19904: .doit = nl80211_flush_pmksa,
19905: .flags = GENL_UNS_ADMIN_PERM,
19906: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19907: },
19908: {
19909: .cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
19910: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19911: .doit = nl80211_remain_on_channel,
19912: .flags = GENL_UNS_ADMIN_PERM,
19913: /* FIXME: requiring a link ID here is probably not good */
19914: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
19915: NL80211_FLAG_MLO_VALID_LINK_ID),
19916: },
19917: {
19918: .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
19919: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19920: .doit = nl80211_cancel_remain_on_channel,
19921: .flags = GENL_UNS_ADMIN_PERM,
19922: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
19923: },
19924: {
19925: .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
19926: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19927: .doit = nl80211_set_tx_bitrate_mask,
19928: .flags = GENL_UNS_ADMIN_PERM,
19929: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
19930: NL80211_FLAG_MLO_VALID_LINK_ID),
19931: },
19932: {
19933: .cmd = NL80211_CMD_REGISTER_FRAME,
19934: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19935: .doit = nl80211_register_mgmt,
19936: .flags = GENL_UNS_ADMIN_PERM,
19937: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV),
19938: },
19939: {
19940: .cmd = NL80211_CMD_FRAME,
19941: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19942: .doit = nl80211_tx_mgmt,
19943: .flags = GENL_UNS_ADMIN_PERM,
19944: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
19945: },
19946: {
19947: .cmd = NL80211_CMD_FRAME_WAIT_CANCEL,
19948: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19949: .doit = nl80211_tx_mgmt_cancel_wait,
19950: .flags = GENL_UNS_ADMIN_PERM,
19951: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
19952: },
19953: {
19954: .cmd = NL80211_CMD_SET_POWER_SAVE,
19955: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19956: .doit = nl80211_set_power_save,
19957: .flags = GENL_UNS_ADMIN_PERM,
19958: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
19959: },
19960: {
19961: .cmd = NL80211_CMD_GET_POWER_SAVE,
19962: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19963: .doit = nl80211_get_power_save,
19964: /* can be retrieved by unprivileged users */
19965: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
19966: },
19967: {
19968: .cmd = NL80211_CMD_SET_CQM,
19969: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19970: .doit = nl80211_set_cqm,
19971: .flags = GENL_UNS_ADMIN_PERM,
19972: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
19973: },
19974: {
19975: .cmd = NL80211_CMD_SET_CHANNEL,
19976: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19977: .doit = nl80211_set_channel,
19978: .flags = GENL_UNS_ADMIN_PERM,
19979: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
19980: NL80211_FLAG_MLO_VALID_LINK_ID),
19981: },
19982: {
19983: .cmd = NL80211_CMD_JOIN_MESH,
19984: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19985: .doit = nl80211_join_mesh,
19986: .flags = GENL_UNS_ADMIN_PERM,
19987: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19988: },
19989: {
19990: .cmd = NL80211_CMD_LEAVE_MESH,
19991: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19992: .doit = nl80211_leave_mesh,
19993: .flags = GENL_UNS_ADMIN_PERM,
19994: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
19995: },
19996: {
19997: .cmd = NL80211_CMD_JOIN_OCB,
19998: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
19999: .doit = nl80211_join_ocb,
20000: .flags = GENL_UNS_ADMIN_PERM,
20001: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20002: },
20003: {
20004: .cmd = NL80211_CMD_LEAVE_OCB,
20005: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20006: .doit = nl80211_leave_ocb,
20007: .flags = GENL_UNS_ADMIN_PERM,
20008: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20009: },
20010: #ifdef CONFIG_PM
20011: {
20012: .cmd = NL80211_CMD_GET_WOWLAN,
20013: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20014: .doit = nl80211_get_wowlan,
20015: /* can be retrieved by unprivileged users */
20016: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
20017: },
20018: {
20019: .cmd = NL80211_CMD_SET_WOWLAN,
20020: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20021: .doit = nl80211_set_wowlan,
20022: .flags = GENL_UNS_ADMIN_PERM,
20023: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
20024: },
20025: #endif
20026: {
20027: .cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
20028: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20029: .doit = nl80211_set_rekey_data,
20030: .flags = GENL_UNS_ADMIN_PERM,
20031: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
20032: NL80211_FLAG_CLEAR_SKB),
20033: },
20034: {
20035: .cmd = NL80211_CMD_TDLS_MGMT,
20036: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20037: .doit = nl80211_tdls_mgmt,
20038: .flags = GENL_UNS_ADMIN_PERM,
20039: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
20040: NL80211_FLAG_MLO_VALID_LINK_ID),
20041: },
20042: {
20043: .cmd = NL80211_CMD_TDLS_OPER,
20044: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20045: .doit = nl80211_tdls_oper,
20046: .flags = GENL_UNS_ADMIN_PERM,
20047: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20048: },
20049: {
20050: .cmd = NL80211_CMD_UNEXPECTED_FRAME,
20051: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20052: .doit = nl80211_register_unexpected_frame,
20053: .flags = GENL_UNS_ADMIN_PERM,
20054: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
20055: },
20056: {
20057: .cmd = NL80211_CMD_PROBE_CLIENT,
20058: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20059: .doit = nl80211_probe_client,
20060: .flags = GENL_UNS_ADMIN_PERM,
20061: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20062: },
20063: {
20064: .cmd = NL80211_CMD_REGISTER_BEACONS,
20065: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20066: .doit = nl80211_register_beacons,
20067: .flags = GENL_UNS_ADMIN_PERM,
20068: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
20069: },
20070: {
20071: .cmd = NL80211_CMD_SET_NOACK_MAP,
20072: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20073: .doit = nl80211_set_noack_map,
20074: .flags = GENL_UNS_ADMIN_PERM,
20075: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
20076: },
20077: {
20078: .cmd = NL80211_CMD_START_P2P_DEVICE,
20079: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20080: .doit = nl80211_start_p2p_device,
20081: .flags = GENL_UNS_ADMIN_PERM,
20082: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
20083: NL80211_FLAG_NEED_RTNL),
20084: },
20085: {
20086: .cmd = NL80211_CMD_STOP_P2P_DEVICE,
20087: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20088: .doit = nl80211_stop_p2p_device,
20089: .flags = GENL_UNS_ADMIN_PERM,
20090: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
20091: NL80211_FLAG_NEED_RTNL),
20092: },
20093: {
20094: .cmd = NL80211_CMD_START_NAN,
20095: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20096: .doit = nl80211_start_nan,
20097: .flags = GENL_ADMIN_PERM,
20098: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
20099: NL80211_FLAG_NEED_RTNL),
20100: },
20101: {
20102: .cmd = NL80211_CMD_STOP_NAN,
20103: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20104: .doit = nl80211_stop_nan,
20105: .flags = GENL_ADMIN_PERM,
20106: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
20107: NL80211_FLAG_NO_WIPHY_MTX |
20108: NL80211_FLAG_NEED_RTNL),
20109: },
20110: {
20111: .cmd = NL80211_CMD_ADD_NAN_FUNCTION,
20112: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20113: .doit = nl80211_nan_add_func,
20114: .flags = GENL_ADMIN_PERM,
20115: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
20116: },
20117: {
20118: .cmd = NL80211_CMD_DEL_NAN_FUNCTION,
20119: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20120: .doit = nl80211_nan_del_func,
20121: .flags = GENL_ADMIN_PERM,
20122: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
20123: },
20124: {
20125: .cmd = NL80211_CMD_CHANGE_NAN_CONFIG,
20126: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20127: .doit = nl80211_nan_change_config,
20128: .flags = GENL_ADMIN_PERM,
20129: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
20130: },
20131: {
20132: .cmd = NL80211_CMD_START_PD,
20133: .doit = nl80211_start_pd,
20134: .flags = GENL_ADMIN_PERM,
20135: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
20136: NL80211_FLAG_NEED_RTNL),
20137: },
20138: {
20139: .cmd = NL80211_CMD_STOP_PD,
20140: .doit = nl80211_stop_pd,
20141: .flags = GENL_ADMIN_PERM,
20142: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
20143: NL80211_FLAG_NEED_RTNL),
20144: },
20145: {
20146: .cmd = NL80211_CMD_SET_MCAST_RATE,
20147: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20148: .doit = nl80211_set_mcast_rate,
20149: .flags = GENL_UNS_ADMIN_PERM,
20150: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
20151: },
20152: {
20153: .cmd = NL80211_CMD_SET_MAC_ACL,
20154: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20155: .doit = nl80211_set_mac_acl,
20156: .flags = GENL_UNS_ADMIN_PERM,
20157: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
20158: NL80211_FLAG_MLO_UNSUPPORTED),
20159: },
20160: {
20161: .cmd = NL80211_CMD_RADAR_DETECT,
20162: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20163: .doit = nl80211_start_radar_detection,
20164: .flags = GENL_UNS_ADMIN_PERM,
20165: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
20166: NL80211_FLAG_NO_WIPHY_MTX |
20167: NL80211_FLAG_MLO_VALID_LINK_ID),
20168: },
20169: {
20170: .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
20171: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20172: .doit = nl80211_get_protocol_features,
20173: },
20174: {
20175: .cmd = NL80211_CMD_UPDATE_FT_IES,
20176: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20177: .doit = nl80211_update_ft_ies,
20178: .flags = GENL_UNS_ADMIN_PERM,
20179: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20180: },
20181: {
20182: .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
20183: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20184: .doit = nl80211_crit_protocol_start,
20185: .flags = GENL_UNS_ADMIN_PERM,
20186: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
20187: },
20188: {
20189: .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
20190: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20191: .doit = nl80211_crit_protocol_stop,
20192: .flags = GENL_UNS_ADMIN_PERM,
20193: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
20194: },
20195: {
20196: .cmd = NL80211_CMD_GET_COALESCE,
20197: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20198: .doit = nl80211_get_coalesce,
20199: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
20200: },
20201: {
20202: .cmd = NL80211_CMD_SET_COALESCE,
20203: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20204: .doit = nl80211_set_coalesce,
20205: .flags = GENL_UNS_ADMIN_PERM,
20206: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
20207: },
20208: {
20209: .cmd = NL80211_CMD_CHANNEL_SWITCH,
20210: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20211: .doit = nl80211_channel_switch,
20212: .flags = GENL_UNS_ADMIN_PERM,
20213: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
20214: NL80211_FLAG_MLO_VALID_LINK_ID),
20215: },
20216: {
20217: .cmd = NL80211_CMD_VENDOR,
20218: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20219: .doit = nl80211_vendor_cmd,
20220: .dumpit = nl80211_vendor_cmd_dump,
20221: .flags = GENL_UNS_ADMIN_PERM,
20222: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
20223: NL80211_FLAG_CLEAR_SKB),
20224: },
20225: {
20226: .cmd = NL80211_CMD_SET_QOS_MAP,
20227: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20228: .doit = nl80211_set_qos_map,
20229: .flags = GENL_UNS_ADMIN_PERM,
20230: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20231: },
20232: {
20233: .cmd = NL80211_CMD_ADD_TX_TS,
20234: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20235: .doit = nl80211_add_tx_ts,
20236: .flags = GENL_UNS_ADMIN_PERM,
20237: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
20238: NL80211_FLAG_MLO_UNSUPPORTED),
20239: },
20240: {
20241: .cmd = NL80211_CMD_DEL_TX_TS,
20242: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20243: .doit = nl80211_del_tx_ts,
20244: .flags = GENL_UNS_ADMIN_PERM,
20245: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20246: },
20247: {
20248: .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
20249: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20250: .doit = nl80211_tdls_channel_switch,
20251: .flags = GENL_UNS_ADMIN_PERM,
20252: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20253: },
20254: {
20255: .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
20256: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20257: .doit = nl80211_tdls_cancel_channel_switch,
20258: .flags = GENL_UNS_ADMIN_PERM,
20259: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20260: },
20261: {
20262: .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST,
20263: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20264: .doit = nl80211_set_multicast_to_unicast,
20265: .flags = GENL_UNS_ADMIN_PERM,
20266: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
20267: },
20268: {
20269: .cmd = NL80211_CMD_SET_PMK,
20270: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20271: .doit = nl80211_set_pmk,
20272: .flags = GENL_UNS_ADMIN_PERM,
20273: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
20274: NL80211_FLAG_CLEAR_SKB),
20275: },
20276: {
20277: .cmd = NL80211_CMD_DEL_PMK,
20278: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20279: .doit = nl80211_del_pmk,
20280: .flags = GENL_UNS_ADMIN_PERM,
20281: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20282: },
20283: {
20284: .cmd = NL80211_CMD_EXTERNAL_AUTH,
20285: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20286: .doit = nl80211_external_auth,
20287: .flags = GENL_ADMIN_PERM,
20288: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20289: },
20290: {
20291: .cmd = NL80211_CMD_CONTROL_PORT_FRAME,
20292: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20293: .doit = nl80211_tx_control_port,
20294: .flags = GENL_UNS_ADMIN_PERM,
20295: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20296: },
20297: {
20298: .cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS,
20299: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20300: .doit = nl80211_get_ftm_responder_stats,
20301: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
20302: NL80211_FLAG_MLO_VALID_LINK_ID),
20303: },
20304: {
20305: .cmd = NL80211_CMD_PEER_MEASUREMENT_START,
20306: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20307: .doit = nl80211_pmsr_start,
20308: .flags = GENL_UNS_ADMIN_PERM,
20309: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
20310: },
20311: {
20312: .cmd = NL80211_CMD_NOTIFY_RADAR,
20313: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20314: .doit = nl80211_notify_radar_detection,
20315: .flags = GENL_UNS_ADMIN_PERM,
20316: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20317: },
20318: {
20319: .cmd = NL80211_CMD_UPDATE_OWE_INFO,
20320: .doit = nl80211_update_owe_info,
20321: .flags = GENL_ADMIN_PERM,
20322: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20323: },
20324: {
20325: .cmd = NL80211_CMD_PROBE_MESH_LINK,
20326: .doit = nl80211_probe_mesh_link,
20327: .flags = GENL_UNS_ADMIN_PERM,
20328: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20329: },
20330: {
20331: .cmd = NL80211_CMD_SET_TID_CONFIG,
20332: .doit = nl80211_set_tid_config,
20333: .flags = GENL_UNS_ADMIN_PERM,
20334: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
20335: NL80211_FLAG_MLO_VALID_LINK_ID),
20336: },
20337: {
20338: .cmd = NL80211_CMD_SET_SAR_SPECS,
20339: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20340: .doit = nl80211_set_sar_specs,
20341: .flags = GENL_UNS_ADMIN_PERM,
20342: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
20343: NL80211_FLAG_NEED_RTNL),
20344: },
20345: {
20346: .cmd = NL80211_CMD_COLOR_CHANGE_REQUEST,
20347: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20348: .doit = nl80211_color_change,
20349: .flags = GENL_UNS_ADMIN_PERM,
20350: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
20351: NL80211_FLAG_MLO_VALID_LINK_ID),
20352: },
20353: {
20354: .cmd = NL80211_CMD_SET_FILS_AAD,
20355: .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20356: .doit = nl80211_set_fils_aad,
20357: .flags = GENL_UNS_ADMIN_PERM,
20358: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20359: },
20360: {
20361: .cmd = NL80211_CMD_ADD_LINK,
20362: .doit = nl80211_add_link,
20363: .flags = GENL_UNS_ADMIN_PERM,
20364: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20365: },
20366: {
20367: .cmd = NL80211_CMD_REMOVE_LINK,
20368: .doit = nl80211_remove_link,
20369: .flags = GENL_UNS_ADMIN_PERM,
20370: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
20371: NL80211_FLAG_MLO_VALID_LINK_ID),
20372: },
20373: {
20374: .cmd = NL80211_CMD_ADD_LINK_STA,
20375: .doit = nl80211_add_link_station,
20376: .flags = GENL_UNS_ADMIN_PERM,
20377: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
20378: NL80211_FLAG_MLO_VALID_LINK_ID),
20379: },
20380: {
20381: .cmd = NL80211_CMD_MODIFY_LINK_STA,
20382: .doit = nl80211_modify_link_station,
20383: .flags = GENL_UNS_ADMIN_PERM,
20384: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
20385: NL80211_FLAG_MLO_VALID_LINK_ID),
20386: },
20387: {
20388: .cmd = NL80211_CMD_REMOVE_LINK_STA,
20389: .doit = nl80211_remove_link_station,
20390: .flags = GENL_UNS_ADMIN_PERM,
20391: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
20392: NL80211_FLAG_MLO_VALID_LINK_ID),
20393: },
20394: {
20395: .cmd = NL80211_CMD_SET_HW_TIMESTAMP,
20396: .doit = nl80211_set_hw_timestamp,
20397: .flags = GENL_UNS_ADMIN_PERM,
20398: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20399: },
20400: {
20401: .cmd = NL80211_CMD_SET_TID_TO_LINK_MAPPING,
20402: .doit = nl80211_set_ttlm,
20403: .flags = GENL_UNS_ADMIN_PERM,
20404: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20405: },
20406: {
20407: .cmd = NL80211_CMD_ASSOC_MLO_RECONF,
20408: .doit = nl80211_assoc_ml_reconf,
20409: .flags = GENL_UNS_ADMIN_PERM,
20410: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20411: },
20412: {
20413: .cmd = NL80211_CMD_EPCS_CFG,
20414: .doit = nl80211_epcs_cfg,
20415: .flags = GENL_UNS_ADMIN_PERM,
20416: .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
20417: },
20418: {
20419: .cmd = NL80211_CMD_NAN_SET_LOCAL_SCHED,
20420: .doit = nl80211_nan_set_local_sched,
20421: .flags = GENL_ADMIN_PERM,
20422: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
20423: },
20424: {
20425: .cmd = NL80211_CMD_NAN_SET_PEER_SCHED,
20426: .doit = nl80211_nan_set_peer_sched,
20427: .flags = GENL_ADMIN_PERM,
20428: .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
20429: },
20430: };
SourceFile:net/wireless/nl80211.c]
|
| 78/2 |
2026/08/19 17:18 |
llm |
expert |
0m
Model:
Tokens:
input: 110250
output: 28
thoughts: 85
Thoughts: **Decoding the Permission Flag**
Okay, so I'm looking at this `.flags` field and it's set to `GENL_UNS_ADMIN_PERM`. Right off the bat, I know that's a permission flag related to Generic Netlink, but I need to quickly recall what `GENL_UNS_ADMIN_PERM` *specifically* implies. My first guess, based on the name, is that it requires administrative privileges. Bingo! Looks like it boils down to needing `CAP_NET_ADMIN` within the user namespace.
Just to be absolutely certain, and since this is safety-critical code, I'm not going to rely on memory alone. Time for a quick check of the definitive definition to solidify this understanding. No need to second-guess myself, after all `GENL_UNS_ADMIN_PERM` is `GENL_UNS_ADMIN_PERM`. Best to verify and confirm, even if it seems straightforward.
|
| 79/2 |
2026/08/19 17:18 |
tool |
codesearch-definition-source |
0m
Error:
Args: map[Name:GENL_UNS_ADMIN_PERM]
Results: map[SourceCode: SourceFile:]
|
| 80/2 |
2026/08/19 17:18 |
llm |
expert |
0m
Model:
Tokens:
input: 110592
output: 24
thoughts: 17
Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience:
**Analyzing Potential Administrative Permission Vulnerabilities**
Okay, so I'm thinking, where are the places where this could be an issue? The first thing that pops into my head is to dive right into the codebase and search for that constant string, `GENL_UNS_ADMIN_PERM`. I need to figure out how this permission is being checked, used, and granted. Grepping for the string itself is the obvious starting point. I want to see every instance. This will give me a quick overview of the code that's referencing this permission. I'm already anticipating that the grep results will need significant analysis. I'll need to look at the context surrounding each use. I'm looking for where this permission is being checked, assigned, and if there are any obvious flaws in those processes. I'm also considering potential bypasses, privilege escalation scenarios, or ways it might be improperly used in different contexts. Time to get to work. Let's see what the initial results look like.
|
| 81/2 |
2026/08/19 17:18 |
tool |
grepper |
0m
Args: map[Expression:GENL_UNS_ADMIN_PERM]
Results: map[Output:
Full output is too long, showing 500 out of 829 lines.
Use more precise expression if possible.
drivers/net/ieee802154/mac802154_hwsim.c=751=static const struct genl_small_ops hwsim_nl_ops[] = {
--
drivers/net/ieee802154/mac802154_hwsim.c-755- .doit = hwsim_new_radio_nl,
drivers/net/ieee802154/mac802154_hwsim.c:756: .flags = GENL_UNS_ADMIN_PERM,
drivers/net/ieee802154/mac802154_hwsim.c-757- },
--
drivers/net/ieee802154/mac802154_hwsim.c-761- .doit = hwsim_del_radio_nl,
drivers/net/ieee802154/mac802154_hwsim.c:762: .flags = GENL_UNS_ADMIN_PERM,
drivers/net/ieee802154/mac802154_hwsim.c-763- },
--
drivers/net/ieee802154/mac802154_hwsim.c-773- .doit = hwsim_new_edge_nl,
drivers/net/ieee802154/mac802154_hwsim.c:774: .flags = GENL_UNS_ADMIN_PERM,
drivers/net/ieee802154/mac802154_hwsim.c-775- },
--
drivers/net/ieee802154/mac802154_hwsim.c-779- .doit = hwsim_del_edge_nl,
drivers/net/ieee802154/mac802154_hwsim.c:780: .flags = GENL_UNS_ADMIN_PERM,
drivers/net/ieee802154/mac802154_hwsim.c-781- },
--
drivers/net/ieee802154/mac802154_hwsim.c-785- .doit = hwsim_set_edge_lqi,
drivers/net/ieee802154/mac802154_hwsim.c:786: .flags = GENL_UNS_ADMIN_PERM,
drivers/net/ieee802154/mac802154_hwsim.c-787- },
--
drivers/net/wireguard/generated/netlink.c=56=const struct genl_split_ops wireguard_nl_ops[2] = {
--
drivers/net/wireguard/generated/netlink.c-63- .maxattr = WGDEVICE_A_IFNAME,
drivers/net/wireguard/generated/netlink.c:64: .flags = GENL_UNS_ADMIN_PERM | GENL_CMD_CAP_DUMP,
drivers/net/wireguard/generated/netlink.c-65- },
--
drivers/net/wireguard/generated/netlink.c-70- .maxattr = WGDEVICE_A_PEERS,
drivers/net/wireguard/generated/netlink.c:71: .flags = GENL_UNS_ADMIN_PERM | GENL_CMD_CAP_DO,
drivers/net/wireguard/generated/netlink.c-72- },
--
drivers/net/wireless/virtual/mac80211_hwsim_main.c=7052=static const struct genl_small_ops hwsim_ops[] = {
--
drivers/net/wireless/virtual/mac80211_hwsim_main.c-7056- .doit = hwsim_register_received_nl,
drivers/net/wireless/virtual/mac80211_hwsim_main.c:7057: .flags = GENL_UNS_ADMIN_PERM,
drivers/net/wireless/virtual/mac80211_hwsim_main.c-7058- },
--
drivers/net/wireless/virtual/mac80211_hwsim_main.c-7072- .doit = hwsim_new_radio_nl,
drivers/net/wireless/virtual/mac80211_hwsim_main.c:7073: .flags = GENL_UNS_ADMIN_PERM,
drivers/net/wireless/virtual/mac80211_hwsim_main.c-7074- },
--
drivers/net/wireless/virtual/mac80211_hwsim_main.c-7078- .doit = hwsim_del_radio_nl,
drivers/net/wireless/virtual/mac80211_hwsim_main.c:7079: .flags = GENL_UNS_ADMIN_PERM,
drivers/net/wireless/virtual/mac80211_hwsim_main.c-7080- },
--
include/net/genetlink.h=173=enum genl_validate_flags {
--
include/net/genetlink.h-182- * @internal_flags: flags used by the family
include/net/genetlink.h:183: * @flags: GENL_* flags (%GENL_ADMIN_PERM or %GENL_UNS_ADMIN_PERM)
include/net/genetlink.h-184- * @validate: validation flags from enum genl_validate_flags
--
include/net/genetlink.h=191=struct genl_small_ops {
--
include/net/genetlink.h-203- * @internal_flags: flags used by the family
include/net/genetlink.h:204: * @flags: GENL_* flags (%GENL_ADMIN_PERM or %GENL_UNS_ADMIN_PERM)
include/net/genetlink.h-205- * @maxattr: maximum number of attributes supported
--
include/net/genetlink.h=213=struct genl_ops {
--
include/net/genetlink.h-231- * @internal_flags: flags used by the family
include/net/genetlink.h:232: * @flags: GENL_* flags (%GENL_ADMIN_PERM or %GENL_UNS_ADMIN_PERM)
include/net/genetlink.h-233- * @validate: validation flags from enum genl_validate_flags
--
include/uapi/linux/genetlink.h=13=struct genlmsghdr {
--
include/uapi/linux/genetlink.h-24-#define GENL_CMD_CAP_HASPOL 0x08
include/uapi/linux/genetlink.h:25:#define GENL_UNS_ADMIN_PERM 0x10
include/uapi/linux/genetlink.h-26-
--
net/batman-adv/netlink.c=1408=static const struct genl_small_ops batadv_netlink_ops[] = {
--
net/batman-adv/netlink.c-1418- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1419: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1420- .doit = batadv_netlink_tp_meter_start,
--
net/batman-adv/netlink.c-1425- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1426: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1427- .doit = batadv_netlink_tp_meter_cancel,
--
net/batman-adv/netlink.c-1432- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1433: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1434- .dumpit = batadv_algo_dump,
--
net/batman-adv/netlink.c-1447- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1448: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1449- .dumpit = batadv_tt_local_dump,
--
net/batman-adv/netlink.c-1453- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1454: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1455- .dumpit = batadv_tt_global_dump,
--
net/batman-adv/netlink.c-1459- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1460: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1461- .dumpit = batadv_orig_dump,
--
net/batman-adv/netlink.c-1465- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1466: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1467- .dumpit = batadv_hardif_neigh_dump,
--
net/batman-adv/netlink.c-1471- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1472: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1473- .dumpit = batadv_gw_dump,
--
net/batman-adv/netlink.c-1477- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1478: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1479- .dumpit = batadv_bla_claim_dump,
--
net/batman-adv/netlink.c-1483- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1484: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1485- .dumpit = batadv_bla_backbone_dump,
--
net/batman-adv/netlink.c-1489- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1490: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1491- .dumpit = batadv_dat_cache_dump,
--
net/batman-adv/netlink.c-1495- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1496: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1497- .dumpit = batadv_mcast_flags_dump,
--
net/batman-adv/netlink.c-1501- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1502: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1503- .doit = batadv_netlink_set_mesh,
--
net/batman-adv/netlink.c-1508- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1509: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1510- .doit = batadv_netlink_set_hardif,
--
net/batman-adv/netlink.c-1524- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/batman-adv/netlink.c:1525: .flags = GENL_UNS_ADMIN_PERM,
net/batman-adv/netlink.c-1526- .doit = batadv_netlink_set_vlan,
--
net/core/netdev-genl-gen.c=138=static const struct genl_split_ops netdev_nl_ops[] = {
--
net/core/netdev-genl-gen.c-222- .maxattr = NETDEV_A_DMABUF_FD,
net/core/netdev-genl-gen.c:223: .flags = GENL_UNS_ADMIN_PERM | GENL_CMD_CAP_DO,
net/core/netdev-genl-gen.c-224- },
--
net/ethtool/netlink.c=1161=static const struct genl_ops ethtool_genl_ops[] = {
--
net/ethtool/netlink.c-1181- .cmd = ETHTOOL_MSG_LINKINFO_SET,
net/ethtool/netlink.c:1182: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1183- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1197- .cmd = ETHTOOL_MSG_LINKMODES_SET,
net/ethtool/netlink.c:1198: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1199- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1222- .cmd = ETHTOOL_MSG_DEBUG_SET,
net/ethtool/netlink.c:1223: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1224- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1229- .cmd = ETHTOOL_MSG_WOL_GET,
net/ethtool/netlink.c:1230: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1231- .doit = ethnl_default_doit,
--
net/ethtool/netlink.c-1239- .cmd = ETHTOOL_MSG_WOL_SET,
net/ethtool/netlink.c:1240: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1241- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1255- .cmd = ETHTOOL_MSG_FEATURES_SET,
net/ethtool/netlink.c:1256: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1257- .doit = ethnl_set_features,
--
net/ethtool/netlink.c-1271- .cmd = ETHTOOL_MSG_PRIVFLAGS_SET,
net/ethtool/netlink.c:1272: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1273- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1287- .cmd = ETHTOOL_MSG_RINGS_SET,
net/ethtool/netlink.c:1288: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1289- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1303- .cmd = ETHTOOL_MSG_CHANNELS_SET,
net/ethtool/netlink.c:1304: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1305- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1319- .cmd = ETHTOOL_MSG_COALESCE_SET,
net/ethtool/netlink.c:1320: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1321- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1335- .cmd = ETHTOOL_MSG_PAUSE_SET,
net/ethtool/netlink.c:1336: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1337- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1351- .cmd = ETHTOOL_MSG_EEE_SET,
net/ethtool/netlink.c:1352: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1353- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1367- .cmd = ETHTOOL_MSG_CABLE_TEST_ACT,
net/ethtool/netlink.c:1368: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1369- .doit = ethnl_act_cable_test,
--
net/ethtool/netlink.c-1374- .cmd = ETHTOOL_MSG_CABLE_TEST_TDR_ACT,
net/ethtool/netlink.c:1375: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1376- .doit = ethnl_act_cable_test_tdr,
--
net/ethtool/netlink.c-1398- .cmd = ETHTOOL_MSG_FEC_SET,
net/ethtool/netlink.c:1399: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1400- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1405- .cmd = ETHTOOL_MSG_MODULE_EEPROM_GET,
net/ethtool/netlink.c:1406: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1407- .doit = ethnl_default_doit,
--
net/ethtool/netlink.c-1442- .cmd = ETHTOOL_MSG_MODULE_SET,
net/ethtool/netlink.c:1443: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1444- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1458- .cmd = ETHTOOL_MSG_PSE_SET,
net/ethtool/netlink.c:1459: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1460- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1482- .cmd = ETHTOOL_MSG_PLCA_SET_CFG,
net/ethtool/netlink.c:1483: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1484- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1507- .cmd = ETHTOOL_MSG_MM_SET,
net/ethtool/netlink.c:1508: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1509- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1514- .cmd = ETHTOOL_MSG_MODULE_FW_FLASH_ACT,
net/ethtool/netlink.c:1515: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1516- .doit = ethnl_act_module_fw_flash,
--
net/ethtool/netlink.c-1539- .cmd = ETHTOOL_MSG_TSCONFIG_SET,
net/ethtool/netlink.c:1540: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1541- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1546- .cmd = ETHTOOL_MSG_RSS_SET,
net/ethtool/netlink.c:1547: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1548- .doit = ethnl_default_set_doit,
--
net/ethtool/netlink.c-1553- .cmd = ETHTOOL_MSG_RSS_CREATE_ACT,
net/ethtool/netlink.c:1554: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1555- .doit = ethnl_rss_create_doit,
--
net/ethtool/netlink.c-1560- .cmd = ETHTOOL_MSG_RSS_DELETE_ACT,
net/ethtool/netlink.c:1561: .flags = GENL_UNS_ADMIN_PERM,
net/ethtool/netlink.c-1562- .doit = ethnl_rss_delete_doit,
--
net/l2tp/l2tp_netlink.c=935=static const struct genl_small_ops l2tp_nl_ops[] = {
--
net/l2tp/l2tp_netlink.c-945- .doit = l2tp_nl_cmd_tunnel_create,
net/l2tp/l2tp_netlink.c:946: .flags = GENL_UNS_ADMIN_PERM,
net/l2tp/l2tp_netlink.c-947- },
--
net/l2tp/l2tp_netlink.c-951- .doit = l2tp_nl_cmd_tunnel_delete,
net/l2tp/l2tp_netlink.c:952: .flags = GENL_UNS_ADMIN_PERM,
net/l2tp/l2tp_netlink.c-953- },
--
net/l2tp/l2tp_netlink.c-957- .doit = l2tp_nl_cmd_tunnel_modify,
net/l2tp/l2tp_netlink.c:958: .flags = GENL_UNS_ADMIN_PERM,
net/l2tp/l2tp_netlink.c-959- },
--
net/l2tp/l2tp_netlink.c-964- .dumpit = l2tp_nl_cmd_tunnel_dump,
net/l2tp/l2tp_netlink.c:965: .flags = GENL_UNS_ADMIN_PERM,
net/l2tp/l2tp_netlink.c-966- },
--
net/l2tp/l2tp_netlink.c-970- .doit = l2tp_nl_cmd_session_create,
net/l2tp/l2tp_netlink.c:971: .flags = GENL_UNS_ADMIN_PERM,
net/l2tp/l2tp_netlink.c-972- },
--
net/l2tp/l2tp_netlink.c-976- .doit = l2tp_nl_cmd_session_delete,
net/l2tp/l2tp_netlink.c:977: .flags = GENL_UNS_ADMIN_PERM,
net/l2tp/l2tp_netlink.c-978- },
--
net/l2tp/l2tp_netlink.c-982- .doit = l2tp_nl_cmd_session_modify,
net/l2tp/l2tp_netlink.c:983: .flags = GENL_UNS_ADMIN_PERM,
net/l2tp/l2tp_netlink.c-984- },
--
net/l2tp/l2tp_netlink.c-989- .dumpit = l2tp_nl_cmd_session_dump,
net/l2tp/l2tp_netlink.c:990: .flags = GENL_UNS_ADMIN_PERM,
net/l2tp/l2tp_netlink.c-991- },
--
net/mptcp/mptcp_pm_gen.c=92=const struct genl_ops mptcp_pm_nl_ops[11] = {
--
net/mptcp/mptcp_pm_gen.c-98- .maxattr = MPTCP_PM_ENDPOINT_ADDR,
net/mptcp/mptcp_pm_gen.c:99: .flags = GENL_UNS_ADMIN_PERM,
net/mptcp/mptcp_pm_gen.c-100- },
--
net/mptcp/mptcp_pm_gen.c-106- .maxattr = MPTCP_PM_ENDPOINT_ADDR,
net/mptcp/mptcp_pm_gen.c:107: .flags = GENL_UNS_ADMIN_PERM,
net/mptcp/mptcp_pm_gen.c-108- },
--
net/mptcp/mptcp_pm_gen.c-122- .maxattr = MPTCP_PM_ENDPOINT_ADDR,
net/mptcp/mptcp_pm_gen.c:123: .flags = GENL_UNS_ADMIN_PERM,
net/mptcp/mptcp_pm_gen.c-124- },
--
net/mptcp/mptcp_pm_gen.c-130- .maxattr = MPTCP_PM_ATTR_SUBFLOWS,
net/mptcp/mptcp_pm_gen.c:131: .flags = GENL_UNS_ADMIN_PERM,
net/mptcp/mptcp_pm_gen.c-132- },
--
net/mptcp/mptcp_pm_gen.c-145- .maxattr = MPTCP_PM_ATTR_ADDR_REMOTE,
net/mptcp/mptcp_pm_gen.c:146: .flags = GENL_UNS_ADMIN_PERM,
net/mptcp/mptcp_pm_gen.c-147- },
--
net/mptcp/mptcp_pm_gen.c-153- .maxattr = MPTCP_PM_ATTR_TOKEN,
net/mptcp/mptcp_pm_gen.c:154: .flags = GENL_UNS_ADMIN_PERM,
net/mptcp/mptcp_pm_gen.c-155- },
--
net/mptcp/mptcp_pm_gen.c-161- .maxattr = MPTCP_PM_ATTR_LOC_ID,
net/mptcp/mptcp_pm_gen.c:162: .flags = GENL_UNS_ADMIN_PERM,
net/mptcp/mptcp_pm_gen.c-163- },
--
net/mptcp/mptcp_pm_gen.c-169- .maxattr = MPTCP_PM_ATTR_ADDR_REMOTE,
net/mptcp/mptcp_pm_gen.c:170: .flags = GENL_UNS_ADMIN_PERM,
net/mptcp/mptcp_pm_gen.c-171- },
--
net/mptcp/mptcp_pm_gen.c-177- .maxattr = MPTCP_PM_ATTR_ADDR_REMOTE,
net/mptcp/mptcp_pm_gen.c:178: .flags = GENL_UNS_ADMIN_PERM,
net/mptcp/mptcp_pm_gen.c-179- },
--
net/netlink/genetlink.c=1155=static int genl_family_rcv_msg(const struct genl_family *family,
--
net/netlink/genetlink.c-1185-
net/netlink/genetlink.c:1186: if ((op.flags & GENL_UNS_ADMIN_PERM) &&
net/netlink/genetlink.c-1187- !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
--
net/openvswitch/conntrack.c=1957=static const struct genl_small_ops ct_limit_genl_ops[] = {
--
net/openvswitch/conntrack.c-1959- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/openvswitch/conntrack.c:1960: .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN
net/openvswitch/conntrack.c-1961- * privilege.
--
net/openvswitch/conntrack.c-1966- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/openvswitch/conntrack.c:1967: .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN
net/openvswitch/conntrack.c-1968- * privilege.
--
net/openvswitch/datapath.c=733=static const struct genl_small_ops dp_packet_genl_ops[] = {
--
net/openvswitch/datapath.c-735- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/openvswitch/datapath.c:736: .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
net/openvswitch/datapath.c-737- .doit = ovs_packet_cmd_execute
--
net/openvswitch/datapath.c=1566=static const struct genl_small_ops dp_flow_genl_ops[] = {
--
net/openvswitch/datapath.c-1568- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/openvswitch/datapath.c:1569: .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
net/openvswitch/datapath.c-1570- .doit = ovs_flow_cmd_new
--
net/openvswitch/datapath.c-1573- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/openvswitch/datapath.c:1574: .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
net/openvswitch/datapath.c-1575- .doit = ovs_flow_cmd_del
--
net/openvswitch/datapath.c-1584- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/openvswitch/datapath.c:1585: .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
net/openvswitch/datapath.c-1586- .doit = ovs_flow_cmd_set,
--
net/openvswitch/datapath.c=2112=static const struct genl_small_ops dp_datapath_genl_ops[] = {
--
net/openvswitch/datapath.c-2114- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/openvswitch/datapath.c:2115: .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
net/openvswitch/datapath.c-2116- .doit = ovs_dp_cmd_new
--
net/openvswitch/datapath.c-2119- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/openvswitch/datapath.c:2120: .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
net/openvswitch/datapath.c-2121- .doit = ovs_dp_cmd_del
--
net/openvswitch/datapath.c-2130- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/openvswitch/datapath.c:2131: .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
net/openvswitch/datapath.c-2132- .doit = ovs_dp_cmd_set,
--
net/openvswitch/datapath.c=2640=static const struct genl_small_ops dp_vport_genl_ops[] = {
--
net/openvswitch/datapath.c-2642- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/openvswitch/datapath.c:2643: .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
net/openvswitch/datapath.c-2644- .doit = ovs_vport_cmd_new
--
net/openvswitch/datapath.c-2647- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/openvswitch/datapath.c:2648: .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
net/openvswitch/datapath.c-2649- .doit = ovs_vport_cmd_del
--
net/openvswitch/datapath.c-2658- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/openvswitch/datapath.c:2659: .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
net/openvswitch/datapath.c-2660- .doit = ovs_vport_cmd_set,
--
net/openvswitch/meter.c=687=static const struct genl_small_ops dp_meter_genl_ops[] = {
--
net/openvswitch/meter.c-694- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/openvswitch/meter.c:695: .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN
net/openvswitch/meter.c-696- * privilege.
--
net/openvswitch/meter.c-706- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/openvswitch/meter.c:707: .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN
net/openvswitch/meter.c-708- * privilege.
--
net/tipc/netlink.c=155=static const struct genl_ops tipc_genl_v2_ops[] = {
--
net/tipc/netlink.c-158- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/tipc/netlink.c:159: .flags = GENL_UNS_ADMIN_PERM,
net/tipc/netlink.c-160- .doit = tipc_nl_bearer_disable,
--
net/tipc/netlink.c-164- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/tipc/netlink.c:165: .flags = GENL_UNS_ADMIN_PERM,
net/tipc/netlink.c-166- .doit = tipc_nl_bearer_enable,
--
net/tipc/netlink.c-176- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/tipc/netlink.c:177: .flags = GENL_UNS_ADMIN_PERM,
net/tipc/netlink.c-178- .doit = tipc_nl_bearer_add,
--
net/tipc/netlink.c-182- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/tipc/netlink.c:183: .flags = GENL_UNS_ADMIN_PERM,
net/tipc/netlink.c-184- .doit = tipc_nl_bearer_set,
--
net/tipc/netlink.c-207- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/tipc/netlink.c:208: .flags = GENL_UNS_ADMIN_PERM,
net/tipc/netlink.c-209- .doit = tipc_nl_node_set_link,
--
net/tipc/netlink.c-213- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/tipc/netlink.c:214: .flags = GENL_UNS_ADMIN_PERM,
net/tipc/netlink.c-215- .doit = tipc_nl_node_reset_link_stats,
--
net/tipc/netlink.c-225- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/tipc/netlink.c:226: .flags = GENL_UNS_ADMIN_PERM,
net/tipc/netlink.c-227- .doit = tipc_nl_media_set,
--
net/tipc/netlink.c-241- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/tipc/netlink.c:242: .flags = GENL_UNS_ADMIN_PERM,
net/tipc/netlink.c-243- .doit = tipc_nl_net_set,
--
net/tipc/netlink.c-252- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/tipc/netlink.c:253: .flags = GENL_UNS_ADMIN_PERM,
net/tipc/netlink.c-254- .doit = tipc_nl_node_set_monitor,
--
net/tipc/netlink.c-270- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/tipc/netlink.c:271: .flags = GENL_UNS_ADMIN_PERM,
net/tipc/netlink.c-272- .doit = tipc_nl_peer_rm,
--
net/tipc/netlink.c-285- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/tipc/netlink.c:286: .flags = GENL_UNS_ADMIN_PERM,
net/tipc/netlink.c-287- .doit = tipc_nl_node_set_key,
--
net/tipc/netlink.c-291- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/tipc/netlink.c:292: .flags = GENL_UNS_ADMIN_PERM,
net/tipc/netlink.c-293- .doit = tipc_nl_node_flush_key,
--
net/wireless/nl80211.c=14183=static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
--
net/wireless/nl80211.c-14205- * The caller already has CAP_NET_ADMIN over the source netns
net/wireless/nl80211.c:14206: * (enforced by GENL_UNS_ADMIN_PERM on the genl op). Mirror the
net/wireless/nl80211.c-14207- * convention used by net/core/rtnetlink.c::rtnl_get_net_ns_capable()
--
net/wireless/nl80211.c=19547=static const struct genl_small_ops nl80211_small_ops[] = {
--
net/wireless/nl80211.c-19551- .doit = nl80211_set_wiphy,
net/wireless/nl80211.c:19552: .flags = GENL_UNS_ADMIN_PERM,
net/wireless/nl80211.c-19553- },
--
net/wireless/nl80211.c-19565- .doit = nl80211_set_interface,
net/wireless/nl80211.c:19566: .flags = GENL_UNS_ADMIN_PERM,
net/wireless/nl80211.c-19567- .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
--
net/wireless/nl80211.c-19573- .doit = nl80211_new_interface,
net/wireless/nl80211.c:19574: .flags = GENL_UNS_ADMIN_PERM,
net/wireless/nl80211.c-19575- .internal_flags =
--
net/wireless/nl80211.c-19584- .doit = nl80211_del_interface,
net/wireless/nl80211.c:19585: .flags = GENL_UNS_ADMIN_PERM,
net/wireless/nl80211.c-19586- .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
--
net/wireless/nl80211.c-19592- .doit = nl80211_get_key,
net/wireless/nl80211.c:19593: .flags = GENL_UNS_ADMIN_PERM,
net/wireless/nl80211.c-19594- .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
--
net/wireless/nl80211.c-19599- .doit = nl80211_set_key,
net/wireless/nl80211.c:19600: .flags = GENL_UNS_ADMIN_PERM,
net/wireless/nl80211.c-19601- /* cannot use NL80211_FLAG_MLO_VALID_LINK_ID, depends on key */
--
net/wireless/nl80211.c-19608- .doit = nl80211_new_key,
net/wireless/nl80211.c:19609: .flags = GENL_UNS_ADMIN_PERM,
net/wireless/nl80211.c-19610- .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
--
net/wireless/nl80211.c-19616- .doit = nl80211_del_key,
net/wireless/nl80211.c:19617: .flags = GENL_UNS_ADMIN_PERM,
net/wireless/nl80211.c-19618- .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
--
net/wireless/nl80211.c-19622- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/wireless/nl80211.c:19623: .flags = GENL_UNS_ADMIN_PERM,
net/wireless/nl80211.c-19624- .doit = nl80211_set_beacon,
--
net/wireless/nl80211.c-19630- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/wireless/nl80211.c:19631: .flags = GENL_UNS_ADMIN_PERM,
net/wireless/nl80211.c-19632- .doit = nl80211_start_ap,
--
net/wireless/nl80211.c-19638- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
net/wireless/nl80211.c:19639: .flags = GENL_UNS_ADMIN_PERM,
net/wireless/nl80211.c-19640- .doit = nl80211_stop_ap,
--
net/wireless/nl80211.c-19654- .doit = nl80211_set_station,
net/wireless/nl80211.c:19655: .flags = GENL_UNS_ADMIN_PERM,
net/wireless/nl80211.c-19656- .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
--
net/wireless/nl80211.c-19661- .doit = nl80211_new_station,
net/wireless/nl80211.c:19662: .flags = GENL_UNS_ADMIN_PERM,
net/wireless/nl80211.c-19663- .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
--
net/wireless/nl80211.c-19668- .doit = nl80211_del_station,
net/wireless/nl80211.c:19669: .flags = GENL_UNS_ADMIN_PERM,
net/wireless/nl80211.c-19670- /* cannot use NL80211_FLAG_MLO_VALID_LINK_ID, depends on
--
]
|
| 82/2 |
2026/08/19 17:18 |
llm |
expert |
0m
Model:
Tokens:
input: 124001
output: 30
thoughts: 412
Thoughts: **Analyzing the Privilege Requirements for `ieee80211_mesh_csa_beacon`**
Okay, let me break this down. `GENL_UNS_ADMIN_PERM`... that's the key. That means the code path I'm looking at, specifically within `genl_family_rcv_msg`, demands `CAP_NET_ADMIN` *within the user namespace*. The code snippet confirms it: the check `!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)` is explicitly verifying that the calling process possesses that capability within its user namespace context.
Given the prompt, let's assume user namespaces are off-limits, which means I can't even *create* a new one to try and elevate privileges. Therefore, this particular path, triggered through `GENL_UNS_ADMIN_PERM`, is *not* accessible to an unprivileged process. It requires user namespace access to function.
So, unprivileged processes are out. But, if user namespaces *were* enabled, it *would* be accessible, because `GENL_UNS_ADMIN_PERM` only requires `CAP_NET_ADMIN` in the user namespace, not the root namespace.
Now, let's think about how else I might trigger `ieee80211_mesh_csa_beacon`. I need to trace the call chain. I see it's called from `ieee80211_set_csa_beacon`, which in turn is called from `__ieee80211_channel_switch`.
Alright, `__ieee80211_channel_switch` itself is called from two places:
1. `nl80211_channel_switch`, which goes through `rdev_channel_switch` and `drv_channel_switch` before getting to `__ieee80211_channel_switch`. That's a direct path.
2. And, critically, `ieee80211_csa_switch_work`. Hang on... `ieee80211_csa_switch_work`? That's a workqueue function! I need to investigate that further. This could be a different vector, possibly operating outside the normal privilege checks, given it's asynchronous and running in a kernel workqueue. That's definitely worth pursuing.
|
| 83/2 |
2026/08/19 17:19 |
tool |
codesearch-find-references |
0m
Args: map[Name:__ieee80211_channel_switch]
Results: map[References:[map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:ieee80211_channel_switch SourceFile:net/mac80211/cfg.c SourceLine:4831]] TruncatedOutput:false]
|
| 84/2 |
2026/08/19 17:19 |
llm |
expert |
0m
Model:
Tokens:
input: 125051
output: 29
thoughts: 52
Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue:
**Investigating the Channel Switch Function**
Alright, let's see... so `__ieee80211_channel_switch` is the internal workhorse, the low-level function doing the actual heavy lifting for channel changes in the 802.11 code. Good, that helps me understand its scope. The code makes it clear that its only called directly from the function `ieee80211_channel_switch`.
Now, if I want to trace the initiation of a channel switch, or understand the overall channel change process, I need to know *where* `ieee80211_channel_switch` itself is invoked. Is it triggered by a higher-level management frame, a regulatory event, an external configuration change, or something else entirely? Knowing the call sites of that function will be key to understanding the full channel-switching sequence and the conditions that trigger it. Time to go hunting for its callers.
|
| 85/2 |
2026/08/19 17:19 |
tool |
codesearch-find-references |
0m
Args: map[Name:ieee80211_channel_switch]
Results: map[References:[map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:__bpf_trace_chanswitch_evt SourceFile:net/mac80211/trace.h SourceLine:1279] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:__do_trace_drv_channel_switch SourceFile:net/mac80211/trace.h SourceLine:1316] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:__do_trace_drv_channel_switch_rx_beacon SourceFile:net/mac80211/trace.h SourceLine:2224] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:__do_trace_drv_pre_channel_switch SourceFile:net/mac80211/trace.h SourceLine:2205] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:__ieee80211_channel_switch SourceFile:net/mac80211/cfg.c SourceLine:4713] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:__probestub_drv_channel_switch SourceFile:net/mac80211/trace.h SourceLine:1316] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:__probestub_drv_channel_switch_rx_beacon SourceFile:net/mac80211/trace.h SourceLine:2224] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:__probestub_drv_pre_channel_switch SourceFile:net/mac80211/trace.h SourceLine:2205] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:__traceiter_drv_channel_switch SourceFile:net/mac80211/trace.h SourceLine:1316] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:__traceiter_drv_channel_switch SourceFile:net/mac80211/trace.h SourceLine:1316] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:__traceiter_drv_channel_switch_rx_beacon SourceFile:net/mac80211/trace.h SourceLine:2224] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:__traceiter_drv_channel_switch_rx_beacon SourceFile:net/mac80211/trace.h SourceLine:2224] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:__traceiter_drv_pre_channel_switch SourceFile:net/mac80211/trace.h SourceLine:2205] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:__traceiter_drv_pre_channel_switch SourceFile:net/mac80211/trace.h SourceLine:2205] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:check_trace_callback_type_drv_channel_switch SourceFile:net/mac80211/trace.h SourceLine:1316] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:check_trace_callback_type_drv_channel_switch_rx_beacon SourceFile:net/mac80211/trace.h SourceLine:2224] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:check_trace_callback_type_drv_pre_channel_switch SourceFile:net/mac80211/trace.h SourceLine:2205] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:do_perf_trace_chanswitch_evt SourceFile:net/mac80211/trace.h SourceLine:1279] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:do_trace_event_raw_event_chanswitch_evt SourceFile:net/mac80211/trace.h SourceLine:1279] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:drv_channel_switch SourceFile:net/mac80211/driver-ops.h SourceLine:761] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:drv_channel_switch_rx_beacon SourceFile:net/mac80211/driver-ops.h SourceLine:1243] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:drv_pre_channel_switch SourceFile:net/mac80211/driver-ops.h SourceLine:1173] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:ieee80211_sta_process_chanswitch SourceFile:net/mac80211/mlme.c SourceLine:3240] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:perf_trace_chanswitch_evt SourceFile:net/mac80211/trace.h SourceLine:1279] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:register_trace_drv_channel_switch SourceFile:net/mac80211/trace.h SourceLine:1316] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:register_trace_drv_channel_switch_rx_beacon SourceFile:net/mac80211/trace.h SourceLine:2224] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:register_trace_drv_pre_channel_switch SourceFile:net/mac80211/trace.h SourceLine:2205] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:register_trace_prio_drv_channel_switch SourceFile:net/mac80211/trace.h SourceLine:1316] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:register_trace_prio_drv_channel_switch_rx_beacon SourceFile:net/mac80211/trace.h SourceLine:2224] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:register_trace_prio_drv_pre_channel_switch SourceFile:net/mac80211/trace.h SourceLine:2205] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:trace_call__drv_channel_switch SourceFile:net/mac80211/trace.h SourceLine:1316] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:trace_call__drv_channel_switch_rx_beacon SourceFile:net/mac80211/trace.h SourceLine:2224] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:trace_call__drv_pre_channel_switch SourceFile:net/mac80211/trace.h SourceLine:2205] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:trace_drv_channel_switch SourceFile:net/mac80211/trace.h SourceLine:1316] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:trace_drv_channel_switch_rx_beacon SourceFile:net/mac80211/trace.h SourceLine:2224] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:trace_drv_pre_channel_switch SourceFile:net/mac80211/trace.h SourceLine:2205] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:trace_event_get_offsets_chanswitch_evt SourceFile:net/mac80211/trace.h SourceLine:1279] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:trace_event_raw_event_chanswitch_evt SourceFile:net/mac80211/trace.h SourceLine:1279] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:unregister_trace_drv_channel_switch SourceFile:net/mac80211/trace.h SourceLine:1316] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:unregister_trace_drv_channel_switch_rx_beacon SourceFile:net/mac80211/trace.h SourceLine:2224] map[ReferenceKind:uses ReferencingEntityKind:function ReferencingEntityName:unregister_trace_drv_pre_channel_switch SourceFile:net/mac80211/trace.h SourceLine:2205] map[ReferenceKind:uses ReferencingEntityKind:struct ReferencingEntityName:ieee80211_ops SourceFile:include/net/mac80211.h SourceLine:4926] map[ReferenceKind:uses ReferencingEntityKind:struct ReferencingEntityName:ieee80211_ops SourceFile:include/net/mac80211.h SourceLine:5013] map[ReferenceKind:uses ReferencingEntityKind:struct ReferencingEntityName:ieee80211_ops SourceFile:include/net/mac80211.h SourceLine:5023] map[ReferenceKind:uses ReferencingEntityKind:typedef ReferencingEntityName:btf_trace_drv_channel_switch SourceFile:net/mac80211/trace.h SourceLine:1316] map[ReferenceKind:uses ReferencingEntityKind:typedef ReferencingEntityName:btf_trace_drv_channel_switch_rx_beacon SourceFile:net/mac80211/trace.h SourceLine:2224] map[ReferenceKind:uses ReferencingEntityKind:typedef ReferencingEntityName:btf_trace_drv_pre_channel_switch SourceFile:net/mac80211/trace.h SourceLine:2205]] TruncatedOutput:false]
|
| 86/2 |
2026/08/19 17:19 |
llm |
expert |
0m
Model:
Tokens:
input: 128265
output: 33
thoughts: 119
Thoughts: **Tracing the Channel Switch Call Chain**
Okay, so I'm digging into how channel switching is handled in this wireless stack. My initial thought is that `ieee80211_channel_switch` is the core function, but I need to understand the call flow. It looks like it's being called from `rdev_channel_switch`, which in turn gets called from `nl80211_channel_switch`. That's one clear path.
But I have a nagging feeling there might be another. I need to make sure I'm not missing anything. Ah, here it is: `ieee80211_sta_process_chanswitch` in `net/mac80211/mlme.c` also calls `ieee80211_channel_switch`. Excellent. I need to take a closer look at `ieee80211_sta_process_chanswitch` now to see how this second path works. This is going to be interesting.
|
| 87/2 |
2026/08/19 17:19 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_sta_process_chanswitch]
Results: map[SourceCode:3227: static void
3228: ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
3229: u64 timestamp, u32 device_timestamp,
3230: struct ieee802_11_elems *full_elems,
3231: struct ieee802_11_elems *csa_elems,
3232: enum ieee80211_csa_source source)
3233: {
3234: struct ieee80211_sub_if_data *sdata = link->sdata;
3235: struct ieee80211_local *local = sdata->local;
3236: struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3237: struct ieee80211_chanctx *chanctx = NULL;
3238: struct ieee80211_chanctx_conf *conf;
3239: struct ieee80211_csa_ie csa_ie = {};
3240: struct ieee80211_channel_switch ch_switch = {
3241: .link_id = link->link_id,
3242: .timestamp = timestamp,
3243: .device_timestamp = device_timestamp,
3244: };
3245: u32 csa_time_tu;
3246: ktime_t now;
3247: int res;
3248:
3249: lockdep_assert_wiphy(local->hw.wiphy);
3250:
3251: if (csa_elems) {
3252: struct cfg80211_bss *cbss = link->conf->bss;
3253: enum nl80211_band current_band;
3254: struct ieee80211_bss *bss;
3255:
3256: if (WARN_ON(!cbss))
3257: return;
3258:
3259: current_band = cbss->channel->band;
3260: bss = (void *)cbss->priv;
3261:
3262: res = ieee80211_parse_ch_switch_ie(sdata, csa_elems,
3263: current_band,
3264: bss->vht_cap_info,
3265: &link->u.mgd.conn,
3266: link->u.mgd.bssid,
3267: source == IEEE80211_CSA_SOURCE_UNPROT_ACTION,
3268: &csa_ie);
3269: if (res == 0) {
3270: ch_switch.block_tx = csa_ie.mode;
3271: ch_switch.chandef = csa_ie.chanreq.oper;
3272: ch_switch.count = csa_ie.count;
3273: ch_switch.delay = csa_ie.max_switch_time;
3274: }
3275:
3276: link->u.mgd.csa.tpe = csa_elems->csa_tpe;
3277: } else {
3278: /*
3279: * If there was no per-STA profile for this link, we
3280: * get called with csa_elems == NULL. This of course means
3281: * there are no CSA elements, so set res=1 indicating
3282: * no more CSA.
3283: */
3284: res = 1;
3285: }
3286:
3287: if (res < 0) {
3288: /* ignore this case, not a protected frame */
3289: if (source == IEEE80211_CSA_SOURCE_UNPROT_ACTION)
3290: return;
3291: goto drop_connection;
3292: }
3293:
3294: if (link->conf->csa_active) {
3295: switch (source) {
3296: case IEEE80211_CSA_SOURCE_PROT_ACTION:
3297: case IEEE80211_CSA_SOURCE_UNPROT_ACTION:
3298: /* already processing - disregard action frames */
3299: return;
3300: case IEEE80211_CSA_SOURCE_BEACON:
3301: if (link->u.mgd.csa.waiting_bcn) {
3302: ieee80211_chswitch_post_beacon(link);
3303: /*
3304: * If the CSA is still present after the switch
3305: * we need to consider it as a new CSA (possibly
3306: * to self). This happens by not returning here
3307: * so we'll get to the check below.
3308: */
3309: } else if (res) {
3310: ieee80211_sta_abort_chanswitch(link);
3311: return;
3312: } else {
3313: drv_channel_switch_rx_beacon(sdata, &ch_switch);
3314: return;
3315: }
3316: break;
3317: case IEEE80211_CSA_SOURCE_OTHER_LINK:
3318: /* active link: we want to see the beacon to continue */
3319: if (ieee80211_vif_link_active(&sdata->vif,
3320: link->link_id))
3321: return;
3322:
3323: /* switch work ran, so just complete the process */
3324: if (link->u.mgd.csa.waiting_bcn) {
3325: ieee80211_chswitch_post_beacon(link);
3326: /*
3327: * If the CSA is still present after the switch
3328: * we need to consider it as a new CSA (possibly
3329: * to self). This happens by not returning here
3330: * so we'll get to the check below.
3331: */
3332: break;
3333: }
3334:
3335: /* link still has CSA but we already know, do nothing */
3336: if (!res)
3337: return;
3338:
3339: /* check in the RNR if the CSA aborted */
3340: ieee80211_sta_other_link_csa_disappeared(link,
3341: full_elems);
3342: return;
3343: }
3344: }
3345:
3346: /* no active CSA nor a new one */
3347: if (res) {
3348: /*
3349: * However, we may have stopped queues when receiving a public
3350: * action frame that couldn't be protected, if it had the quiet
3351: * bit set. This is a trade-off, we want to be quiet as soon as
3352: * possible, but also don't trust the public action frame much,
3353: * as it can't be protected.
3354: */
3355: if (unlikely(link->u.mgd.csa.blocked_tx)) {
3356: link->u.mgd.csa.blocked_tx = false;
3357: ieee80211_vif_unblock_queues_csa(sdata);
3358: }
3359: return;
3360: }
3361:
3362: /*
3363: * We don't really trust public action frames, but block queues (go to
3364: * quiet mode) for them anyway, we should get a beacon soon to either
3365: * know what the CSA really is, or figure out the public action frame
3366: * was actually an attack.
3367: */
3368: if (source == IEEE80211_CSA_SOURCE_UNPROT_ACTION) {
3369: if (csa_ie.mode) {
3370: link->u.mgd.csa.blocked_tx = true;
3371: ieee80211_vif_block_queues_csa(sdata);
3372: }
3373: return;
3374: }
3375:
3376: if (link->conf->chanreq.oper.chan->band !=
3377: csa_ie.chanreq.oper.chan->band) {
3378: link_info(link,
3379: "AP %pM switches to different band (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
3380: link->u.mgd.bssid,
3381: csa_ie.chanreq.oper.chan->center_freq,
3382: csa_ie.chanreq.oper.width,
3383: csa_ie.chanreq.oper.center_freq1,
3384: csa_ie.chanreq.oper.center_freq2);
3385: goto drop_connection;
3386: }
3387:
3388: if (!cfg80211_chandef_usable(local->hw.wiphy, &csa_ie.chanreq.oper,
3389: IEEE80211_CHAN_DISABLED)) {
3390: link_info(link,
3391: "AP %pM switches to unsupported channel (%d.%03d MHz, width:%d, CF1/2: %d.%03d/%d MHz), disconnecting\n",
3392: link->u.mgd.bssid,
3393: csa_ie.chanreq.oper.chan->center_freq,
3394: csa_ie.chanreq.oper.chan->freq_offset,
3395: csa_ie.chanreq.oper.width,
3396: csa_ie.chanreq.oper.center_freq1,
3397: csa_ie.chanreq.oper.freq1_offset,
3398: csa_ie.chanreq.oper.center_freq2);
3399: goto drop_connection;
3400: }
3401:
3402: if (cfg80211_chandef_identical(&csa_ie.chanreq.oper,
3403: &link->conf->chanreq.oper) &&
3404: (!csa_ie.mode || source != IEEE80211_CSA_SOURCE_BEACON)) {
3405: if (link->u.mgd.csa.ignored_same_chan)
3406: return;
3407: link_info(link,
3408: "AP %pM tries to chanswitch to same channel, ignore\n",
3409: link->u.mgd.bssid);
3410: link->u.mgd.csa.ignored_same_chan = true;
3411: return;
3412: }
3413:
3414: /*
3415: * Drop all TDLS peers on the affected link - either we disconnect or
3416: * move to a different channel from this point on. There's no telling
3417: * what our peer will do.
3418: * The TDLS WIDER_BW scenario is also problematic, as peers might now
3419: * have an incompatible wider chandef.
3420: */
3421: ieee80211_teardown_tdls_peers(link);
3422:
3423: conf = rcu_dereference_protected(link->conf->chanctx_conf,
3424: lockdep_is_held(&local->hw.wiphy->mtx));
3425: if (ieee80211_vif_link_active(&sdata->vif, link->link_id) && !conf) {
3426: link_info(link,
3427: "no channel context assigned to vif?, disconnecting\n");
3428: goto drop_connection;
3429: }
3430:
3431: if (conf)
3432: chanctx = container_of(conf, struct ieee80211_chanctx, conf);
3433:
3434: if (!ieee80211_hw_check(&local->hw, CHANCTX_STA_CSA)) {
3435: link_info(link,
3436: "driver doesn't support chan-switch with channel contexts\n");
3437: goto drop_connection;
3438: }
3439:
3440: if (drv_pre_channel_switch(sdata, &ch_switch)) {
3441: link_info(link,
3442: "preparing for channel switch failed, disconnecting\n");
3443: goto drop_connection;
3444: }
3445:
3446: link->u.mgd.csa.ap_chandef = csa_ie.chanreq.ap;
3447:
3448: link->csa.chanreq.oper = csa_ie.chanreq.oper;
3449: ieee80211_set_chanreq_ap(sdata, &link->csa.chanreq, &link->u.mgd.conn,
3450: &csa_ie.chanreq.ap);
3451:
3452: if (chanctx) {
3453: res = ieee80211_link_reserve_chanctx(link, &link->csa.chanreq,
3454: chanctx->mode, false);
3455: if (res) {
3456: link_info(link,
3457: "failed to reserve channel context for channel switch, disconnecting (err=%d)\n",
3458: res);
3459: goto drop_connection;
3460: }
3461: }
3462:
3463: link->conf->csa_active = true;
3464: link->u.mgd.csa.ignored_same_chan = false;
3465: link->u.mgd.beacon_crc_valid = false;
3466: link->u.mgd.csa.blocked_tx = csa_ie.mode;
3467:
3468: if (csa_ie.mode)
3469: ieee80211_vif_block_queues_csa(sdata);
3470:
3471: cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chanreq.oper,
3472: link->link_id, csa_ie.count,
3473: csa_ie.mode);
3474:
3475: /* we may have to handle timeout for deactivated link in software */
3476: now = ktime_get_boottime();
3477: csa_time_tu = (max_t(int, csa_ie.count, 1) - 1) * link->conf->beacon_int;
3478: link->u.mgd.csa.time = now + us_to_ktime(ieee80211_tu_to_usec(csa_time_tu));
3479:
3480: if (ieee80211_vif_link_active(&sdata->vif, link->link_id) &&
3481: local->ops->channel_switch) {
3482: /*
3483: * Use driver's channel switch callback, the driver will
3484: * later call ieee80211_chswitch_done(). It may deactivate
3485: * the link as well, we handle that elsewhere and queue
3486: * the csa.switch_work for the calculated time then.
3487: */
3488: drv_channel_switch(local, sdata, &ch_switch);
3489: return;
3490: }
3491:
3492: /* channel switch handled in software */
3493: wiphy_hrtimer_work_queue(local->hw.wiphy,
3494: &link->u.mgd.csa.switch_work,
3495: link->u.mgd.csa.time - now);
3496: return;
3497: drop_connection:
3498: /*
3499: * This is just so that the disconnect flow will know that
3500: * we were trying to switch channel and failed. In case the
3501: * mode is 1 (we are not allowed to Tx), we will know not to
3502: * send a deauthentication frame. Those two fields will be
3503: * reset when the disconnection worker runs.
3504: */
3505: link->conf->csa_active = true;
3506: link->u.mgd.csa.blocked_tx = csa_ie.mode;
3507:
3508: wiphy_work_queue(sdata->local->hw.wiphy,
3509: &ifmgd->csa_connection_drop_work);
3510: }
SourceFile:net/mac80211/mlme.c]
|
| 88/2 |
2026/08/19 17:19 |
llm |
expert |
0m
Model:
Tokens:
input: 133562
output: 32
thoughts: 421
Thoughts: **My Analysis of the Channel Switch Vulnerability**
Okay, let's break this down systematically. We're looking at a potential vulnerability related to channel switching. The core of it seems to be in the `NL80211_CMD_CHANNEL_SWITCH` command, which ultimately calls `nl80211_channel_switch`. I know that function requires `CAP_NET_ADMIN` in the user namespace, which immediately throws a wrench into things given the constraint that user namespaces are *not* accessible in this scenario. Therefore, an unprivileged user cannot directly trigger the bug through this route.
So, is it exploitable? Initially, I was thinking yes because memory leaks are typically exploitable for a DoS. But the prompt explicitly focuses on whether the bug leads to memory corruption, privilege escalation, or information disclosure. A memory leak *isn't* any of those things. It's a resource leak. Therefore, I have to classify it as *not* directly exploitable in the way they are looking for.
However, the memory leak *is* a Denial of Service, absolutely. It's just not the kind of exploit they're focusing on in this prompt. It's *not* accessible from unprivileged processes, and it *is* accessible from user namespaces (if those were available to the attacker), but not via VM or other triggers.
Now, a remote trigger... hmm... *could* this be triggered remotely via a mesh network? If a mesh node receives a Channel Switch Announcement (CSA) action frame, perhaps that could trigger a path like `ieee80211_mesh_process_chnswitch` -> `ieee80211_mesh_csa_beacon`? That's the part that needs further investigation. I'll need to check the code around `ieee80211_mesh_process_chnswitch` to confirm that pathway.
|
| 89/2 |
2026/08/19 17:19 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_mesh_process_chnswitch]
Results: map[SourceCode:1258: static bool
1259: ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
1260: struct ieee802_11_elems *elems, bool beacon)
1261: {
1262: struct cfg80211_csa_settings params;
1263: struct ieee80211_csa_ie csa_ie;
1264: struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
1265: struct ieee80211_supported_band *sband;
1266: int err;
1267: struct ieee80211_conn_settings conn = ieee80211_conn_settings_unlimited;
1268: u32 vht_cap_info = 0;
1269:
1270: lockdep_assert_wiphy(sdata->local->hw.wiphy);
1271:
1272: sband = ieee80211_get_sband(sdata);
1273: if (!sband)
1274: return false;
1275:
1276: switch (sdata->vif.bss_conf.chanreq.oper.width) {
1277: case NL80211_CHAN_WIDTH_20_NOHT:
1278: conn.mode = IEEE80211_CONN_MODE_LEGACY;
1279: conn.bw_limit = IEEE80211_CONN_BW_LIMIT_20;
1280: break;
1281: case NL80211_CHAN_WIDTH_20:
1282: conn.mode = IEEE80211_CONN_MODE_HT;
1283: conn.bw_limit = IEEE80211_CONN_BW_LIMIT_20;
1284: break;
1285: case NL80211_CHAN_WIDTH_40:
1286: conn.mode = IEEE80211_CONN_MODE_HT;
1287: conn.bw_limit = IEEE80211_CONN_BW_LIMIT_40;
1288: break;
1289: default:
1290: break;
1291: }
1292:
1293: if (elems->vht_cap_elem)
1294: vht_cap_info =
1295: le32_to_cpu(elems->vht_cap_elem->vht_cap_info);
1296:
1297: memset(¶ms, 0, sizeof(params));
1298: err = ieee80211_parse_ch_switch_ie(sdata, elems, sband->band,
1299: vht_cap_info, &conn,
1300: sdata->vif.addr, false,
1301: &csa_ie);
1302: if (err < 0)
1303: return false;
1304: if (err)
1305: return false;
1306:
1307: /* Mark the channel unavailable if the reason for the switch is
1308: * regulatory.
1309: */
1310: if (csa_ie.reason_code == WLAN_REASON_MESH_CHAN_REGULATORY)
1311: ieee80211_mesh_csa_mark_radar(sdata);
1312:
1313: params.chandef = csa_ie.chanreq.oper;
1314: params.count = csa_ie.count;
1315:
1316: if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef,
1317: IEEE80211_CHAN_DISABLED) ||
1318: !cfg80211_reg_can_beacon(sdata->local->hw.wiphy, ¶ms.chandef,
1319: NL80211_IFTYPE_MESH_POINT)) {
1320: sdata_info(sdata,
1321: "mesh STA %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), aborting\n",
1322: sdata->vif.addr,
1323: params.chandef.chan->center_freq,
1324: params.chandef.width,
1325: params.chandef.center_freq1,
1326: params.chandef.center_freq2);
1327: return false;
1328: }
1329:
1330: err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
1331: ¶ms.chandef,
1332: NL80211_IFTYPE_MESH_POINT);
1333: if (err < 0)
1334: return false;
1335: if (err > 0 && !ifmsh->userspace_handles_dfs) {
1336: sdata_info(sdata,
1337: "mesh STA %pM switches to channel requiring DFS (%d MHz, width:%d, CF1/2: %d/%d MHz), aborting\n",
1338: sdata->vif.addr,
1339: params.chandef.chan->center_freq,
1340: params.chandef.width,
1341: params.chandef.center_freq1,
1342: params.chandef.center_freq2);
1343: return false;
1344: }
1345:
1346: params.radar_required = err;
1347:
1348: if (cfg80211_chandef_identical(¶ms.chandef,
1349: &sdata->vif.bss_conf.chanreq.oper)) {
1350: mcsa_dbg(sdata,
1351: "received csa with an identical chandef, ignoring\n");
1352: return true;
1353: }
1354:
1355: mcsa_dbg(sdata,
1356: "received channel switch announcement to go to channel %d MHz\n",
1357: params.chandef.chan->center_freq);
1358:
1359: params.block_tx = csa_ie.mode & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT;
1360: if (beacon) {
1361: ifmsh->chsw_ttl = csa_ie.ttl - 1;
1362: if (ifmsh->pre_value >= csa_ie.pre_value)
1363: return false;
1364: ifmsh->pre_value = csa_ie.pre_value;
1365: }
1366:
1367: if (ifmsh->chsw_ttl >= ifmsh->mshcfg.dot11MeshTTL)
1368: return false;
1369:
1370: ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_REPEATER;
1371:
1372: if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev,
1373: ¶ms) < 0)
1374: return false;
1375:
1376: return true;
1377: }
SourceFile:net/mac80211/mesh.c]
|
| 90/2 |
2026/08/19 17:19 |
llm |
expert |
0m
Model:
Tokens:
input: 136583
output: 31
thoughts: 1270
Thoughts: **Channel Switch Vulnerability in Mesh Mode**
Okay, here's what I've figured out: `ieee80211_mesh_process_chnswitch` is triggered by `ieee80211_mesh_rx_bcn_presp` and `ieee80211_mesh_rx_mgmt_action`. This function calls a chain of other functions, eventually leading to `ieee80211_mesh_csa_beacon` and allocating `tmp_csa_settings`. A malicious actor can exploit this! They can send a CSA action frame or a beacon with a CSA IE to a mesh node, initiating a channel switch.
Now, the important part: If the node *isn't* already in a channel switch (`sdata->vif.bss_conf.csa_active` is false), the `ieee80211_mesh_process_chnswitch` function *will* be called. It only triggers if `csa_active` is false. This will lead to `ieee80211_channel_switch` succeeding and `csa_active` becoming true. Crucially, `ifmsh->csa` will be set, but then, if the attacker stops sending beacons, or the mesh node leaves the mesh, `ifmsh->csa` will leak. However, if the mesh node leaves the mesh, that's a local action, so the attacker can't trigger it remotely.
The attacker could send a CSA frame to start a channel switch, and if it completes, `ieee80211_mesh_finish_csa` would be called, freeing `ifmsh->csa`, so no leak.
But, if the attacker sends a CSA frame with a large `count`, the channel switch will take a long time. If the user brings down the interface during this time, it leaks. However, that requires user interaction.
So, how can we make the leak happen without user interaction? What if the attacker sends a CSA frame, and then the channel switch fails? *Could we make it fail?* The only place where it can fail is in `ieee80211_set_csa_beacon`. This is the *last* thing that can fail in `__ieee80211_channel_switch`.
If `ieee80211_set_csa_beacon` succeeds, `csa_active` becomes true, so `__ieee80211_channel_switch` returns 0 (success) which means the channel switch is active. It will complete when the beacon count reaches 0, or `ieee80211_csa_finalize` is called. But `ieee80211_csa_finalize` is called if `changed` is 0, so that does not work.
However, for mesh, `ieee80211_mesh_csa_beacon` sets `*changed |= BSS_CHANGED_BEACON;`, so `changed` is always non-zero. Then `drv_channel_switch_beacon` is called. So, the channel switch does not finish immediately.
I'm trying to figure out how the channel switch finishes. Does the firmware handle this? In `mac80211`? I need to know who decrements the count. Is this something that happens in `ieee80211_mesh_rx_bcn_presp` or somewhere else? I'll need to check `ieee80211_mesh_build_beacon` to understand how the count is handled.
|
| 91/2 |
2026/08/19 17:19 |
tool |
codesearch-definition-source |
0m
Args: map[Name:ieee80211_mesh_build_beacon]
Results: map[SourceCode: 934: static int
935: ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
936: {
937: struct beacon_data *bcn;
938: int head_len, tail_len;
939: struct sk_buff *skb;
940: struct ieee80211_mgmt *mgmt;
941: struct mesh_csa_settings *csa;
942: const struct ieee80211_supported_band *sband;
943: u8 ie_len_he_cap, ie_len_eht_cap;
944: u8 *pos;
945: struct ieee80211_sub_if_data *sdata;
946: int hdr_len = offsetofend(struct ieee80211_mgmt, u.beacon);
947:
948: sdata = container_of(ifmsh, struct ieee80211_sub_if_data, u.mesh);
949:
950: sband = ieee80211_get_sband(sdata);
951:
952: ie_len_he_cap = ieee80211_ie_len_he_cap(sdata);
953: ie_len_eht_cap = ieee80211_ie_len_eht_cap(sdata);
954: head_len = hdr_len +
955: 2 + /* NULL SSID */
956: /* Channel Switch Announcement */
957: 2 + sizeof(struct ieee80211_channel_sw_ie) +
958: /* Mesh Channel Switch Parameters */
959: 2 + sizeof(struct ieee80211_mesh_chansw_params_ie) +
960: /* Channel Switch Wrapper + Wide Bandwidth CSA IE */
961: 2 + 2 + sizeof(struct ieee80211_wide_bw_chansw_ie) +
962: 2 + sizeof(struct ieee80211_sec_chan_offs_ie) +
963: 2 + 8 + /* supported rates */
964: 2 + 3; /* DS params */
965: tail_len = 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
966: 2 + sizeof(struct ieee80211_ht_cap) +
967: 2 + sizeof(struct ieee80211_ht_operation) +
968: 2 + ifmsh->mesh_id_len +
969: 2 + sizeof(struct ieee80211_meshconf_ie) +
970: 2 + sizeof(__le16) + /* awake window */
971: 2 + sizeof(struct ieee80211_vht_cap) +
972: 2 + sizeof(struct ieee80211_vht_operation) +
973: ie_len_he_cap +
974: 2 + 1 + sizeof(struct ieee80211_he_operation) +
975: sizeof(struct ieee80211_he_6ghz_oper) +
976: 2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) +
977: ie_len_eht_cap +
978: 2 + 1 + offsetof(struct ieee80211_eht_operation, optional) +
979: offsetof(struct ieee80211_eht_operation_info, optional) +
980: ifmsh->ie_len;
981:
982: bcn = kzalloc(sizeof(*bcn) + head_len + tail_len, GFP_KERNEL);
983: /* need an skb for IE builders to operate on */
984: skb = __dev_alloc_skb(max(head_len, tail_len), GFP_KERNEL);
985:
986: if (!bcn || !skb)
987: goto out_free;
988:
989: /*
990: * pointers go into the block we allocated,
991: * memory is | beacon_data | head | tail |
992: */
993: bcn->head = ((u8 *) bcn) + sizeof(*bcn);
994:
995: /* fill in the head */
996: mgmt = skb_put_zero(skb, hdr_len);
997: mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
998: IEEE80211_STYPE_BEACON);
999: eth_broadcast_addr(mgmt->da);
1000: memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
1001: memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
1002: ieee80211_mps_set_frame_flags(sdata, NULL, (void *) mgmt);
1003: mgmt->u.beacon.beacon_int =
1004: cpu_to_le16(sdata->vif.bss_conf.beacon_int);
1005: mgmt->u.beacon.capab_info |= cpu_to_le16(
1006: sdata->u.mesh.security ? WLAN_CAPABILITY_PRIVACY : 0);
1007:
1008: pos = skb_put(skb, 2);
1009: *pos++ = WLAN_EID_SSID;
1010: *pos++ = 0x0;
1011:
1012: rcu_read_lock();
1013: csa = rcu_dereference(ifmsh->csa);
1014: if (csa) {
1015: enum nl80211_channel_type ct;
1016: struct cfg80211_chan_def *chandef;
1017: int ie_len = 2 + sizeof(struct ieee80211_channel_sw_ie) +
1018: 2 + sizeof(struct ieee80211_mesh_chansw_params_ie);
1019:
1020: pos = skb_put_zero(skb, ie_len);
1021: *pos++ = WLAN_EID_CHANNEL_SWITCH;
1022: *pos++ = 3;
1023: *pos++ = 0x0;
1024: *pos++ = ieee80211_frequency_to_channel(
1025: csa->settings.chandef.chan->center_freq);
1026: bcn->cntdwn_current_counter = csa->settings.count;
1027: bcn->cntdwn_counter_offsets[0] = hdr_len + 6;
1028: *pos++ = csa->settings.count;
1029: *pos++ = WLAN_EID_CHAN_SWITCH_PARAM;
1030: *pos++ = 6;
1031: if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) {
1032: *pos++ = ifmsh->mshcfg.dot11MeshTTL;
1033: *pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
1034: } else {
1035: *pos++ = ifmsh->chsw_ttl;
1036: }
1037: *pos++ |= csa->settings.block_tx ?
1038: WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
1039: put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos);
1040: pos += 2;
1041: put_unaligned_le16(ifmsh->pre_value, pos);
1042: pos += 2;
1043:
1044: switch (csa->settings.chandef.width) {
1045: case NL80211_CHAN_WIDTH_40:
1046: ie_len = 2 + sizeof(struct ieee80211_sec_chan_offs_ie);
1047: pos = skb_put_zero(skb, ie_len);
1048:
1049: *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; /* EID */
1050: *pos++ = 1; /* len */
1051: ct = cfg80211_get_chandef_type(&csa->settings.chandef);
1052: if (ct == NL80211_CHAN_HT40PLUS)
1053: *pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
1054: else
1055: *pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
1056: break;
1057: case NL80211_CHAN_WIDTH_80:
1058: case NL80211_CHAN_WIDTH_80P80:
1059: case NL80211_CHAN_WIDTH_160:
1060: /* Channel Switch Wrapper + Wide Bandwidth CSA IE */
1061: ie_len = 2 + 2 +
1062: sizeof(struct ieee80211_wide_bw_chansw_ie);
1063: pos = skb_put_zero(skb, ie_len);
1064:
1065: *pos++ = WLAN_EID_CHANNEL_SWITCH_WRAPPER; /* EID */
1066: *pos++ = 5; /* len */
1067: /* put sub IE */
1068: chandef = &csa->settings.chandef;
1069: ieee80211_ie_build_wide_bw_cs(pos, chandef);
1070: break;
1071: default:
1072: break;
1073: }
1074: }
1075: rcu_read_unlock();
1076:
1077: if (ieee80211_put_srates_elem(skb, sband,
1078: sdata->vif.bss_conf.basic_rates,
1079: 0, WLAN_EID_SUPP_RATES) ||
1080: mesh_add_ds_params_ie(sdata, skb))
1081: goto out_free;
1082:
1083: bcn->head_len = skb->len;
1084: memcpy(bcn->head, skb->data, bcn->head_len);
1085:
1086: /* now the tail */
1087: skb_trim(skb, 0);
1088: bcn->tail = bcn->head + bcn->head_len;
1089:
1090: if (ieee80211_put_srates_elem(skb, sband,
1091: sdata->vif.bss_conf.basic_rates,
1092: 0, WLAN_EID_EXT_SUPP_RATES) ||
1093: mesh_add_rsn_ie(sdata, skb) ||
1094: mesh_add_ht_cap_ie(sdata, skb) ||
1095: mesh_add_ht_oper_ie(sdata, skb) ||
1096: mesh_add_meshid_ie(sdata, skb) ||
1097: mesh_add_meshconf_ie(sdata, skb) ||
1098: mesh_add_awake_window_ie(sdata, skb) ||
1099: mesh_add_vht_cap_ie(sdata, skb) ||
1100: mesh_add_vht_oper_ie(sdata, skb) ||
1101: mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) ||
1102: mesh_add_he_oper_ie(sdata, skb) ||
1103: mesh_add_he_6ghz_cap_ie(sdata, skb) ||
1104: mesh_add_eht_cap_ie(sdata, skb, ie_len_eht_cap) ||
1105: mesh_add_eht_oper_ie(sdata, skb) ||
1106: mesh_add_vendor_ies(sdata, skb))
1107: goto out_free;
1108:
1109: bcn->tail_len = skb->len;
1110: memcpy(bcn->tail, skb->data, bcn->tail_len);
1111: ieee80211_mesh_update_bss_params(sdata, bcn->tail, bcn->tail_len);
1112: bcn->meshconf = (struct ieee80211_meshconf_ie *)
1113: (bcn->tail + ifmsh->meshconf_offset);
1114:
1115: dev_kfree_skb(skb);
1116: rcu_assign_pointer(ifmsh->beacon, bcn);
1117: return 0;
1118: out_free:
1119: kfree(bcn);
1120: dev_kfree_skb(skb);
1121: return -ENOMEM;
1122: }
SourceFile:net/mac80211/mesh.c]
|
| 92/2 |
2026/08/19 17:19 |
llm |
expert |
0m
Model:
Tokens:
input: 142551
output: 30
thoughts: 4270
Thoughts: **Analysis of the IEEE 802.11 Mesh Channel Switch Vulnerability**
Okay, so I've been dissecting this channel switch vulnerability in the mesh networking code. The core issue is a memory leak, specifically the `ifmsh->csa` structure. Here's what I've figured out:
The `ieee80211_mesh_build_beacon` function builds the beacon with the CSA IE. The CSA process involves a count that's decremented by the driver or hardware. When this count reaches zero, the driver notifies mac80211, and that's when the channel switch finalizes. If the driver doesn't handle hardware CSA, mac80211 will take over, I understand this fully.
The leak happens when `ifmsh->csa` isn't properly freed. This occurs if the interface is stopped while a channel switch is active (i.e., `csa_active` is true). `ieee80211_do_stop` unsets `csa_active`, but does *not* free `ifmsh->csa`. This is the crux. So, if a CSA frame is received, initiating the channel switch, and then the interface is stopped, `ifmsh->csa` remains leaked.
The immediate thought was whether an attacker could trigger this. Sending a CSA frame, followed by deauth/disassoc. However, mesh nodes don't stop the interface on deauth. Also, the `ieee80211_mesh_process_chnswitch` function prevents the vulnerability from being triggered by multiple CSA frames in quick succession. `csa_active` acts as a guard.
I've explored all the code paths where `ifmsh->csa` *should* be freed:
* When a channel switch completes (`ieee80211_csa_finalize` is called, all good).
* When rebuilding the beacon fails (`ieee80211_mesh_rebuild_beacon` handles it).
* Even if `ieee80211_set_csa_beacon` fails *after* `ieee80211_mesh_csa_beacon`.
* And `__ieee80211_channel_switch` succeeding doesn't cause a leak.
The key observation is that the leak only happens if the interface is *stopped* while the channel switch is active. Because stopping the interface requires `CAP_NET_ADMIN` privileges, only a privileged user can trigger it. The thought of unprivileged users in user namespaces crossed my mind, but that's been ruled out.
From a remote attacker's perspective, this isn't directly exploitable. A remote attacker can send a CSA frame to start a channel switch, but they *can't* stop the interface.
So, the Syzkaller reproducer must trigger a specific sequence. It sends the `CHANNEL_SWITCH` command and then exits. The exit causes the net namespace to be destroyed. Interface gets torn down. This teardown triggers `ieee80211_do_stop`, *and the leak occurs because it's not freeing `ifmsh->csa`.*
A local process with `CAP_NET_ADMIN`, or running in a user namespace with `CAP_NET_ADMIN` is the only way to trigger this bug. A remote attack isn't going to be possible, I believe.
I have re-checked the execution path for all failure conditions. There are no other ways for the channel switch to be aborted. It doesn't look like any other code path that I checked can lead to the leak.
Therefore, this is a local denial-of-service vulnerability, but not remotely exploitable, nor is it exploitable by unprivileged users on a normal system.
|
| 93/2 |
2026/08/19 17:20 |
tool |
codesearch-find-references |
0m
Args: map[Name:ieee80211_csa_finalize]
Results: map[References:[map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:__ieee80211_channel_switch SourceFile:net/mac80211/cfg.c SourceLine:4816] map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:ieee80211_csa_finalize_work SourceFile:net/mac80211/cfg.c SourceLine:4560]] TruncatedOutput:false]
|
| 94/2 |
2026/08/19 17:20 |
llm |
expert |
0m
Model:
Tokens:
input: 147827
output: 32
thoughts: 56
Thoughts: Here's my thought process, as if I were analyzing that code:
**Digging into the CSA Finalization Logic**
Okay, so I'm looking at `ieee80211_csa_finalize`... I know it's related to Channel Switch Announcements (CSAs), which is crucial for handling channel changes in 802.11 networks. My immediate question is, how and when is this `finalize` function actually executed? The text clearly shows it's called from `ieee80211_csa_finalize_work`. That's the key. Now, the next logical step in my investigation: where does `ieee80211_csa_finalize_work` get *queued*? Understanding the queue mechanism will reveal the timing and context of the finalization process, which will be vital for debugging, performance optimization, and even security assessments. Gotta trace that back to see what triggers the `work` to execute.
|
| 95/2 |
2026/08/19 17:20 |
tool |
codesearch-find-references |
0m
Args: map[Name:ieee80211_csa_finalize_work]
Results: map[References:[map[ReferenceKind:takes-address-of ReferencingEntityKind:function ReferencingEntityName:ieee80211_link_init SourceFile:net/mac80211/link.c SourceLine:131]] TruncatedOutput:false]
|
| 96/2 |
2026/08/19 17:20 |
llm |
expert |
0m
Model:
Tokens:
input: 148208
output: 31
thoughts: 72
Thoughts: Okay, let's break this down.
**Diving into the CSA Finalization Work**
Alright, so I'm looking at this bit of code, specifically the `ieee80211_link_init` function. It seems like it's initializing something related to Channel Switch Announcements (CSAs) within a wireless link. The key line here is:
```c
INIT_WIPHY_WORK(&link->csa.finalize_work, ieee80211_csa_finalize_work);
```
I'm instantly zeroing in on `link->csa.finalize_work`. It's pretty clear that this is a work item, a delayed function call, related to finalizing a CSA operation. The `INIT_WIPHY_WORK` macro likely sets up the internal structure needed for this work item. And from the code, I can tell it links `link->csa.finalize_work` to the function `ieee80211_csa_finalize_work`, so that's the code that will actually *do* the finalization.
Now my real question is: where is this work item actually getting queued? The snippet doesn't show me that. I need to figure out where and *when* `link->csa.finalize_work` is actually scheduled to run. Is it triggered by a timer? Is it part of a specific process or interrupt? I need to trace the references to this work item to understand the control flow and understand the timing of the CSA finalization. Time to go hunting for the call to `queue_work()`, or something similar, where the work item gets added to the workqueue.
|
| 97/2 |
2026/08/19 17:20 |
tool |
grepper |
0m
Args: map[Expression:finalize_work PathPrefix:net/mac80211]
Results: map[Output:net/mac80211/cfg.c=4375=void ieee80211_csa_finish(struct ieee80211_vif *vif, unsigned int link_id)
--
net/mac80211/cfg.c-4406- wiphy_work_queue(iter->sdata->local->hw.wiphy,
net/mac80211/cfg.c:4407: &iter->csa.finalize_work);
net/mac80211/cfg.c-4408- }
--
net/mac80211/cfg.c-4410-
net/mac80211/cfg.c:4411: wiphy_work_queue(local->hw.wiphy, &link_data->csa.finalize_work);
net/mac80211/cfg.c-4412-
--
net/mac80211/cfg.c=4523=static void ieee80211_csa_finalize(struct ieee80211_link_data *link_data)
--
net/mac80211/cfg.c-4543-
net/mac80211/cfg.c:4544:void ieee80211_csa_finalize_work(struct wiphy *wiphy, struct wiphy_work *work)
net/mac80211/cfg.c-4545-{
net/mac80211/cfg.c-4546- struct ieee80211_link_data *link =
net/mac80211/cfg.c:4547: container_of(work, struct ieee80211_link_data, csa.finalize_work);
net/mac80211/cfg.c-4548- struct ieee80211_sub_if_data *sdata = link->sdata;
--
net/mac80211/cfg.c=5610=static int ieee80211_color_change_finalize(struct ieee80211_link_data *link)
--
net/mac80211/cfg.c-5634-
net/mac80211/cfg.c:5635:void ieee80211_color_change_finalize_work(struct wiphy *wiphy,
net/mac80211/cfg.c-5636- struct wiphy_work *work)
--
net/mac80211/cfg.c-5639- container_of(work, struct ieee80211_link_data,
net/mac80211/cfg.c:5640: color_change_finalize_work);
net/mac80211/cfg.c-5641- struct ieee80211_sub_if_data *sdata = link->sdata;
--
net/mac80211/cfg.c=5669=void ieee80211_color_change_finish(struct ieee80211_vif *vif, u8 link_id)
--
net/mac80211/cfg.c-5685- wiphy_work_queue(sdata->local->hw.wiphy,
net/mac80211/cfg.c:5686: &link->color_change_finalize_work);
net/mac80211/cfg.c-5687-
--
net/mac80211/chan.c=1579=ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link)
--
net/mac80211/chan.c-1588- wiphy_work_queue(sdata->local->hw.wiphy,
net/mac80211/chan.c:1589: &link->csa.finalize_work);
net/mac80211/chan.c-1590- break;
--
net/mac80211/ieee80211_i.h=1099=struct ieee80211_link_data {
--
net/mac80211/ieee80211_i.h-1114- struct {
net/mac80211/ieee80211_i.h:1115: struct wiphy_work finalize_work;
net/mac80211/ieee80211_i.h-1116- struct ieee80211_chan_req chanreq;
--
net/mac80211/ieee80211_i.h-1118-
net/mac80211/ieee80211_i.h:1119: struct wiphy_work color_change_finalize_work;
net/mac80211/ieee80211_i.h-1120- struct wiphy_delayed_work color_collision_detect_work;
--
net/mac80211/ieee80211_i.h=2160=int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
--
net/mac80211/ieee80211_i.h-2163-/* channel switch handling */
net/mac80211/ieee80211_i.h:2164:void ieee80211_csa_finalize_work(struct wiphy *wiphy, struct wiphy_work *work);
net/mac80211/ieee80211_i.h-2165-int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
--
net/mac80211/ieee80211_i.h-2168-/* color change handling */
net/mac80211/ieee80211_i.h:2169:void ieee80211_color_change_finalize_work(struct wiphy *wiphy,
net/mac80211/ieee80211_i.h-2170- struct wiphy_work *work);
--
net/mac80211/iface.c=479=static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_down)
--
net/mac80211/iface.c-571-
net/mac80211/iface.c:572: wiphy_work_cancel(local->hw.wiphy, &sdata->deflink.csa.finalize_work);
net/mac80211/iface.c-573- wiphy_work_cancel(local->hw.wiphy,
net/mac80211/iface.c:574: &sdata->deflink.color_change_finalize_work);
net/mac80211/iface.c-575- wiphy_hrtimer_work_cancel(local->hw.wiphy,
--
net/mac80211/link.c=95=void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
--
net/mac80211/link.c-129-
net/mac80211/link.c:130: wiphy_work_init(&link->csa.finalize_work,
net/mac80211/link.c:131: ieee80211_csa_finalize_work);
net/mac80211/link.c:132: wiphy_work_init(&link->color_change_finalize_work,
net/mac80211/link.c:133: ieee80211_color_change_finalize_work);
net/mac80211/link.c-134- wiphy_delayed_work_init(&link->color_collision_detect_work,
--
net/mac80211/link.c=162=void ieee80211_link_stop(struct ieee80211_link_data *link)
--
net/mac80211/link.c-169- wiphy_work_cancel(link->sdata->local->hw.wiphy,
net/mac80211/link.c:170: &link->color_change_finalize_work);
net/mac80211/link.c-171- wiphy_work_cancel(link->sdata->local->hw.wiphy,
net/mac80211/link.c:172: &link->csa.finalize_work);
net/mac80211/link.c-173-
]
|
| 98/2 |
2026/08/19 17:20 |
llm |
expert |
0m
Model:
Tokens:
input: 151007
output: 25
thoughts: 1114
Thoughts: **Analyzing the IEEE 802.11 CSA Memory Leak**
Okay, so here's the breakdown of this potential memory leak in the 802.11 channel switch code, and how an adversary could trigger it. `ieee80211_csa_finish` is the critical function here; it's called by the driver after a channel switch completes and it should be cleaning up the mess. The driver is responsible for telling the core when the hardware finishes switching channels. However, there's a race condition if the interface is stopped (using something like `ifconfig down`) *while* the channel switch is in progress. `ieee80211_do_stop` cancels the `finalize_work` for CSA. This means `ieee80211_csa_finalize` never runs, which leaves `ifmsh->csa` hanging around, causing a memory leak.
The initial assumption was this wasn't exploitable by unprivileged users, since stopping an interface normally requires `CAP_NET_ADMIN`. We're looking at a Denial of Service via a memory leak, which is not direct code execution but still problematic.
So, I went through all the usual ways to stop/destroy an interface - `SIOCSIFFLAGS`, `RTM_DELLINK`, even closing a netlink socket if we somehow had an unprivileged user namespace – all require `CAP_NET_ADMIN`, and the prompt assumed that unprivileged user namespaces are not accessible. So, no go there.
Then it hit me: what about a USB Wi-Fi dongle? If you *unplug* the device while a channel switch is active, the driver gets unloaded, and the interface is destroyed. This would call `ieee80211_teardown_sdata` and `ieee80211_do_stop` which should trigger the leak. This seems like a Peripheral Trigger, and it's physically unplugging the device. But the initial CSA must be triggered first.
However, initiating the channel switch in the first place would still need `CAP_NET_ADMIN`, so an unprivileged user can't *start* the process without help.
Aha! This is where the mesh network aspect changes things. If this is a mesh node and a *remote* attacker sends a Channel Switch Announcement (CSA) frame, the node starts the channel switch. Then, a user unplugs the USB dongle. Boom: memory leak. This is a combined scenario: remote (CSA frame) and physical (unplugging). A long CSA countdown could make it easier to unplug the device at the right time.
But is that a "Peripheral Trigger"? The prompt defines the trigger as via an untrusted peripheral device. Here, the dongle is not the *trigger* in the strict sense, it's just the interface being manipulated in the physical world. The trigger is the *remote* CSA frame.
Could a remote attacker, somehow, *cause* the interface to stop/destroy itself? A malformed frame that triggers a driver reset is driver-specific, but that's a possibility, though a less general one.
Oh, one more thing to check: timeouts. Is there a timeout that could abort the channel switch? Looking into the code, regular STA code has a timeout. However, in mesh, the channel switch does NOT queue a timeout work! Mesh nodes call `ieee80211_channel_switch`. Specifically, `ieee80211_mesh_csa_beacon` calls `__ieee80211_channel_switch` with `drv_channel_switch_beacon` if hardware CSA is not supported.
|
| 99/2 |
2026/08/19 17:21 |
tool |
codesearch-definition-source |
0m
Args: map[Name:drv_channel_switch_beacon]
Results: map[SourceCode:1155: static inline void
1156: drv_channel_switch_beacon(struct ieee80211_sub_if_data *sdata,
1157: struct cfg80211_chan_def *chandef)
1158: {
1159: struct ieee80211_local *local = sdata->local;
1160:
1161: might_sleep();
1162: lockdep_assert_wiphy(local->hw.wiphy);
1163:
1164: if (local->ops->channel_switch_beacon) {
1165: trace_drv_channel_switch_beacon(local, sdata, chandef);
1166: local->ops->channel_switch_beacon(&local->hw, &sdata->vif,
1167: chandef);
1168: }
1169: }
SourceFile:net/mac80211/driver-ops.h]
|
| 100/2 |
2026/08/19 17:21 |
llm |
expert |
0m
Model:
Tokens:
input: 153227
output: 21
thoughts: 243
Thoughts: **Mesh CSA Count Decryption**
Okay, so I'm thinking through this channel switch announcement (CSA) situation. If the driver doesn't bother to provide a `channel_switch_beacon` implementation, then effectively, it does nothing. But, hold on a second... if the *driver* isn't decrementing the CSA count, then *who* is? For Access Point (AP) mode, I know `mac80211` handles the decrementing in `ieee80211_ap_csa_handle_bcn`. But what about mesh mode? I need to figure out the decrementing process in that context.
Let me check `ieee80211_mesh_build_beacon`. Aha! I see it uses `csa->settings.count`. But wait, it doesn't *decrement* it there. Okay, so it sets `bcn->cntdwn_current_counter = csa->settings.count;` and, crucially, `bcn->cntdwn_counter_offsets[0] = hdr_len + 6;`. *That's* the key. It's essentially telling the driver or the hardware where to find the counter *within* the beacon so the hardware can decrement it directly! So, the hardware handles the decrementing.
Now, if the hardware *doesn't* have direct support for decrementing, does `mac80211` kick in with a software fallback? I should probably check out `ieee80211_ap_csa_handle_bcn` or something similar for mesh, just to be sure. I need to understand if there is a software mechanism for those cases.
|
| 101/2 |
2026/08/19 17:21 |
tool |
grepper |
0m
Args: map[Expression:cntdwn_current_counter]
Results: map[Output:net/mac80211/cfg.c=1464=ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
--
net/mac80211/cfg.c-1546- if (csa) {
net/mac80211/cfg.c:1547: new->cntdwn_current_counter = csa->count;
net/mac80211/cfg.c-1548- memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_beacon,
--
net/mac80211/cfg.c-1551- } else if (cca) {
net/mac80211/cfg.c:1552: new->cntdwn_current_counter = cca->count;
net/mac80211/cfg.c-1553- new->cntdwn_counter_offsets[0] = cca->counter_offset_beacon;
--
net/mac80211/ibss.c=38=ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
--
net/mac80211/ibss.c-143- *pos++ = csa_settings->count;
net/mac80211/ibss.c:144: presp->cntdwn_current_counter = csa_settings->count;
net/mac80211/ibss.c-145- }
--
net/mac80211/ieee80211_i.h=280=struct beacon_data {
--
net/mac80211/ieee80211_i.h-284- u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
net/mac80211/ieee80211_i.h:285: u8 cntdwn_current_counter;
net/mac80211/ieee80211_i.h-286- struct cfg80211_mbssid_elems *mbssid_ies;
--
net/mac80211/mesh.c=935=ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
--
net/mac80211/mesh.c-1025- csa->settings.chandef.chan->center_freq);
net/mac80211/mesh.c:1026: bcn->cntdwn_current_counter = csa->settings.count;
net/mac80211/mesh.c-1027- bcn->cntdwn_counter_offsets[0] = hdr_len + 6;
--
net/mac80211/offchannel.c=812=int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
--
net/mac80211/offchannel.c-1004- data[params->csa_offsets[i]] =
net/mac80211/offchannel.c:1005: beacon->cntdwn_current_counter;
net/mac80211/offchannel.c-1006-
--
net/mac80211/tx.c=5208=static void ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data *sdata,
--
net/mac80211/tx.c-5237- bcn_offsets = beacon->cntdwn_counter_offsets;
net/mac80211/tx.c:5238: count = beacon->cntdwn_current_counter;
net/mac80211/tx.c-5239- if (link->conf->csa_active)
--
net/mac80211/tx.c=5257=static u8 __ieee80211_beacon_update_cntdwn(struct ieee80211_link_data *link,
--
net/mac80211/tx.c-5259-{
net/mac80211/tx.c:5260: if (beacon->cntdwn_current_counter == 1) {
net/mac80211/tx.c-5261- /*
--
net/mac80211/tx.c-5274-
net/mac80211/tx.c:5275: beacon->cntdwn_current_counter--;
net/mac80211/tx.c-5276-
net/mac80211/tx.c:5277: return beacon->cntdwn_current_counter;
net/mac80211/tx.c-5278-}
--
net/mac80211/tx.c=5314=void ieee80211_beacon_set_cntdwn(struct ieee80211_vif *vif, u8 counter)
--
net/mac80211/tx.c-5330-
net/mac80211/tx.c:5331: if (counter < beacon->cntdwn_current_counter)
net/mac80211/tx.c:5332: beacon->cntdwn_current_counter = counter;
net/mac80211/tx.c-5333-
]
|
| 102/2 |
2026/08/19 17:21 |
llm |
expert |
0m
Model:
Tokens:
input: 155320
output: 34
thoughts: 94
Thoughts: Okay, here's my interpretation of that code snippet, presented as my own thought process:
**Beacon Countdown & CSA Finalization**
Right, so `__ieee80211_beacon_update_cntdwn` is the one decrementing the countdown timer. That makes sense, keeps track of when we should act. And the really important bit is that when that counter hits zero, boom, `ieee80211_csa_finalize` gets called. That's the critical link. Now, I need to understand where that decrement is actually happening. Is it triggered in `ieee80211_tx_bcn_update_cntdwn`? That feels like the most logical place, given the names. Let me confirm that.
|
| 103/2 |
2026/08/19 17:21 |
tool |
codesearch-find-references |
0m
Args: map[Name:__ieee80211_beacon_update_cntdwn]
Results: map[References:[map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:__ieee80211_beacon_get SourceFile:net/mac80211/tx.c SourceLine:5815] map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:__ieee80211_beacon_get SourceFile:net/mac80211/tx.c SourceLine:5847] map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:ieee80211_beacon_update_cntdwn SourceFile:net/mac80211/tx.c SourceLine:5306]] TruncatedOutput:false]
|
| 104/2 |
2026/08/19 17:21 |
llm |
expert |
0m
Model:
Tokens:
input: 155825
output: 66
thoughts: 2050
Thoughts: **Analysis of the IEEE 802.11 Channel Switch Memory Leak**
Okay, let's break this down. From what I'm seeing, `ieee80211_beacon_update_cntdwn` is called either when a driver indicates a beacon transmission or when mac80211 itself sends one. This means the channel switch should, eventually, complete, and `ifmsh->csa` *should* be freed. The crux of the problem lies in the interface being stopped *before* that channel switch finishes. This leads to the memory leak, as confirmed by my earlier analysis.
Now, because stopping the interface directly requires `CAP_NET_ADMIN`, it's clear this isn't something an unprivileged process can do. I've got to consider all the angles, though. Can a remote actor cause this to happen? Nope, there isn't a direct remote trigger.
I considered a denial-of-service attack with CSA frames with count set to 255 to cause a very long channel switch, but the `ieee80211_mesh_process_chnswitch` function prevents this with `csa_active`. This means the channel switch will still complete and `ifmsh->csa` will be freed. No remote permanent leak possible.
So, the issue is a local denial-of-service (DoS) via memory leak, and it requires `CAP_NET_ADMIN`. Not exploitable for privilege escalation directly, not accessible from unprivileged processes. However, since the prompt specified, and now I've confirmed that the NL80211_CMD_CHANNEL_SWITCH command is accessible from user namespaces, then, it is accessible from user namespaces.
Now, let's go down the list of potential triggers. It's not exploitable, because it is just a DoS. Since `CAP_NET_ADMIN` is needed to stop the interface, this means the bug is not unprivileged. As previously mentioned, the user namespace is the relevant triggering path. I am sure that there are no VM triggers. Since this is a local issue, there is no network, remote, or filesystem trigger.
I had to give it some thought, but I'm pretty certain there's no way a malicious USB device could be inserted to trigger this. The USB device, even if malicious, can't directly stop the mesh interface that it is attached to. It would need to have `CAP_NET_ADMIN` privileges. Sending a CSA frame would start the channel switch, but it can't stop the interface.
Here, I'm thinking about other possible triggering paths. If the mesh interface is automatically stopped by a daemon (like NetworkManager or wpa_supplicant), then maybe it could be remotely triggered? But, the bug report specifies a local syzkaller reproducer that explicitly creates the interface, starts the channel switch, and then exits. So, it's not a remote trigger.
I've also re-examined the code, particularly the `ieee80211_mesh_csa_beacon` function to ensure that there aren't any error paths that could trigger the leak. The code confirms that only stopping the interface while a channel switch is active leaks the memory.
In terms of exploitability, while it's a memory leak of 1024 bytes per trigger, an attacker can trigger this again and again. It would eventually lead to an out-of-memory (OOM) situation and a denial of service, but doesn't cause memory corruption or privilege escalation, so it's not directly exploitable in that sense.
So, I'm sticking with my conclusion: the key points are:
* Exploitable: False
* DenialOfService: True
* Unprivileged: False
* UserNamespace: True
* VMGuestTrigger: False
* VMHostTrigger: False
* NetworkTrigger: False
* RemoteTrigger: False
* PeripheralTrigger: False
* FilesystemTrigger: False
|
| 105/2 |
2026/08/19 17:21 |
tool |
set-results |
0m
Args: map[DenialOfService:true Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:false UserNamespace:true VMGuestTrigger:false VMHostTrigger:false]
Results: map[DenialOfService:true Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:false UserNamespace:true VMGuestTrigger:false VMHostTrigger:false]
|
| 106/2 |
2026/08/19 17:22 |
llm |
expert |
0m
Model:
Tokens:
input: 158869
output: 655
thoughts: 494
Thoughts: **Final Assessment of the Mesh CSA Memory Leak**
Okay, the results are in, and it's time to craft the final response. Here's how I see this:
This memory leak in the mesh channel switch announcement (CSA) functionality boils down to a failure to free the `struct mesh_csa_settings` memory allocated within `ieee80211_mesh_csa_beacon`. That allocation is triggered when a channel switch is initiated on a mesh interface using something like `NL80211_CMD_CHANNEL_SWITCH`.
Normally, `ifmsh->csa` holds the allocated memory, and `ieee80211_mesh_finish_csa` takes care of freeing it when the channel switch successfully completes. The catch? If the mesh interface gets stopped or destroyed (think network namespace destruction or interface shutdown) *while* a channel switch is still pending, the cleanup procedures like `ieee80211_do_stop`, `ieee80211_stop_mesh`, or `ieee80211_mesh_teardown_sdata` fail to free that `ifmsh->csa` memory. Boom, memory leak.
Now, to actually trigger this, you need to create a mesh interface, join a mesh, and initiate a channel switch. Both the join and channel switch operations (`NL80211_CMD_JOIN_MESH` and `NL80211_CMD_CHANNEL_SWITCH`) specifically require `CAP_NET_ADMIN`. This alone means an unprivileged user in the initial namespace is blocked.
The good news is, these Netlink operations also have the `GENL_UNS_ADMIN_PERM` flag. That means a user with `CAP_NET_ADMIN` *within* a user namespace can trigger the leak. So it is accessible from within a user namespace.
The critical piece for exploitation: this is a *pure* memory leak. It can definitely lead to a denial-of-service (DoS) via out-of-memory (OOM) if you trigger it repeatedly. However, there's no memory corruption, no chance for privilege escalation, and no information leaks involved. So, it's not a code execution vector.
Finally, while a remote attacker might potentially try to start a channel switch by sending a CSA frame, they can't force the interface to shut down or be destroyed to trigger the leak. It's not remotely exploitable.
|
| 107/1 |
2026/08/19 17:22 |
action |
format-explanation |
0m
Results: map[Explanation:Based on the analysis of the bug report and the kernel source code, here is the
assessment of the vulnerability:
**Root Cause Analysis:**
The bug is a memory leak of a `struct mesh_csa_settings` object. When a channel
switch is initiated on a mesh interface (e.g., via the
`NL80211_CMD_CHANNEL_SWITCH` netlink command), `ieee80211_mesh_csa_beacon()` is
called. This function allocates a new `mesh_csa_settings` object and assigns it
to `sdata->u.mesh.csa` (`ifmsh->csa`).
Under normal circumstances, when the channel switch completes,
`ieee80211_mesh_finish_csa()` is called, which properly frees `ifmsh->csa`.
However, if the mesh interface is stopped or destroyed (e.g., by bringing the
interface down or destroying the network namespace) while the channel switch is
still active, the cleanup routines (`ieee80211_do_stop()`,
`ieee80211_stop_mesh()`, and `ieee80211_mesh_teardown_sdata()`) fail to free the
pending `ifmsh->csa` pointer. This results in the memory leak reported by
kmemleak.
**Exploitability:**
This is a pure memory leak. While an attacker could repeatedly trigger this to
exhaust system memory (leading to an Out-Of-Memory condition and system
instability), it does not lead to memory corruption (like use-after-free or
out-of-bounds access), privilege escalation, or information leaks. Therefore, it
is classified as a Denial of Service (DoS) but not Exploitable for code
execution.
**Privilege Requirements:**
To trigger this bug, a user must be able to issue `NL80211_CMD_JOIN_MESH` and
`NL80211_CMD_CHANNEL_SWITCH` commands, and subsequently bring down or destroy
the interface. In the `mac80211` netlink policy (`nl80211_small_ops`), these
commands are flagged with `GENL_UNS_ADMIN_PERM`. This means they require the
`CAP_NET_ADMIN` capability.
- **Unprivileged Processes:** Cannot trigger the bug because they lack
`CAP_NET_ADMIN`.
- **User Namespaces:** Can trigger the bug, because `GENL_UNS_ADMIN_PERM` allows
the commands to be executed if the process has `CAP_NET_ADMIN` within its own
user/network namespace.
**Remote/Peripheral Triggers:**
While a remote attacker could potentially send a Channel Switch Announcement
(CSA) management frame over the air to initiate a channel switch on a victim's
mesh node, they cannot remotely force the victim's interface to be stopped or
destroyed to actually trigger the memory leak. Thus, it is not considered
remotely triggerable. It also does not involve malicious filesystems or
untrusted physical peripherals.]
|