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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox