Merge tag 'ieee802154-for-net-next-2026-06-20' of git://git.kernel.org/pub/scm/linux/kernel/git/wpan/wpan-next

Stefan Schmidt says:

====================
pull-request: ieee802154-next 2026-06-20

An overdue pull request for ieee802154, catching up on all the AI found issues
at last.

Shitalkumar Gandhi fixed problems in the ca8210 driver for cases where we could
have a leak or a pointer truncation.

Robertus Diawan Chris made sure we do not overwrite the return code when
associating.

Michael Bommarito worked on properly gating our netlink API use in the llsec
security context.

Ivan Abramov cleaned up the netns cases as he did in other subsystems.

Doruk Tan Ozturk ensures we have the correct skn ready in cryptoo operation (to
avoid a  silent overwrite).

Aleksandr Nogikh fixed a kernel-infoleak detected by syzbot.

* tag 'ieee802154-for-net-next-2026-06-20' of git://git.kernel.org/pub/scm/linux/kernel/git/wpan/wpan-next:
  ieee802154: allow legacy LLSEC ADD/DEL ops to pass strict validation
  ieee802154: admin-gate legacy LLSEC dump operations
  mac802154: Prevent overwrite return code in mac802154_perform_association()
  ieee802154: fix kernel-infoleak in dgram_recvmsg()
  mac802154: llsec: add skb_cow_data() before in-place crypto
  ieee802154: ca8210: fix pointer truncation in kfifo on 64-bit
  ieee802154: ca8210: fix cas_ctl leak on spi_async failure
  ieee802154: Remove WARN_ON() in cfg802154_pernet_exit()
  ieee802154: Avoid calling WARN_ON() on -ENOMEM in cfg802154_switch_netns()
  ieee802154: Restore initial state on failed device_rename() in cfg802154_switch_netns()
====================

Link: https://patch.msgid.link/20260620174903.1010671-1-stefan@datenfreihafen.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-06-21 14:55:41 -07:00
commit 617fb6fa9c
7 changed files with 90 additions and 45 deletions

View File

@ -595,7 +595,7 @@ static int ca8210_test_int_driver_write(
fifo_buffer = kmemdup(buf, len, GFP_KERNEL);
if (!fifo_buffer)
return -ENOMEM;
kfifo_in(&test->up_fifo, &fifo_buffer, 4);
kfifo_in(&test->up_fifo, &fifo_buffer, sizeof(fifo_buffer));
wake_up_interruptible(&priv->test.readq);
return 0;
@ -919,9 +919,10 @@ static int ca8210_spi_transfer(
if (status < 0) {
dev_crit(
&spi->dev,
"status %d from spi_sync in write\n",
"status %d from spi_async in write\n",
status
);
kfree(cas_ctl);
}
return status;
@ -2525,6 +2526,7 @@ static ssize_t ca8210_test_int_user_read(
struct ca8210_priv *priv = filp->private_data;
unsigned char *fifo_buffer;
unsigned long bytes_not_copied;
unsigned int copied;
if (filp->f_flags & O_NONBLOCK) {
/* Non-blocking mode */
@ -2538,7 +2540,8 @@ static ssize_t ca8210_test_int_user_read(
);
}
if (kfifo_out(&priv->test.up_fifo, &fifo_buffer, 4) != 4) {
copied = kfifo_out(&priv->test.up_fifo, &fifo_buffer, sizeof(fifo_buffer));
if (copied != sizeof(fifo_buffer)) {
dev_err(
&priv->spi->dev,
"test_interface: Wrong number of elements popped from upstream fifo\n"

View File

@ -228,36 +228,43 @@ int cfg802154_switch_netns(struct cfg802154_registered_device *rdev,
continue;
wpan_dev->netdev->netns_immutable = false;
err = dev_change_net_namespace(wpan_dev->netdev, net, "wpan%d");
if (err)
if (err) {
WARN_ON(err && err != -ENOMEM);
break;
}
wpan_dev->netdev->netns_immutable = true;
}
if (err) {
/* failed -- clean up to old netns */
net = wpan_phy_net(&rdev->wpan_phy);
if (err)
goto errout;
list_for_each_entry_continue_reverse(wpan_dev,
&rdev->wpan_dev_list,
list) {
if (!wpan_dev->netdev)
continue;
wpan_dev->netdev->netns_immutable = false;
err = dev_change_net_namespace(wpan_dev->netdev, net,
"wpan%d");
WARN_ON(err);
wpan_dev->netdev->netns_immutable = true;
}
err = device_rename(&rdev->wpan_phy.dev, dev_name(&rdev->wpan_phy.dev));
WARN_ON(err && err != -ENOMEM);
return err;
}
if (err)
goto errout;
wpan_phy_net_set(&rdev->wpan_phy, net);
err = device_rename(&rdev->wpan_phy.dev, dev_name(&rdev->wpan_phy.dev));
WARN_ON(err);
return 0;
errout:
/* failed -- clean up to old netns */
net = wpan_phy_net(&rdev->wpan_phy);
list_for_each_entry_continue_reverse(wpan_dev,
&rdev->wpan_dev_list,
list) {
if (!wpan_dev->netdev)
continue;
wpan_dev->netdev->netns_immutable = false;
err = dev_change_net_namespace(wpan_dev->netdev, net,
"wpan%d");
WARN_ON(err && err != -ENOMEM);
wpan_dev->netdev->netns_immutable = true;
}
return err;
}
void cfg802154_dev_free(struct cfg802154_registered_device *rdev)
@ -351,7 +358,7 @@ static void __net_exit cfg802154_pernet_exit(struct net *net)
rtnl_lock();
list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
if (net_eq(wpan_phy_net(&rdev->wpan_phy), net))
WARN_ON(cfg802154_switch_netns(rdev, &init_net));
cfg802154_switch_netns(rdev, &init_net);
}
rtnl_unlock();
}

View File

@ -173,10 +173,13 @@ ieee802154_hdr_get_addr(const u8 *buf, int mode, bool omit_pan,
{
int pos = 0;
addr->mode = mode;
if (mode == IEEE802154_ADDR_NONE)
if (mode == IEEE802154_ADDR_NONE) {
memset(addr, 0, sizeof(*addr));
addr->mode = IEEE802154_ADDR_NONE;
return 0;
}
addr->mode = mode;
if (!omit_pan) {
memcpy(&addr->pan_id, buf + pos, 2);

View File

@ -16,6 +16,15 @@ void ieee802154_nl_exit(void);
.flags = GENL_ADMIN_PERM, \
}
#define IEEE802154_OP_RELAXED(_cmd, _func) \
{ \
.cmd = _cmd, \
.doit = _func, \
.dumpit = NULL, \
.flags = GENL_ADMIN_PERM, \
.validate = GENL_DONT_VALIDATE_STRICT,\
}
#define IEEE802154_DUMP(_cmd, _func, _dump) \
{ \
.cmd = _cmd, \
@ -23,6 +32,14 @@ void ieee802154_nl_exit(void);
.dumpit = _dump, \
}
#define IEEE802154_DUMP_PRIV(_cmd, _func, _dump) \
{ \
.cmd = _cmd, \
.doit = _func, \
.dumpit = _dump, \
.flags = GENL_ADMIN_PERM, \
}
struct genl_info;
struct sk_buff *ieee802154_nl_create(int flags, u8 req);

View File

@ -98,24 +98,24 @@ static const struct genl_small_ops ieee802154_ops[] = {
IEEE802154_OP(IEEE802154_SET_MACPARAMS, ieee802154_set_macparams),
IEEE802154_OP(IEEE802154_LLSEC_GETPARAMS, ieee802154_llsec_getparams),
IEEE802154_OP(IEEE802154_LLSEC_SETPARAMS, ieee802154_llsec_setparams),
IEEE802154_DUMP(IEEE802154_LLSEC_LIST_KEY, NULL,
ieee802154_llsec_dump_keys),
IEEE802154_OP(IEEE802154_LLSEC_ADD_KEY, ieee802154_llsec_add_key),
IEEE802154_OP(IEEE802154_LLSEC_DEL_KEY, ieee802154_llsec_del_key),
IEEE802154_DUMP(IEEE802154_LLSEC_LIST_DEV, NULL,
ieee802154_llsec_dump_devs),
IEEE802154_OP(IEEE802154_LLSEC_ADD_DEV, ieee802154_llsec_add_dev),
IEEE802154_OP(IEEE802154_LLSEC_DEL_DEV, ieee802154_llsec_del_dev),
IEEE802154_DUMP(IEEE802154_LLSEC_LIST_DEVKEY, NULL,
ieee802154_llsec_dump_devkeys),
IEEE802154_OP(IEEE802154_LLSEC_ADD_DEVKEY, ieee802154_llsec_add_devkey),
IEEE802154_OP(IEEE802154_LLSEC_DEL_DEVKEY, ieee802154_llsec_del_devkey),
IEEE802154_DUMP(IEEE802154_LLSEC_LIST_SECLEVEL, NULL,
ieee802154_llsec_dump_seclevels),
IEEE802154_OP(IEEE802154_LLSEC_ADD_SECLEVEL,
ieee802154_llsec_add_seclevel),
IEEE802154_OP(IEEE802154_LLSEC_DEL_SECLEVEL,
ieee802154_llsec_del_seclevel),
IEEE802154_DUMP_PRIV(IEEE802154_LLSEC_LIST_KEY, NULL,
ieee802154_llsec_dump_keys),
IEEE802154_OP_RELAXED(IEEE802154_LLSEC_ADD_KEY, ieee802154_llsec_add_key),
IEEE802154_OP_RELAXED(IEEE802154_LLSEC_DEL_KEY, ieee802154_llsec_del_key),
IEEE802154_DUMP_PRIV(IEEE802154_LLSEC_LIST_DEV, NULL,
ieee802154_llsec_dump_devs),
IEEE802154_OP_RELAXED(IEEE802154_LLSEC_ADD_DEV, ieee802154_llsec_add_dev),
IEEE802154_OP_RELAXED(IEEE802154_LLSEC_DEL_DEV, ieee802154_llsec_del_dev),
IEEE802154_DUMP_PRIV(IEEE802154_LLSEC_LIST_DEVKEY, NULL,
ieee802154_llsec_dump_devkeys),
IEEE802154_OP_RELAXED(IEEE802154_LLSEC_ADD_DEVKEY, ieee802154_llsec_add_devkey),
IEEE802154_OP_RELAXED(IEEE802154_LLSEC_DEL_DEVKEY, ieee802154_llsec_del_devkey),
IEEE802154_DUMP_PRIV(IEEE802154_LLSEC_LIST_SECLEVEL, NULL,
ieee802154_llsec_dump_seclevels),
IEEE802154_OP_RELAXED(IEEE802154_LLSEC_ADD_SECLEVEL,
ieee802154_llsec_add_seclevel),
IEEE802154_OP_RELAXED(IEEE802154_LLSEC_DEL_SECLEVEL,
ieee802154_llsec_del_seclevel),
};
static const struct genl_multicast_group ieee802154_mcgrps[] = {

View File

@ -710,6 +710,7 @@ int mac802154_llsec_encrypt(struct mac802154_llsec *sec, struct sk_buff *skb)
{
struct ieee802154_hdr hdr;
int rc, authlen, hlen;
struct sk_buff *trailer;
struct mac802154_llsec_key *key;
u32 frame_ctr;
@ -769,6 +770,12 @@ int mac802154_llsec_encrypt(struct mac802154_llsec *sec, struct sk_buff *skb)
skb->mac_len = ieee802154_hdr_push(skb, &hdr);
skb_reset_mac_header(skb);
rc = skb_cow_data(skb, 0, &trailer);
if (rc < 0) {
llsec_key_put(key);
return rc;
}
rc = llsec_do_encrypt(skb, sec, &hdr, key);
llsec_key_put(key);
@ -908,6 +915,13 @@ llsec_do_decrypt(struct sk_buff *skb, const struct mac802154_llsec *sec,
const struct ieee802154_hdr *hdr,
struct mac802154_llsec_key *key, __le64 dev_addr)
{
struct sk_buff *trailer;
int err;
err = skb_cow_data(skb, 0, &trailer);
if (err < 0)
return err;
if (hdr->sec.level == IEEE802154_SCF_SECLEVEL_ENC)
return llsec_do_decrypt_unauth(skb, sec, hdr, key, dev_addr);
else

View File

@ -594,6 +594,7 @@ int mac802154_perform_association(struct ieee802154_sub_if_data *sdata,
"Negative ASSOC RESP received from %8phC: %s\n", &ceaddr,
local->assoc_status == IEEE802154_PAN_AT_CAPACITY ?
"PAN at capacity" : "access denied");
goto clear_assoc;
}
ret = 0;