mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Joas Antonio dos Santos <joasantonio108@gmail.com>
To: Alexander Aring <alex.aring@gmail.com>,
	Stefan Schmidt <stefan@datenfreihafen.org>,
	Miquel Raynal <miquel.raynal@bootlin.com>
Cc: David S. Miller <davem@davemloft.net>,
	Eric Dumazet <edumazet@kernel.org>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Simon Horman <horms@kernel.org>,
	syzbot+9ea34da5ca6100593c90@syzkaller.appspotmail.com,
	linux-wpan@vger.kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH net] ieee802154: reject ARPHRD_IEEE802154 devices without ieee802154_ptr
Date: Fri, 30 Oct 2026 16:25:42 -0300	[thread overview]
Message-ID: <179338834213.72059.10411262981778676981@gmail.com> (raw)

TUNSETLINK lets a TUN device change its link type to ARPHRD_IEEE802154
without it becoming a WPAN device: dev->ieee802154_ptr and dev->ml_priv
stay NULL.  The legacy 802.15.4 netlink code and the AF_IEEE802154
socket code only check dev->type before dereferencing them:

- ieee802154_llsec_dump_table() calls ieee802154_mlme_ops(dev)->llsec
  (the syzbot report below);
- ieee802154_dump_iface() and ieee802154_nl_get_dev() users such as
  IEEE802154_LIST_IFACE, which needs no privileges, go through
  ieee802154_nl_fill_iface() and dev->ieee802154_ptr->wpan_phy;
- ieee802154_del_iface() reads dev->ieee802154_ptr->wpan_phy;
- ieee802154_get_dev(), used by bind() and sendmsg() on any
  AF_IEEE802154 datagram socket, reads tmp->ieee802154_ptr->pan_id when
  looking up a short address, and dgram_sendmsg() and
  ieee802154_dgram_deliver() use dev->ieee802154_ptr of the device they
  picked by type.

Once such a TUN device exists in init_net, an unprivileged user can
crash the kernel with an IEEE802154_LIST_IFACE dump or by binding an
AF_IEEE802154 datagram socket to a short address:

  Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
  pc : ieee802154_nl_fill_iface.isra.0+0xf0/0x64c

  KASAN: null-ptr-deref in range [0x0000000000000038-0x000000000000003f]
  pc : ieee802154_get_dev+0x2b8/0x478

Reject devices without ieee802154_ptr wherever a device is picked by
its type, as was done for lowpan_newlink() in commit bf79662bc85e
("ieee802154: 6lowpan: fix NULL dereference in lowpan_newlink").

The bug was reported by syzbot; the other paths were found by
LLM-assisted review of the same pattern and confirmed with a test that
sets up the TUN device as root and then triggers them as uid 65534.

Fixes: 3e9c156e2c21 ("ieee802154: add netlink interfaces for llsec")
Reported-by: syzbot+9ea34da5ca6100593c90@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=9ea34da5ca6100593c90
Cc: stable@vger.kernel.org
Signed-off-by: Joas Antonio dos Santos <joasantonio108@gmail.com>
Assisted-by: Yaga Agent HackerSec Claude:claude-opus-5-5
---
Tested on arm64 QEMU with KASAN (net/main 94cea342e891, mac802154_hwsim
loaded): a TUN device set to ARPHRD_IEEE802154 by root, then
- LLSEC_LIST_KEY dump as root: NULL deref in ieee802154_llsec_dump_table()
  without the patch, normal dump with it;
- LIST_IFACE dump as uid 65534: NULL deref in ieee802154_nl_fill_iface()
  without the patch, lists the hwsim interfaces with it;
- bind() of an AF_IEEE802154 datagram socket to a short address as uid
  65534: NULL deref in ieee802154_get_dev() without the patch, -ENODEV
  with it;
- sendto() on an unbound datagram socket keeps working (it picks a hwsim
  interface).

 net/ieee802154/nl-mac.c |  8 +++++---
 net/ieee802154/nl-phy.c |  2 +-
 net/ieee802154/socket.c | 18 ++++++++++++++++--
 3 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c
index 74ef0a310..5bf6725eb 100644
--- a/net/ieee802154/nl-mac.c
+++ b/net/ieee802154/nl-mac.c
@@ -162,7 +162,7 @@ static struct net_device *ieee802154_nl_get_dev(struct genl_info *info)
 	if (!dev)
 		return NULL;
 
-	if (dev->type != ARPHRD_IEEE802154) {
+	if (dev->type != ARPHRD_IEEE802154 || !dev->ieee802154_ptr) {
 		dev_put(dev);
 		return NULL;
 	}
@@ -437,7 +437,8 @@ int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb)
 
 	idx = 0;
 	for_each_netdev(net, dev) {
-		if (idx < s_idx || dev->type != ARPHRD_IEEE802154)
+		if (idx < s_idx || dev->type != ARPHRD_IEEE802154 ||
+		    !dev->ieee802154_ptr)
 			goto cont;
 
 		if (ieee802154_nl_fill_iface(skb, NETLINK_CB(cb->skb).portid,
@@ -771,7 +772,8 @@ ieee802154_llsec_dump_table(struct sk_buff *skb, struct netlink_callback *cb,
 	int rc;
 
 	for_each_netdev(net, dev) {
-		if (idx < first_dev || dev->type != ARPHRD_IEEE802154)
+		if (idx < first_dev || dev->type != ARPHRD_IEEE802154 ||
+		    !dev->ieee802154_ptr)
 			goto skip;
 
 		data.ops = ieee802154_mlme_ops(dev);
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index 4c07a475c..39aaa9745 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -284,7 +284,7 @@ int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info)
 	dev = dev_get_by_name(genl_info_net(info), name);
 	if (!dev)
 		return rc;
-	if (dev->type != ARPHRD_IEEE802154)
+	if (dev->type != ARPHRD_IEEE802154 || !dev->ieee802154_ptr)
 		goto out;
 
 	phy = dev->ieee802154_ptr->wpan_phy;
diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c
index be8ca1f05..f87c9ccbc 100644
--- a/net/ieee802154/socket.c
+++ b/net/ieee802154/socket.c
@@ -53,7 +53,8 @@ ieee802154_get_dev(struct net *net, const struct ieee802154_addr *addr)
 		rtnl_lock();
 
 		for_each_netdev(net, tmp) {
-			if (tmp->type != ARPHRD_IEEE802154)
+			if (tmp->type != ARPHRD_IEEE802154 ||
+			    !tmp->ieee802154_ptr)
 				continue;
 
 			pan_id = tmp->ieee802154_ptr->pan_id;
@@ -74,6 +75,14 @@ ieee802154_get_dev(struct net *net, const struct ieee802154_addr *addr)
 		break;
 	}
 
+	/* A TUN device can have its type set to ARPHRD_IEEE802154 without
+	 * being a WPAN device.
+	 */
+	if (dev && !dev->ieee802154_ptr) {
+		dev_put(dev);
+		dev = NULL;
+	}
+
 	return dev;
 }
 
@@ -641,6 +650,11 @@ static int dgram_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
 	else
 		dev = ieee802154_get_dev(sock_net(sk), &ro->src_addr);
 
+	if (dev && !dev->ieee802154_ptr) {
+		dev_put(dev);
+		dev = NULL;
+	}
+
 	if (!dev) {
 		pr_debug("no dev\n");
 		err = -ENXIO;
@@ -1097,7 +1111,7 @@ static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev,
 
 	ieee802154_raw_deliver(dev, skb);
 
-	if (dev->type != ARPHRD_IEEE802154)
+	if (dev->type != ARPHRD_IEEE802154 || !dev->ieee802154_ptr)
 		goto drop;
 
 	if (skb->pkt_type != PACKET_OTHERHOST)
-- 
2.43.0


             reply	other threads:[~2026-10-30 19:25 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-30 19:25 Joas Antonio dos Santos [this message]
2026-11-03 19:38 ` netdev-bot+sashiko

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=179338834213.72059.10411262981778676981@gmail.com \
    --to=joasantonio108@gmail.com \
    --cc=alex.aring@gmail.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@kernel.org \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.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=syzbot+9ea34da5ca6100593c90@syzkaller.appspotmail.com \
    /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

all inboxes | Powered by JetHome®