* [PATCH v3 0/2] wifi: nl80211: tighten netns handling in SET_WIPHY_NETNS and dump continuation
@ 2026-05-06 6:48 Maoyi Xie
2026-05-06 6:48 ` [PATCH v3 1/2] wifi: nl80211: require CAP_NET_ADMIN over the target netns in SET_WIPHY_NETNS Maoyi Xie
2026-05-06 6:48 ` [PATCH v3 2/2] wifi: nl80211: re-check wiphy netns in nl80211_prepare_wdev_dump() continuation Maoyi Xie
0 siblings, 2 replies; 3+ messages in thread
From: Maoyi Xie @ 2026-05-06 6:48 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, linux-kernel, Maoyi Xie
From: Maoyi Xie <maoyi.xie@ntu.edu.sg>
This series addresses two related namespace handling gaps in
nl80211 that came up during a recent inquiry on the list. Both
follow the netdev convention.
Patch 1/2: NL80211_CMD_SET_WIPHY_NETNS uses GENL_UNS_ADMIN_PERM,
which only checks CAP_NET_ADMIN over the source netns. The target
netns selected via NL80211_ATTR_NETNS_FD or NL80211_ATTR_PID is
not checked. Mirror the rtnetlink convention spelled out by
rtnl_get_net_ns_capable() and require ns_capable(target_net->user_ns,
CAP_NET_ADMIN) on the resolved target netns. Reachable from an
unprivileged user namespace whenever the caller already holds a
WIPHY_FLAG_NETNS_OK wiphy in their own netns (mac80211_hwsim, or
an admin-delegated container scenario). PoC reproduces on a KASAN
VM with mac80211_hwsim and shows the call now returns -EPERM.
Patch 2/2: nl80211_prepare_wdev_dump() validates the wdev's netns
on the first dumpit invocation but not on subsequent ones, where
it looks up the wiphy by global index. If the wiphy moves netns
between dumpit invocations (via SET_WIPHY_NETNS), the dump silently
keeps copying BSS list contents from the wiphy's new netns into
the caller's netns. Add a net_eq() check on the continuation path
so the dump terminates cleanly. This is mostly a clarity and
convention fix. Combined with 1/2 it also closes the path by
which an unprivileged-userns caller could trigger the race
themselves.
Changes since v2:
Both patches: dropped the Reported-by trailer that pointed to
the same address as Signed-off-by, per Johannes's review.
Both patches: added an explicit From: line at the top of the
commit body so the email header From and the Signed-off-by
trailer match the patch author, addressing the bot warning
Johannes flagged on v2 1/2.
No code changes since v2.
Changes since v1:
Patch 2/2: trimmed the comment per Johannes's review. The
comment now describes the invariant being protected (wiphy
may move between dumpit invocations) rather than referencing
other dump callers as motivation.
Patch 1/2: unchanged.
Maoyi Xie (2):
wifi: nl80211: require CAP_NET_ADMIN over the target netns in
SET_WIPHY_NETNS
wifi: nl80211: re-check wiphy netns in nl80211_prepare_wdev_dump()
continuation
net/wireless/nl80211.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
base-commit: 65493f27a6008bf84bd11bd41c5e1ea6b0bf3c3d
--
2.34.1
^ permalink raw reply [flat|nested] 3+ messages in thread* [PATCH v3 1/2] wifi: nl80211: require CAP_NET_ADMIN over the target netns in SET_WIPHY_NETNS
2026-05-06 6:48 [PATCH v3 0/2] wifi: nl80211: tighten netns handling in SET_WIPHY_NETNS and dump continuation Maoyi Xie
@ 2026-05-06 6:48 ` Maoyi Xie
2026-05-06 6:48 ` [PATCH v3 2/2] wifi: nl80211: re-check wiphy netns in nl80211_prepare_wdev_dump() continuation Maoyi Xie
1 sibling, 0 replies; 3+ messages in thread
From: Maoyi Xie @ 2026-05-06 6:48 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, linux-kernel, Maoyi Xie
From: Maoyi Xie <maoyi.xie@ntu.edu.sg>
NL80211_CMD_SET_WIPHY_NETNS dispatches with GENL_UNS_ADMIN_PERM, which
verifies that the caller has CAP_NET_ADMIN over the user namespace
owning the source netns (the netlink socket's netns). It does not
verify that the caller has CAP_NET_ADMIN over the target netns
selected by NL80211_ATTR_NETNS_FD or NL80211_ATTR_PID.
This diverges from the convention enforced in
net/core/rtnetlink.c::rtnl_get_net_ns_capable():
/* For now, the caller is required to have CAP_NET_ADMIN in
* the user namespace owning the target net ns.
*/
if (!sk_ns_capable(sk, net->user_ns, CAP_NET_ADMIN))
return ERR_PTR(-EACCES);
A user with CAP_NET_ADMIN in their own user namespace can therefore
push a wiphy into an arbitrary netns (including init_net) over which
they have no privilege.
Reachable from an unprivileged user namespace as soon as the caller
holds, in their own netns, a wiphy that has WIPHY_FLAG_NETNS_OK set
(true for mac80211_hwsim and for any wiphy that an administrator has
delegated into a container).
Reproducer (mac80211_hwsim, KASAN VM):
1. As real root, modprobe mac80211_hwsim radios=1 in init_net.
2. fork(); child unshare(CLONE_NEWUSER | CLONE_NEWNET) and writes
0-mapped uid_map.
3. Real root migrates phyN into the child's netns via
NL80211_CMD_SET_WIPHY_NETNS (legitimate admin step).
4. Child, with CAP_NET_ADMIN only in its own user_ns, sends
NL80211_CMD_SET_WIPHY_NETNS targeting init_net's netns fd.
5. The kernel honours the request and the wiphy is moved back
to init_net even though the caller has no privilege there.
Mirror the rtnetlink convention by requiring ns_capable(net->user_ns,
CAP_NET_ADMIN) on the resolved target netns before calling
cfg80211_switch_netns().
Signed-off-by: Maoyi Xie <maoyi.xie@ntu.edu.sg>
---
net/wireless/nl80211.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 67088804d..db546dd93 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -13867,6 +13867,19 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
if (IS_ERR(net))
return PTR_ERR(net);
+ /*
+ * The caller already has CAP_NET_ADMIN over the source netns
+ * (enforced by GENL_UNS_ADMIN_PERM on the genl op). Mirror the
+ * convention used by net/core/rtnetlink.c::rtnl_get_net_ns_capable()
+ * and require CAP_NET_ADMIN over the target netns as well, so that
+ * a caller that is privileged in their own user namespace cannot
+ * push a wiphy into a netns where they have no privilege.
+ */
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) {
+ put_net(net);
+ return -EPERM;
+ }
+
err = 0;
/* check if anything to do */
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH v3 2/2] wifi: nl80211: re-check wiphy netns in nl80211_prepare_wdev_dump() continuation
2026-05-06 6:48 [PATCH v3 0/2] wifi: nl80211: tighten netns handling in SET_WIPHY_NETNS and dump continuation Maoyi Xie
2026-05-06 6:48 ` [PATCH v3 1/2] wifi: nl80211: require CAP_NET_ADMIN over the target netns in SET_WIPHY_NETNS Maoyi Xie
@ 2026-05-06 6:48 ` Maoyi Xie
1 sibling, 0 replies; 3+ messages in thread
From: Maoyi Xie @ 2026-05-06 6:48 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, linux-kernel, Maoyi Xie
From: Maoyi Xie <maoyi.xie@ntu.edu.sg>
NL80211_CMD_GET_SCAN is implemented as a multi-call dumpit. The first
invocation of nl80211_prepare_wdev_dump() validates the requested wdev
against the caller's netns via __cfg80211_wdev_from_attrs(). Subsequent
invocations look up the same wiphy by global index via
wiphy_idx_to_wiphy() and do not re-check that the wiphy is still in
the caller's netns.
If the wiphy is moved between dumpit invocations (via
NL80211_CMD_SET_WIPHY_NETNS), the dump silently continues to copy BSS
list contents from the wiphy's new netns into the caller's netns
socket buffer. The other dump paths in nl80211.c (e.g.
nl80211_dump_wiphy() and the parallel scheduled scan dump) already
filter by net_eq(wiphy_net(...), sock_net(skb->sk)) on every iteration.
Add the same filter to the continuation path. If the wiphy's netns no
longer matches the caller's, return -ENODEV and the netlink dump
machinery terminates the walk cleanly.
This is most usefully fixed alongside the SET_WIPHY_NETNS target-cap
hardening in patch 1/2, which closes the path by which an
unprivileged-userns caller could trigger this race themselves.
Signed-off-by: Maoyi Xie <maoyi.xie@ntu.edu.sg>
---
net/wireless/nl80211.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index db546dd93..f2c91a939 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1276,6 +1276,16 @@ static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
rtnl_unlock();
return -ENODEV;
}
+ /*
+ * The first invocation validated the wdev's netns against
+ * the caller via __cfg80211_wdev_from_attrs(). The wiphy
+ * may have moved netns between dumpit invocations (via
+ * NL80211_CMD_SET_WIPHY_NETNS), so re-check here.
+ */
+ if (!net_eq(wiphy_net(wiphy), sock_net(cb->skb->sk))) {
+ rtnl_unlock();
+ return -ENODEV;
+ }
*rdev = wiphy_to_rdev(wiphy);
*wdev = NULL;
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-05-06 6:49 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-06 6:48 [PATCH v3 0/2] wifi: nl80211: tighten netns handling in SET_WIPHY_NETNS and dump continuation Maoyi Xie
2026-05-06 6:48 ` [PATCH v3 1/2] wifi: nl80211: require CAP_NET_ADMIN over the target netns in SET_WIPHY_NETNS Maoyi Xie
2026-05-06 6:48 ` [PATCH v3 2/2] wifi: nl80211: re-check wiphy netns in nl80211_prepare_wdev_dump() continuation Maoyi Xie
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox