[PATCH net v4 5/7] net: ip6_gre: require CAP_NET_ADMIN in the device netns for changelink

From: Maoyi Xie

Date: Tue Jun 09 2026 - 12:57:14 EST


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@xxxxxxxxx>
Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@xxxxxxxxxxxxxx/
Fixes: 690afc165bb3 ("net: ip6_gre: fix moving ip6gre between namespaces")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Maoyi Xie <maoyixie.tju@xxxxxxxxx>
---
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