Netdev List
 help / color / mirror / Atom feed
From: Michael Bommarito <michael.bommarito@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@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Simon Horman <horms@kernel.org>,
	Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>,
	linux-wpan@vger.kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH net 0/2] ieee802154: admin-gate legacy LLSEC dumps + un-deaden ADD/DEL
Date: Wed, 20 May 2026 10:16:38 -0400	[thread overview]
Message-ID: <20260520141640.1149513-1-michael.bommarito@gmail.com> (raw)

The legacy IEEE802154_NL family (net/ieee802154/netlink.c) builds its
ops table from two macros in net/ieee802154/ieee802154.h. IEEE802154_OP()
sets .flags = GENL_ADMIN_PERM; IEEE802154_DUMP() sets no flags. Among
the IEEE802154_DUMP() consumers are four LLSEC dump ops (LIST_KEY,
LIST_DEV, LIST_DEVKEY, LIST_SECLEVEL), and the LLSEC_LIST_KEY dump
handler at net/ieee802154/nl-mac.c emits the raw 16-byte AES-128
keytable bytes (IEEE802154_ATTR_LLSEC_KEY_BYTES, .len = 16, copied
verbatim from struct ieee802154_llsec_key.key) into the reply skb.
The modern nl802154 family admin-gates the equivalent reads
(NL802154_CMD_GET_SEC_KEY at net/ieee802154/nl802154.c:2978 with
.flags = GENL_ADMIN_PERM) so the legacy interface is the open side.

Any local uid with no capabilities can dump the AES-128 LLSEC keytable
of any wpan netdev that has an administrator-installed key. 802.15.4
LLSEC uses CCM*, so the same key authenticates and encrypts frames at
the chosen security level. One key leak compromises confidentiality
and authenticity at the link layer.

Patches:

  1/2 ieee802154: admin-gate legacy LLSEC dump operations
      Introduce IEEE802154_DUMP_PRIV() mirroring IEEE802154_DUMP() but
      with .flags = GENL_ADMIN_PERM. Switch the four LLSEC dump ops to
      it. LIST_PHY and LIST_IFACE keep IEEE802154_DUMP() because the
      modern nl802154 family exposes their equivalents to unprivileged
      readers by design.

  2/2 ieee802154: allow legacy LLSEC ADD/DEL ops to pass strict validation
      While reproducing the dump leak the LLSEC ADD/DEL doit handlers
      turned out to have been silently dead since strict netlink
      validation became the default: IEEE802154_ATTR_LLSEC_KEY_BYTES
      and _KEY_USAGE_COMMANDS are declared as NLA_UNSPEC in
      nl_policy.c, which validate_nla() rejects under
      NL_VALIDATE_STRICT. Add IEEE802154_OP_RELAXED() with
      .validate = GENL_DONT_VALIDATE_STRICT and switch the eight LLSEC
      mutate ops to it. The dump ops keep strict validation; their
      gate from patch 1/2 stands.

This would be a good time to revisit this thread from Alexander Aring:
https://lore.kernel.org/r/20160725121450.4093-4-aar@pengutronix.de

Ten years later the legacy interface is still in mainline and
(per patch 2/2) silently dead on the doit side anyway. Maintainers
who prefer to revive that deletion series should NACK patch 2/2 and
pick patch 1/2 alone; patch 1/2 plugs the key leak whether the
legacy doit path is ever brought back to life or removed entirely.

Reproduction
============

Tree: mainline 7.1-rc2 (22be7671cc3497f68d14555285c0ac221597c8eb),
x86 UML, KASAN off. Conditions: CONFIG_IEEE802154=y, CONFIG_MAC802154=y,
CONFIG_IEEE802154_HWSIM=y; one wpan netdev exists; an administrator
has installed an LLSEC key on it.

Harness: a userspace C program opens AF_NETLINK / NETLINK_GENERIC,
resolves the "802.15.4 MAC" family, and issues a CTRL_CMD_GETFAMILY
followed by a IEEE802154_LLSEC_LIST_KEY dump on wpan0. The dump
response is parsed for IEEE802154_ATTR_LLSEC_KEY_BYTES nested
attributes and the 16-byte payload is hex-printed. The runner drops
privileges to uid=1000 via setpriv with --bounding-set=-all and
--inh-caps=-all before invoking the dump.

For patch 2/2, the same harness shape sends a IEEE802154_LLSEC_ADD_KEY
request with policy-conformant attributes (frame counter, key ID
mode, key bytes, usage frame types) as root. The harness measures
whether the doit handler is reached (ieee802154_llsec_add_key()
return code visible via the netlink ack) or the dispatcher rejects
the request at the validate phase.

Stock vs patched outcomes (per patch):

  1/2: stock dump returns the installed AES-128 key bytes
       byte-identical to the unprivileged dumper; patched returns
       -EPERM at the generic-netlink dispatch.

  2/2: stock LLSEC_ADD_KEY as root returns "Unsupported attribute"
       from __nla_validate_parse(); patched reaches
       ieee802154_llsec_add_key() and installs the key.

Regression-adjacent runs (per patch):

  1/2: LIST_PHY and LIST_IFACE dumps continue to succeed from an
       unprivileged uid post-patch, mirroring the modern
       NL802154_CMD_GET_WPAN_PHY and NL802154_CMD_GET_INTERFACE
       behavior.

  2/2: modern nl802154 NL802154_CMD_NEW_SEC_KEY (which is admin-
       gated and uses NLA_NESTED policy entries, not NLA_UNSPEC)
       continues to install keys unchanged.

Mitigations: a system administrator unwilling to ship patch 1/2
can mitigate the leak by building the kernel without
CONFIG_IEEE802154 or by ensuring no LLSEC key is installed on
any wpan netdev. There is no per-process mitigation.

Selftest gate: tools/testing/selftests/ has no matching binary
for the legacy IEEE802154_NL interface.

The trigger harness sources are available off-list on request.

Scope notes:

  - The dump handler reuses the same struct ieee802154_llsec_key
    storage as the modern nl802154 NEW_SEC_KEY path. Both interfaces
    expose the same backing keytable; gating only the legacy dump is
    the minimal fix.
  - The two new macros sit alongside the existing two; no existing
    callers change beyond the four LIST_LLSEC* lines (patch 1/2)
    and the eight LLSEC ADD/DEL lines (patch 2/2).

Michael Bommarito (2):
  ieee802154: admin-gate legacy LLSEC dump operations
  ieee802154: allow legacy LLSEC ADD/DEL ops to pass strict validation

 net/ieee802154/ieee802154.h | 17 +++++++++++++++++
 net/ieee802154/netlink.c    | 36 ++++++++++++++++++------------------
 2 files changed, 35 insertions(+), 18 deletions(-)


base-commit: 22be7671cc3497f68d14555285c0ac221597c8eb
--
2.53.0


             reply	other threads:[~2026-05-20 14:16 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-20 14:16 Michael Bommarito [this message]
2026-05-20 14:16 ` [PATCH net 1/2] ieee802154: admin-gate legacy LLSEC dump operations Michael Bommarito
2026-05-20 14:16 ` [PATCH net 2/2] ieee802154: allow legacy LLSEC ADD/DEL ops to pass strict validation Michael Bommarito

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=20260520141640.1149513-1-michael.bommarito@gmail.com \
    --to=michael.bommarito@gmail.com \
    --cc=alex.aring@gmail.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --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=phoebe.buckheister@itwm.fraunhofer.de \
    --cc=stefan@datenfreihafen.org \
    /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