From: Denis V. Lunev <[email protected]>
Commit a1049e020cdf ("ve/net/gre: Disable ERSPAN support in ip_gre
module") compiled erspan_net_ops out under CONFIG_VE but left the ERSPAN
receive and ICMP error paths in place. erspan_net_id is then never
assigned and stays 0, and net_generic(net, 0) does not return NULL: it
returns the length word of struct net_generic, which ptr[0] overlays.
ip_tunnel_lookup() passes its NULL check and reads itn->tunnels[] in
the first page. Once ip_gre is loaded, any GRE packet with protocol
ETH_P_ERSPAN or ETH_P_ERSPAN2 delivered to the node panics it in
softirq, and so does an ICMP error quoting such a header. The packet
can come from the network or from container root with a raw socket.
Return a NULL itn for ERSPAN under CONFIG_VE, so both paths miss the
lookup and handle the packet as one for a tunnel that does not exist.
Fixes: a1049e020cdf ("ve/net/gre: Disable ERSPAN support in ip_gre module")
https://virtuozzo.atlassian.net/browse/VSTOR-154362
Feature: net: disable ERSPAN support in ip_gre module
Signed-off-by: Denis V. Lunev <[email protected]>
---
net/ipv4/ip_gre.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index f618aae25033..c84548eebf80 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -120,8 +120,21 @@ static void erspan_build_header(struct sk_buff *skb,
static unsigned int ipgre_net_id __read_mostly;
static unsigned int gre_tap_net_id __read_mostly;
+#ifdef CONFIG_VE
+/* erspan_net_ops is compiled out, there is no erspan pernet state */
+static struct ip_tunnel_net *erspan_itn(struct net *net)
+{
+ return NULL;
+}
+#else
static unsigned int erspan_net_id __read_mostly;
+static struct ip_tunnel_net *erspan_itn(struct net *net)
+{
+ return net_generic(net, erspan_net_id);
+}
+#endif
+
static int ipgre_err(struct sk_buff *skb, u32 info,
const struct tnl_ptk_info *tpi)
{
@@ -151,7 +164,7 @@ static int ipgre_err(struct sk_buff *skb, u32 info,
itn = net_generic(net, gre_tap_net_id);
else if (tpi->proto == htons(ETH_P_ERSPAN) ||
tpi->proto == htons(ETH_P_ERSPAN2))
- itn = net_generic(net, erspan_net_id);
+ itn = erspan_itn(net);
else
itn = net_generic(net, ipgre_net_id);
@@ -279,7 +292,7 @@ static int erspan_rcv(struct sk_buff *skb, struct
tnl_ptk_info *tpi,
ip_tunnel_flags_copy(flags, tpi->flags);
- itn = net_generic(net, erspan_net_id);
+ itn = erspan_itn(net);
iph = ip_hdr(skb);
if (is_erspan_type1(gre_hdr_len)) {
ver = 0;
--
2.53.0
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel