68 lines
2.1 KiB
Diff
68 lines
2.1 KiB
Diff
From 8cc2eac60d5f1f5ec2c40d02c0003731c8b610dc Mon Sep 17 00:00:00 2001
|
|
From: Stephen Hemminger <stephen@networkplumber.org>
|
|
Date: Mon, 10 Apr 2023 16:22:51 -0700
|
|
Subject: [PATCH] iptunnel: detect protocol mismatch on tunnel change
|
|
|
|
If attempt is made to change an IPv6 tunnel by using IPv4
|
|
parameters, a stack overflow would happen and garbage request
|
|
would be passed to kernel.
|
|
|
|
Example:
|
|
ip tunnel add gre1 mode ip6gre local 2001:db8::1 remote 2001:db8::2 ttl 255
|
|
ip tunnel change gre1 mode gre local 192.168.0.0 remote 192.168.0.1 ttl 255
|
|
|
|
The second command should fail because it attempting set IPv4 addresses
|
|
on a GRE tunnel that is IPv6.
|
|
|
|
Do best effort detection of this mismatch by giving a bigger buffer to get
|
|
tunnel request, and checking that the IP header is IPv4. It is still possible
|
|
but unlikely that byte would match in IPv6 tunnel paramater, but good enough
|
|
to catch the obvious cases.
|
|
|
|
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1032642
|
|
Tested-by: Luca Boccassi <bluca@debian.org>
|
|
Reported-by: Robin <imer@imer.cc>
|
|
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
|
|
---
|
|
ip/iptunnel.c | 14 ++++++++++++--
|
|
1 file changed, 12 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/ip/iptunnel.c b/ip/iptunnel.c
|
|
index 02c3670b..b6da1459 100644
|
|
--- a/ip/iptunnel.c
|
|
+++ b/ip/iptunnel.c
|
|
@@ -17,6 +17,7 @@
|
|
#include <net/if_arp.h>
|
|
#include <linux/ip.h>
|
|
#include <linux/if_tunnel.h>
|
|
+#include <linux/ip6_tunnel.h>
|
|
|
|
#include "rt_names.h"
|
|
#include "utils.h"
|
|
@@ -172,11 +173,20 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
|
|
if (get_ifname(p->name, *argv))
|
|
invarg("\"name\" not a valid ifname", *argv);
|
|
if (cmd == SIOCCHGTUNNEL && count == 0) {
|
|
- struct ip_tunnel_parm old_p = {};
|
|
+ union {
|
|
+ struct ip_tunnel_parm ip_tnl;
|
|
+ struct ip6_tnl_parm2 ip6_tnl;
|
|
+ } old_p = {};
|
|
|
|
if (tnl_get_ioctl(*argv, &old_p))
|
|
return -1;
|
|
- *p = old_p;
|
|
+
|
|
+ if (old_p.ip_tnl.iph.version != 4 ||
|
|
+ old_p.ip_tnl.iph.ihl != 5)
|
|
+ invarg("\"name\" is not an ip tunnel",
|
|
+ *argv);
|
|
+
|
|
+ *p = old_p.ip_tnl;
|
|
}
|
|
}
|
|
count++;
|
|
--
|
|
2.27.0
|
|
|