Netdev List
 help / color / mirror / Atom feed
* [PATCH iproute] iptunnel: use worst case buffer for tunnel ioctls
@ 2026-10-20 15:46 Stephen Hemminger
  2026-10-20 19:05 ` Jakub Kicinski
  0 siblings, 1 reply; 2+ messages in thread
From: Stephen Hemminger @ 2026-10-20 15:46 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Claude

The tunnel ioctls are device private, so the kernel fills in
whatever parameter structure the device uses, and that can be
the larger IPv6 struct ip6_tnl_parm2 when an IPv4 tunnel was expected.
Ust a worst case union similar to commit 8cc2eac6 ("iptunnel: detect
protocol mismatch on tunnel change") already uses on the change
path for add, del and show as well.

Reported-by: Anthropic OSS scanner
Assisted-by: Claude <noreply@anthropic.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 ip/iptunnel.c | 50 +++++++++++++++++++++++++++++++-------------------
 1 file changed, 31 insertions(+), 19 deletions(-)

diff --git a/ip/iptunnel.c b/ip/iptunnel.c
index b6da1459..8d590704 100644
--- a/ip/iptunnel.c
+++ b/ip/iptunnel.c
@@ -24,6 +24,18 @@
 #include "ip_common.h"
 #include "tunnel.h"
 
+/*
+ * The tunnel ioctls are device private: the driver of whatever device
+ * owns the name decides how many bytes it copies to ifru_data.  The
+ * name may belong to an IPv6 tunnel (user error, or a rename between
+ * the link dump and the ioctl), so always give the kernel a buffer
+ * large enough for any tunnel parameter block.
+ */
+union ip_tnl_parm {
+	struct ip_tunnel_parm ip_tnl;
+	struct ip6_tnl_parm2 ip6_tnl;
+};
+
 static void usage(void) __attribute__((noreturn));
 
 static void usage(void)
@@ -173,10 +185,7 @@ 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) {
-				union {
-					struct ip_tunnel_parm ip_tnl;
-					struct ip6_tnl_parm2 ip6_tnl;
-				} old_p = {};
+				union ip_tnl_parm old_p = {};
 
 				if (tnl_get_ioctl(*argv, &old_p))
 					return -1;
@@ -260,35 +269,37 @@ static const char *tnl_defname(const struct ip_tunnel_parm *p)
 
 static int do_add(int cmd, int argc, char **argv)
 {
-	struct ip_tunnel_parm p;
+	union ip_tnl_parm u = {};
+	struct ip_tunnel_parm *p = &u.ip_tnl;
 	const char *basedev;
 
-	if (parse_args(argc, argv, cmd, &p) < 0)
+	if (parse_args(argc, argv, cmd, p) < 0)
 		return -1;
 
-	if (p.iph.ttl && p.iph.frag_off == 0) {
+	if (p->iph.ttl && p->iph.frag_off == 0) {
 		fprintf(stderr, "ttl != 0 and nopmtudisc are incompatible\n");
 		return -1;
 	}
 
-	basedev = tnl_defname(&p);
+	basedev = tnl_defname(p);
 	if (!basedev) {
 		fprintf(stderr,
 			"cannot determine tunnel mode (ipip, gre, vti or sit)\n");
 		return -1;
 	}
 
-	return tnl_add_ioctl(cmd, basedev, p.name, &p);
+	return tnl_add_ioctl(cmd, basedev, p->name, &u);
 }
 
 static int do_del(int argc, char **argv)
 {
-	struct ip_tunnel_parm p;
+	union ip_tnl_parm u = {};
+	struct ip_tunnel_parm *p = &u.ip_tnl;
 
-	if (parse_args(argc, argv, SIOCDELTUNNEL, &p) < 0)
+	if (parse_args(argc, argv, SIOCDELTUNNEL, p) < 0)
 		return -1;
 
-	return tnl_del_ioctl(tnl_defname(&p) ? : p.name, p.name, &p);
+	return tnl_del_ioctl(tnl_defname(p) ? : p->name, p->name, &u);
 }
 
 static void print_tunnel(const void *t)
@@ -410,17 +421,18 @@ static bool ip_tunnel_parm_match(const struct tnl_print_nlmsg_info *info)
 
 static int do_show(int argc, char **argv)
 {
-	struct ip_tunnel_parm p, p1;
+	union ip_tnl_parm u = {}, u1 = {};
+	struct ip_tunnel_parm *p = &u.ip_tnl;
 	const char *basedev;
 
-	if (parse_args(argc, argv, SIOCGETTUNNEL, &p) < 0)
+	if (parse_args(argc, argv, SIOCGETTUNNEL, p) < 0)
 		return -1;
 
-	basedev = tnl_defname(&p);
+	basedev = tnl_defname(p);
 	if (!basedev) {
 		struct tnl_print_nlmsg_info info = {
-			.p1    = &p,
-			.p2    = &p1,
+			.p1    = p,
+			.p2    = &u1,
 			.init  = ip_tunnel_parm_initialize,
 			.match = ip_tunnel_parm_match,
 			.print = print_tunnel,
@@ -429,10 +441,10 @@ static int do_show(int argc, char **argv)
 		return do_tunnels_list(&info);
 	}
 
-	if (tnl_get_ioctl(p.name[0] ? p.name : basedev, &p))
+	if (tnl_get_ioctl(p->name[0] ? p->name : basedev, &u))
 		return -1;
 
-	print_tunnel(&p);
+	print_tunnel(p);
 	fputc('\n', stdout);
 	return 0;
 }
-- 
2.53.0


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

* Re: [PATCH iproute] iptunnel: use worst case buffer for tunnel ioctls
  2026-10-20 15:46 [PATCH iproute] iptunnel: use worst case buffer for tunnel ioctls Stephen Hemminger
@ 2026-10-20 19:05 ` Jakub Kicinski
  0 siblings, 0 replies; 2+ messages in thread
From: Jakub Kicinski @ 2026-10-20 19:05 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, Claude

On Tue, 20 Oct 2026 08:46:35 -0700 Stephen Hemminger wrote:
> Subject: [PATCH iproute] iptunnel: use worst case buffer for tunnel ioctls

Please tell your bot that the correct tag is iproute2 not iproute

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

end of thread, other threads:[~2026-10-20 19:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-20 15:46 [PATCH iproute] iptunnel: use worst case buffer for tunnel ioctls Stephen Hemminger
2026-10-20 19:05 ` Jakub Kicinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox