From: Stephen Hemminger <stephen@networkplumber.org>
To: netdev@vger.kernel.org
Cc: Stephen Hemminger <stephen@networkplumber.org>,
Claude <noreply@anthropic.com>
Subject: [PATCH iproute] iptunnel: use worst case buffer for tunnel ioctls
Date: Tue, 20 Oct 2026 08:46:35 -0700 [thread overview]
Message-ID: <20261020154636.1097849-1-stephen@networkplumber.org> (raw)
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
next reply other threads:[~2026-10-20 15:46 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-20 15:46 Stephen Hemminger [this message]
2026-10-20 19:05 ` [PATCH iproute] iptunnel: use worst case buffer for tunnel ioctls Jakub Kicinski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261020154636.1097849-1-stephen@networkplumber.org \
--to=stephen@networkplumber.org \
--cc=netdev@vger.kernel.org \
--cc=noreply@anthropic.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.