mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH net v4 0/7] net: require CAP_NET_ADMIN in the device netns for tunnel changelink
@ 2026-06-09 16:31 Maoyi Xie
  2026-06-09 16:31 ` [PATCH net v4 1/7] net: ip_gre: require CAP_NET_ADMIN in the device netns for changelink Maoyi Xie
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Maoyi Xie @ 2026-06-09 16:31 UTC (permalink / raw)
  To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: David Ahern, Kuniyuki Iwashima, Xiao Liang, Steffen Klassert,
	Herbert Xu, Simon Horman, netdev, linux-kernel, stable

A tunnel changelink rewrites the tunnel in its creation netns. After an
IFLA_NET_NS_FD migration that creation netns is not the caller's. The
rtnl changelink path only checks CAP_NET_ADMIN against the caller's
netns, so a caller with caps only in its current netns can rewrite a
tunnel that lives in the creation netns, and it picks the endpoint
addresses. Commit 8b484efd5cb4 ("ip6: vti: Use ip6_tnl.net in
vti6_siocdevprivate().") added the same check on the ioctl path. This
series adds it on the RTM_NEWLINK path.

Each changelink is gated at the top of the op, before any attribute is
parsed, because the per-type parsers can update live tunnel fields first.
For example ipgre_netlink_parms() sets t->collect_md before
ip_tunnel_changelink() runs. The check is skipped when the creation netns
equals the device's current netns, where the rtnl path already checked
the cap.

This is the same fix as v3, restructured after Paolo's review:

 - Split into one patch per tunnel, each with its own Fixes tag.
 - Move the repeated check into a helper, net_admin_capable(), added in
   patch 1 and used by the rest of the series.

Tested on net/main. For every tunnel type in the series a migrated
fake-root changelink is rejected with EPERM. For vti6 SIOCGETTUNNEL
confirms the creation netns hash is left unchanged. Legit non-migrated
changelinks still succeed.

v3: https://lore.kernel.org/netdev/20260604125055.3254652-1-maoyixie.tju@gmail.com/
v2: https://lore.kernel.org/netdev/20260601034148.1272080-1-maoyixie.tju@gmail.com/
v1: https://lore.kernel.org/netdev/20260527070824.2677331-1-maoyixie.tju@gmail.com/

Maoyi Xie (7):
  net: ip_gre: require CAP_NET_ADMIN in the device netns for changelink
  net: ipip: require CAP_NET_ADMIN in the device netns for changelink
  net: ip_vti: require CAP_NET_ADMIN in the device netns for changelink
  net: ip6_tunnel: require CAP_NET_ADMIN in the device netns for
    changelink
  net: ip6_gre: require CAP_NET_ADMIN in the device netns for changelink
  net: ip6_vti: require CAP_NET_ADMIN in the device netns for changelink
  xfrm: xfrm_interface: require CAP_NET_ADMIN in the device netns for
    changelink

 include/net/net_namespace.h    | 18 ++++++++++++++++++
 net/ipv4/ip_gre.c              |  6 ++++++
 net/ipv4/ip_vti.c              |  3 +++
 net/ipv4/ipip.c                |  3 +++
 net/ipv6/ip6_gre.c             |  6 ++++++
 net/ipv6/ip6_tunnel.c          |  3 +++
 net/ipv6/ip6_vti.c             |  3 +++
 net/xfrm/xfrm_interface_core.c |  3 +++
 8 files changed, 45 insertions(+)


base-commit: 0aa05daef7848a5ac11158949dc73cd741995dc1
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net v4 1/7] net: ip_gre: require CAP_NET_ADMIN in the device netns for changelink
  2026-06-09 16:31 [PATCH net v4 0/7] net: require CAP_NET_ADMIN in the device netns for tunnel changelink Maoyi Xie
@ 2026-06-09 16:31 ` Maoyi Xie
  2026-06-11  5:25   ` Kuniyuki Iwashima
  2026-06-09 16:31 ` [PATCH net v4 2/7] net: ipip: " Maoyi Xie
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 9+ messages in thread
From: Maoyi Xie @ 2026-06-09 16:31 UTC (permalink / raw)
  To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: David Ahern, Kuniyuki Iwashima, Xiao Liang, Steffen Klassert,
	Herbert Xu, Simon Horman, netdev, linux-kernel, stable

A tunnel changelink rewrites the tunnel in its creation netns. After an
IFLA_NET_NS_FD migration that netns is not the caller's. The rtnl
changelink path only checks CAP_NET_ADMIN against the caller's netns. A
caller with caps only in its current netns can then rewrite a tunnel
that lives in another netns, and it picks the endpoint addresses.

Add net_admin_capable(). It requires CAP_NET_ADMIN in the tunnel's netns
and is skipped when that netns is the device's current netns, where the
rtnl path already checked the cap. The other patches in this series use
the same helper.

Gate ipgre_changelink() and erspan_changelink() with it. The check is at
the top of the op, before any attribute is parsed, because the parsers
update live tunnel fields first. ipgre_netlink_parms() sets
t->collect_md before ip_tunnel_changelink() runs.

Commit 8b484efd5cb4 ("ip6: vti: Use ip6_tnl.net in
vti6_siocdevprivate().") added the same check on the ioctl path. This
adds it on RTM_NEWLINK.

Reported-by: Xiao Liang <shaw.leon@gmail.com>
Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/
Fixes: d0f418516022 ("net, ip_tunnel: fix namespaces move")
Cc: stable@vger.kernel.org
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
---
 include/net/net_namespace.h | 18 ++++++++++++++++++
 net/ipv4/ip_gre.c           |  6 ++++++
 2 files changed, 24 insertions(+)

diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 80de5e98a66d..17fb71a78cb6 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -358,6 +358,24 @@ static inline bool net_initialized(const struct net *net)
 	return READ_ONCE(net->list.next);
 }
 
+/**
+ * net_admin_capable - test for CAP_NET_ADMIN over a network namespace
+ * @net: namespace whose state the operation would change
+ * @cur: namespace the operation runs in, e.g. dev_net(dev)
+ *
+ * Returns true when @net is @cur, where CAP_NET_ADMIN was already
+ * checked for the running namespace, or when the caller holds
+ * CAP_NET_ADMIN over @net. rtnl changelink paths use this: a device can
+ * be moved so its state lives in a namespace other than the one the
+ * request runs in, and the cap must then be held over that namespace.
+ */
+static inline bool net_admin_capable(const struct net *net,
+				     const struct net *cur)
+{
+	return net_eq(net, cur) ||
+	       ns_capable(net->user_ns, CAP_NET_ADMIN);
+}
+
 static inline void __netns_tracker_alloc(struct net *net,
 					 netns_tracker *tracker,
 					 bool refcounted,
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 169e2921a851..040a0ef95184 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -1457,6 +1457,9 @@ static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
 	__u32 fwmark = t->fwmark;
 	int err;
 
+	if (!net_admin_capable(t->net, dev_net(dev)))
+		return -EPERM;
+
 	err = ipgre_newlink_encap_setup(dev, data);
 	if (err)
 		return err;
@@ -1486,6 +1489,9 @@ static int erspan_changelink(struct net_device *dev, struct nlattr *tb[],
 	__u32 fwmark = t->fwmark;
 	int err;
 
+	if (!net_admin_capable(t->net, dev_net(dev)))
+		return -EPERM;
+
 	err = ipgre_newlink_encap_setup(dev, data);
 	if (err)
 		return err;
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net v4 2/7] net: ipip: require CAP_NET_ADMIN in the device netns for changelink
  2026-06-09 16:31 [PATCH net v4 0/7] net: require CAP_NET_ADMIN in the device netns for tunnel changelink Maoyi Xie
  2026-06-09 16:31 ` [PATCH net v4 1/7] net: ip_gre: require CAP_NET_ADMIN in the device netns for changelink Maoyi Xie
@ 2026-06-09 16:31 ` Maoyi Xie
  2026-06-09 16:31 ` [PATCH net v4 3/7] net: ip_vti: " Maoyi Xie
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Maoyi Xie @ 2026-06-09 16:31 UTC (permalink / raw)
  To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: David Ahern, Kuniyuki Iwashima, Xiao Liang, Steffen Klassert,
	Herbert Xu, Simon Horman, netdev, linux-kernel, stable

ipip_changelink() rewrites the tunnel in its creation netns. After an
IFLA_NET_NS_FD migration that netns is not the caller's, but the rtnl
changelink path only checks CAP_NET_ADMIN against the caller's netns. A
caller with caps only in its current netns can then rewrite a tunnel in
another netns and pick its endpoint addresses.

Gate the op on net_admin_capable() at its top, before any attribute is
parsed. The check is skipped when the tunnel netns is the device's
current netns, where the rtnl path already checked the cap.

Reported-by: Xiao Liang <shaw.leon@gmail.com>
Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/
Fixes: d0f418516022 ("net, ip_tunnel: fix namespaces move")
Cc: stable@vger.kernel.org
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
---
 net/ipv4/ipip.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index ff95b1b9908e..1813f6026e49 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -494,6 +494,9 @@ static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
 	bool collect_md;
 	__u32 fwmark = t->fwmark;
 
+	if (!net_admin_capable(t->net, dev_net(dev)))
+		return -EPERM;
+
 	if (ip_tunnel_netlink_encap_parms(data, &ipencap)) {
 		int err = ip_tunnel_encap_setup(t, &ipencap);
 
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net v4 3/7] net: ip_vti: require CAP_NET_ADMIN in the device netns for changelink
  2026-06-09 16:31 [PATCH net v4 0/7] net: require CAP_NET_ADMIN in the device netns for tunnel changelink Maoyi Xie
  2026-06-09 16:31 ` [PATCH net v4 1/7] net: ip_gre: require CAP_NET_ADMIN in the device netns for changelink Maoyi Xie
  2026-06-09 16:31 ` [PATCH net v4 2/7] net: ipip: " Maoyi Xie
@ 2026-06-09 16:31 ` Maoyi Xie
  2026-06-09 16:31 ` [PATCH net v4 4/7] net: ip6_tunnel: " Maoyi Xie
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Maoyi Xie @ 2026-06-09 16:31 UTC (permalink / raw)
  To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: David Ahern, Kuniyuki Iwashima, Xiao Liang, Steffen Klassert,
	Herbert Xu, Simon Horman, netdev, linux-kernel, stable

vti_changelink() rewrites the tunnel in its creation netns. After an
IFLA_NET_NS_FD migration that netns is not the caller's, but the rtnl
changelink path only checks CAP_NET_ADMIN against the caller's netns. A
caller with caps only in its current netns can then rewrite a tunnel in
another netns and pick its endpoint addresses.

Gate the op on net_admin_capable() at its top, before any attribute is
parsed. The check is skipped when the tunnel netns is the device's
current netns, where the rtnl path already checked the cap.

Reported-by: Xiao Liang <shaw.leon@gmail.com>
Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/
Fixes: d0f418516022 ("net, ip_tunnel: fix namespaces move")
Cc: stable@vger.kernel.org
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
---
 net/ipv4/ip_vti.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 95b6bb78fcd2..55ec52bc5db0 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -596,6 +596,9 @@ static int vti_changelink(struct net_device *dev, struct nlattr *tb[],
 	struct ip_tunnel_parm_kern p;
 	__u32 fwmark = t->fwmark;
 
+	if (!net_admin_capable(t->net, dev_net(dev)))
+		return -EPERM;
+
 	vti_netlink_parms(data, &p, &fwmark);
 	return ip_tunnel_changelink(dev, tb, &p, fwmark);
 }
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net v4 4/7] net: ip6_tunnel: require CAP_NET_ADMIN in the device netns for changelink
  2026-06-09 16:31 [PATCH net v4 0/7] net: require CAP_NET_ADMIN in the device netns for tunnel changelink Maoyi Xie
                   ` (2 preceding siblings ...)
  2026-06-09 16:31 ` [PATCH net v4 3/7] net: ip_vti: " Maoyi Xie
@ 2026-06-09 16:31 ` Maoyi Xie
  2026-06-09 16:31 ` [PATCH net v4 5/7] net: ip6_gre: " Maoyi Xie
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Maoyi Xie @ 2026-06-09 16:31 UTC (permalink / raw)
  To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: David Ahern, Kuniyuki Iwashima, Xiao Liang, Steffen Klassert,
	Herbert Xu, Simon Horman, netdev, linux-kernel, stable

ip6_tnl_changelink() rewrites the tunnel in its creation netns. After an
IFLA_NET_NS_FD migration that netns is not the caller's, but the rtnl
changelink path only checks CAP_NET_ADMIN against the caller's netns. A
caller with caps only in its current netns can then rewrite a tunnel in
another netns and pick its endpoint addresses.

Gate the op on net_admin_capable() at its top, before any attribute is
parsed. The check is skipped when the tunnel netns is the device's
current netns, where the rtnl path already checked the cap.

Reported-by: Xiao Liang <shaw.leon@gmail.com>
Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/
Fixes: 5311a69aaca3 ("net, ip6_tunnel: fix namespaces move")
Cc: stable@vger.kernel.org
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
---
 net/ipv6/ip6_tunnel.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 9d1037ac082f..5ff8e057fb1e 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -2102,6 +2102,9 @@ static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[],
 	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
 	struct ip_tunnel_encap ipencap;
 
+	if (!net_admin_capable(net, dev_net(dev)))
+		return -EPERM;
+
 	if (dev == ip6n->fb_tnl_dev) {
 		if (ip_tunnel_netlink_encap_parms(data, &ipencap)) {
 			/* iproute2 always sets TUNNEL_ENCAP_FLAG_CSUM6, so
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net v4 5/7] net: ip6_gre: require CAP_NET_ADMIN in the device netns for changelink
  2026-06-09 16:31 [PATCH net v4 0/7] net: require CAP_NET_ADMIN in the device netns for tunnel changelink Maoyi Xie
                   ` (3 preceding siblings ...)
  2026-06-09 16:31 ` [PATCH net v4 4/7] net: ip6_tunnel: " Maoyi Xie
@ 2026-06-09 16:31 ` Maoyi Xie
  2026-06-09 16:31 ` [PATCH net v4 6/7] net: ip6_vti: " Maoyi Xie
  2026-06-09 16:31 ` [PATCH net v4 7/7] xfrm: xfrm_interface: " Maoyi Xie
  6 siblings, 0 replies; 9+ messages in thread
From: Maoyi Xie @ 2026-06-09 16:31 UTC (permalink / raw)
  To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: David Ahern, Kuniyuki Iwashima, Xiao Liang, Steffen Klassert,
	Herbert Xu, Simon Horman, netdev, linux-kernel, stable

ip6gre_changelink() and ip6erspan_changelink() rewrite the tunnel in its
creation netns. After an IFLA_NET_NS_FD migration that netns is not the
caller's, but the rtnl changelink path only checks CAP_NET_ADMIN against
the caller's netns. A caller with caps only in its current netns can then
rewrite a tunnel in another netns and pick its endpoint addresses.

Gate both ops on net_admin_capable() at their top, before any attribute
is parsed. The check is skipped when the tunnel netns is the device's
current netns, where the rtnl path already checked the cap.

Reported-by: Xiao Liang <shaw.leon@gmail.com>
Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/
Fixes: 690afc165bb3 ("net: ip6_gre: fix moving ip6gre between namespaces")
Cc: stable@vger.kernel.org
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
---
 net/ipv6/ip6_gre.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 365b4059eb20..829388d7b870 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -2047,6 +2047,9 @@ static int ip6gre_changelink(struct net_device *dev, struct nlattr *tb[],
 	struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id);
 	struct __ip6_tnl_parm p;
 
+	if (!net_admin_capable(t->net, dev_net(dev)))
+		return -EPERM;
+
 	t = ip6gre_changelink_common(dev, tb, data, &p, extack);
 	if (IS_ERR(t))
 		return PTR_ERR(t);
@@ -2266,6 +2269,9 @@ static int ip6erspan_changelink(struct net_device *dev, struct nlattr *tb[],
 	struct __ip6_tnl_parm p;
 	struct ip6gre_net *ign;
 
+	if (!net_admin_capable(t->net, dev_net(dev)))
+		return -EPERM;
+
 	ign = net_generic(t->net, ip6gre_net_id);
 	t = ip6gre_changelink_common(dev, tb, data, &p, extack);
 	if (IS_ERR(t))
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net v4 6/7] net: ip6_vti: require CAP_NET_ADMIN in the device netns for changelink
  2026-06-09 16:31 [PATCH net v4 0/7] net: require CAP_NET_ADMIN in the device netns for tunnel changelink Maoyi Xie
                   ` (4 preceding siblings ...)
  2026-06-09 16:31 ` [PATCH net v4 5/7] net: ip6_gre: " Maoyi Xie
@ 2026-06-09 16:31 ` Maoyi Xie
  2026-06-09 16:31 ` [PATCH net v4 7/7] xfrm: xfrm_interface: " Maoyi Xie
  6 siblings, 0 replies; 9+ messages in thread
From: Maoyi Xie @ 2026-06-09 16:31 UTC (permalink / raw)
  To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: David Ahern, Kuniyuki Iwashima, Xiao Liang, Steffen Klassert,
	Herbert Xu, Simon Horman, netdev, linux-kernel, stable

vti6_changelink() rewrites the tunnel in its creation netns. After an
IFLA_NET_NS_FD migration that netns is not the caller's, but the rtnl
changelink path only checks CAP_NET_ADMIN against the caller's netns. A
caller with caps only in its current netns can then rewrite a tunnel in
another netns and pick its endpoint addresses.

Gate the op on net_admin_capable() at its top, before any attribute is
parsed. The check is skipped when the tunnel netns is the device's
current netns, where the rtnl path already checked the cap.

Reported-by: Xiao Liang <shaw.leon@gmail.com>
Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/
Fixes: 11b326fb0a37 ("ip6: vti: Use ip6_tnl.net in vti6_changelink().")
Cc: stable@vger.kernel.org
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
---
 net/ipv6/ip6_vti.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index df793c8bfffb..ec82626363f7 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -1044,6 +1044,9 @@ static int vti6_changelink(struct net_device *dev, struct nlattr *tb[],
 	struct __ip6_tnl_parm p;
 	struct vti6_net *ip6n;
 
+	if (!net_admin_capable(net, dev_net(dev)))
+		return -EPERM;
+
 	ip6n = net_generic(net, vti6_net_id);
 	if (dev == ip6n->fb_tnl_dev)
 		return -EINVAL;
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net v4 7/7] xfrm: xfrm_interface: require CAP_NET_ADMIN in the device netns for changelink
  2026-06-09 16:31 [PATCH net v4 0/7] net: require CAP_NET_ADMIN in the device netns for tunnel changelink Maoyi Xie
                   ` (5 preceding siblings ...)
  2026-06-09 16:31 ` [PATCH net v4 6/7] net: ip6_vti: " Maoyi Xie
@ 2026-06-09 16:31 ` Maoyi Xie
  6 siblings, 0 replies; 9+ messages in thread
From: Maoyi Xie @ 2026-06-09 16:31 UTC (permalink / raw)
  To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: David Ahern, Kuniyuki Iwashima, Xiao Liang, Steffen Klassert,
	Herbert Xu, Simon Horman, netdev, linux-kernel, stable

xfrmi_changelink() rewrites the interface in its creation netns. After an
IFLA_NET_NS_FD migration that netns is not the caller's, but the rtnl
changelink path only checks CAP_NET_ADMIN against the caller's netns. A
caller with caps only in its current netns can then rewrite an interface
in another netns.

Gate the op on net_admin_capable() at its top, before any attribute is
parsed. The check is skipped when the interface netns is the device's
current netns, where the rtnl path already checked the cap.

Reported-by: Xiao Liang <shaw.leon@gmail.com>
Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/
Fixes: f203b76d7809 ("xfrm: Add virtual xfrm interfaces")
Cc: stable@vger.kernel.org
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
---
 net/xfrm/xfrm_interface_core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c
index 330a05286a56..8fd3842d20c2 100644
--- a/net/xfrm/xfrm_interface_core.c
+++ b/net/xfrm/xfrm_interface_core.c
@@ -869,6 +869,9 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
 	struct net *net = xi->net;
 	struct xfrm_if_parms p = {};
 
+	if (!net_admin_capable(net, dev_net(dev)))
+		return -EPERM;
+
 	xfrmi_netlink_parms(data, &p);
 	if (!p.if_id) {
 		NL_SET_ERR_MSG(extack, "if_id must be non zero");
-- 
2.34.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net v4 1/7] net: ip_gre: require CAP_NET_ADMIN in the device netns for changelink
  2026-06-09 16:31 ` [PATCH net v4 1/7] net: ip_gre: require CAP_NET_ADMIN in the device netns for changelink Maoyi Xie
@ 2026-06-11  5:25   ` Kuniyuki Iwashima
  0 siblings, 0 replies; 9+ messages in thread
From: Kuniyuki Iwashima @ 2026-06-11  5:25 UTC (permalink / raw)
  To: Maoyi Xie
  Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern, Xiao Liang, Steffen Klassert, Herbert Xu,
	Simon Horman, netdev, linux-kernel, stable

On Tue, Jun 9, 2026 at 9:31 AM Maoyi Xie <maoyixie.tju@gmail.com> wrote:
>
> A tunnel changelink rewrites the tunnel in its creation netns. After an
> IFLA_NET_NS_FD migration that netns is not the caller's. The rtnl
> changelink path only checks CAP_NET_ADMIN against the caller's netns. A
> caller with caps only in its current netns can then rewrite a tunnel
> that lives in another netns, and it picks the endpoint addresses.

nit: This paragraph is not precise (e.g. even without netns migration
a device can use two netns w/ IFLA_LINK_NETNSID, "current netns"
sounds like current->nsproxy->net_ns but not w/ IFLA_NET_NS_PID
etc, also I don't get the last sentence after "it picks...").

Simply state that changelink() operates on at most two netns,
dev_net() and link_net.

>
> Add net_admin_capable(). It requires CAP_NET_ADMIN in the tunnel's netns
> and is skipped when that netns is the device's current netns, where the
> rtnl path already checked the cap. The other patches in this series use
> the same helper.
>
> Gate ipgre_changelink() and erspan_changelink() with it. The check is at
> the top of the op, before any attribute is parsed, because the parsers
> update live tunnel fields first. ipgre_netlink_parms() sets
> t->collect_md before ip_tunnel_changelink() runs.
>
> Commit 8b484efd5cb4 ("ip6: vti: Use ip6_tnl.net in
> vti6_siocdevprivate().") added the same check on the ioctl path. This
> adds it on RTM_NEWLINK.
>
> Reported-by: Xiao Liang <shaw.leon@gmail.com>
> Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/
> Fixes: d0f418516022 ("net, ip_tunnel: fix namespaces move")
> Cc: stable@vger.kernel.org
> Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
> ---
>  include/net/net_namespace.h | 18 ++++++++++++++++++
>  net/ipv4/ip_gre.c           |  6 ++++++
>  2 files changed, 24 insertions(+)
>
> diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
> index 80de5e98a66d..17fb71a78cb6 100644
> --- a/include/net/net_namespace.h
> +++ b/include/net/net_namespace.h

net/core/rtnetlink.c is a better fit.
It has rtnl_get_net_ns_capable().


> @@ -358,6 +358,24 @@ static inline bool net_initialized(const struct net *net)
>         return READ_ONCE(net->list.next);
>  }
>
> +/**
> + * net_admin_capable - test for CAP_NET_ADMIN over a network namespace
> + * @net: namespace whose state the operation would change
> + * @cur: namespace the operation runs in, e.g. dev_net(dev)
> + *
> + * Returns true when @net is @cur, where CAP_NET_ADMIN was already
> + * checked for the running namespace,
> or when the caller holds
> + * CAP_NET_ADMIN over @net. rtnl changelink paths use this: a device can
> + * be moved so its state lives in a namespace other than the one the
> + * request runs in, and the cap must then be held over that namespace.
> + */
> +static inline bool net_admin_capable(const struct net *net,
> +                                    const struct net *cur)

Rename the helper and change args to

rtnl_dev_link_net_capable(const struct net_device *dev, const struct
net *link_net)

since the netns we care about here is rtnl_newlink_params.link_net
(if specified) and dev_net() is redundant in all callers.

Also remove kdoc, it just reiterates the two conditions below.


> +{
> +       return net_eq(net, cur) ||
> +              ns_capable(net->user_ns, CAP_NET_ADMIN);
> +}
> +
>  static inline void __netns_tracker_alloc(struct net *net,
>                                          netns_tracker *tracker,
>                                          bool refcounted,
> diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
> index 169e2921a851..040a0ef95184 100644
> --- a/net/ipv4/ip_gre.c
> +++ b/net/ipv4/ip_gre.c
> @@ -1457,6 +1457,9 @@ static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
>         __u32 fwmark = t->fwmark;
>         int err;
>
> +       if (!net_admin_capable(t->net, dev_net(dev)))
> +               return -EPERM;
> +
>         err = ipgre_newlink_encap_setup(dev, data);
>         if (err)
>                 return err;
> @@ -1486,6 +1489,9 @@ static int erspan_changelink(struct net_device *dev, struct nlattr *tb[],
>         __u32 fwmark = t->fwmark;
>         int err;
>
> +       if (!net_admin_capable(t->net, dev_net(dev)))
> +               return -EPERM;
> +
>         err = ipgre_newlink_encap_setup(dev, data);
>         if (err)
>                 return err;
> --
> 2.34.1
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-06-11  5:25 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-09 16:31 [PATCH net v4 0/7] net: require CAP_NET_ADMIN in the device netns for tunnel changelink Maoyi Xie
2026-06-09 16:31 ` [PATCH net v4 1/7] net: ip_gre: require CAP_NET_ADMIN in the device netns for changelink Maoyi Xie
2026-06-11  5:25   ` Kuniyuki Iwashima
2026-06-09 16:31 ` [PATCH net v4 2/7] net: ipip: " Maoyi Xie
2026-06-09 16:31 ` [PATCH net v4 3/7] net: ip_vti: " Maoyi Xie
2026-06-09 16:31 ` [PATCH net v4 4/7] net: ip6_tunnel: " Maoyi Xie
2026-06-09 16:31 ` [PATCH net v4 5/7] net: ip6_gre: " Maoyi Xie
2026-06-09 16:31 ` [PATCH net v4 6/7] net: ip6_vti: " Maoyi Xie
2026-06-09 16:31 ` [PATCH net v4 7/7] xfrm: xfrm_interface: " Maoyi Xie

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®