[Devel] [PATCH DRAFT vz10 4/5] ve/net/ip6_gre: Fix NULL deref when creating ip6gre/ip6erspan without VE_FEATURE_IPGRE

Konstantin Khorenko khorenko at virtuozzo.com
Wed Aug 12 16:04:00 MSK 2026


When a Container is not granted VE_FEATURE_IPGRE, ip6gre_init_net()
frees the ip6gre_net_id net_generic slot, so net_generic() returns NULL
for that netns. The guard added by commit 1e1433063539 ("net/gre:
Consider VE_FEATURE_IPGRE on new net creation") was placed in
ip6gre_newlink_common(), but both ip6gre_newlink() and
ip6erspan_newlink() dereference the per-net data (ign) earlier - via
rtnl_dereference(ign->collect_md_tun[_erspan]) and
ip6gre_tunnel_find() -> __ip6gre_bucket() - before ever reaching
ip6gre_newlink_common(). Both rtnl link ops are registered
unconditionally, so a Container without the feature can trigger this by
requesting an "ip6gre" or "ip6erspan" link, dereferencing a NULL ign
and crashing the host.

Move the guard to the top of ip6gre_newlink() and ip6erspan_newlink(),
right after ign is fetched and before it is dereferenced, and drop the
now-redundant check in ip6gre_newlink_common() (its only two callers now
guarantee a non-NULL ign). The changelink paths are not affected: they
operate on an already existing tunnel device, which can only exist when
the feature is on and ign is non-NULL.

Fixes: 1e1433063539 ("net/gre: Consider VE_FEATURE_IPGRE on new net creation")
https://virtuozzo.atlassian.net/browse/VSTOR-141173

Feature: ve: per-CT features management
Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
 net/ipv6/ip6_gre.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index ba32cc39fc882..fe867528a0c5b 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -2006,15 +2006,6 @@ static int ip6gre_newlink_common(struct net *src_net, struct net_device *dev,
 	struct ip6_tnl *nt;
 	struct ip_tunnel_encap ipencap;
 	int err;
-#ifdef CONFIG_VE
-	struct net *net = dev_net(dev);
-	struct ip6gre_net *ign;
-
-	ign = net_generic(net, ip6gre_net_id);
-
-	if (!ign) /* no VE_FEATURE_IPGRE */
-		return -EACCES;
-#endif
 
 	nt = netdev_priv(dev);
 
@@ -2054,6 +2045,11 @@ static int ip6gre_newlink(struct net *src_net, struct net_device *dev,
 	ip6gre_netlink_parms(data, &nt->parms);
 	ign = net_generic(net, ip6gre_net_id);
 
+#ifdef CONFIG_VE
+	if (!ign) /* no VE_FEATURE_IPGRE */
+		return -EACCES;
+#endif
+
 	if (nt->parms.collect_md) {
 		if (rtnl_dereference(ign->collect_md_tun))
 			return -EEXIST;
@@ -2291,6 +2287,11 @@ static int ip6erspan_newlink(struct net *src_net, struct net_device *dev,
 	ip6erspan_set_version(data, &nt->parms);
 	ign = net_generic(net, ip6gre_net_id);
 
+#ifdef CONFIG_VE
+	if (!ign) /* no VE_FEATURE_IPGRE */
+		return -EACCES;
+#endif
+
 	if (nt->parms.collect_md) {
 		if (rtnl_dereference(ign->collect_md_tun_erspan))
 			return -EEXIST;
-- 
2.43.0



More information about the Devel mailing list