From: Eric Dumazet <edumazet@google.com>
To: davem@davemloft.net, kuba@kernel.org, pabeni@redhat.com
Cc: horms@kernel.org, dsahern@kernel.org, idosch@nvidia.com,
netdev@vger.kernel.org, eric.dumazet@gmail.com,
Eric Dumazet <edumazet@google.com>
Subject: [PATCH net v2 2/5] ip_gre: validate netlink attributes before changing the tunnel
Date: Wed, 16 Sep 2026 10:01:52 +0000 [thread overview]
Message-ID: <20260916100155.1398403-3-edumazet@google.com> (raw)
In-Reply-To: <20260916100155.1398403-1-edumazet@google.com>
ipgre_netlink_parms() and erspan_netlink_parms() write into the live
tunnel before all attributes have been validated, so a rejected
changelink leaves it half updated.
A request carrying IFLA_GRE_COLLECT_METADATA and an invalid
IFLA_GRE_IGNORE_DF returns -EINVAL, but dev->type has already become
ARPHRD_NONE, breaking the interface for good.
Parse the ERSPAN attributes into local variables and commit them only
once everything is validated, hence erspan_netlink_parms() now calls
ipgre_netlink_parms() last. Same reason for moving
IFLA_GRE_COLLECT_METADATA after the IFLA_GRE_IGNORE_DF validation.
Only the parsers become all-or-nothing: ip_tunnel_encap_setup() still
runs before them, ip_tunnel_changelink() after them.
Fixes: e271c7b4420d ("gre: do not keep the GRE header around in collect medata mode")
Fixes: 84e54fe0a5ea ("gre: introduce native tunnel support for ERSPAN")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/ipv4/ip_gre.c | 55 ++++++++++++++++++++++++++++++-----------------
1 file changed, 35 insertions(+), 20 deletions(-)
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 82309efd417e0f1f6554e7028be8e05d769e932d..dad3d054bd15612a3ebe1cf27e6e8c5d9e6896e9 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -1233,12 +1233,6 @@ static int ipgre_netlink_parms(struct net_device *dev,
parms->iph.frag_off = htons(IP_DF);
}
- if (data[IFLA_GRE_COLLECT_METADATA]) {
- t->collect_md = true;
- if (dev->type == ARPHRD_IPGRE)
- dev->type = ARPHRD_NONE;
- }
-
if (data[IFLA_GRE_IGNORE_DF]) {
if (nla_get_u8(data[IFLA_GRE_IGNORE_DF])
&& (parms->iph.frag_off & htons(IP_DF)))
@@ -1246,6 +1240,16 @@ static int ipgre_netlink_parms(struct net_device *dev,
t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]);
}
+ /* All attributes parsed here have been validated, we can change @dev
+ * and @t. This only makes this parser all-or-nothing, the caller can
+ * still fail in ip_tunnel_changelink().
+ */
+ if (data[IFLA_GRE_COLLECT_METADATA]) {
+ t->collect_md = true;
+ if (dev->type == ARPHRD_IPGRE)
+ dev->type = ARPHRD_NONE;
+ }
+
if (data[IFLA_GRE_FWMARK])
*fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
@@ -1259,40 +1263,51 @@ static int erspan_netlink_parms(struct net_device *dev,
__u32 *fwmark)
{
struct ip_tunnel *t = netdev_priv(dev);
+ u8 erspan_ver = t->erspan_ver;
+ u32 index = t->index;
+ u16 hwid = t->hwid;
+ u8 dir = t->dir;
int err;
- err = ipgre_netlink_parms(dev, data, tb, parms, fwmark);
- if (err)
- return err;
if (!data)
- return 0;
+ return ipgre_netlink_parms(dev, data, tb, parms, fwmark);
if (data[IFLA_GRE_ERSPAN_VER]) {
- t->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
+ erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
- if (t->erspan_ver > 2)
+ if (erspan_ver > 2)
return -EINVAL;
}
- if (t->erspan_ver == 1) {
+ if (erspan_ver == 1) {
if (data[IFLA_GRE_ERSPAN_INDEX]) {
- t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
- if (t->index & ~INDEX_MASK)
+ index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
+ if (index & ~INDEX_MASK)
return -EINVAL;
}
- } else if (t->erspan_ver == 2) {
+ } else if (erspan_ver == 2) {
if (data[IFLA_GRE_ERSPAN_DIR]) {
- t->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]);
- if (t->dir & ~(DIR_MASK >> DIR_OFFSET))
+ dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]);
+ if (dir & ~(DIR_MASK >> DIR_OFFSET))
return -EINVAL;
}
if (data[IFLA_GRE_ERSPAN_HWID]) {
- t->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]);
- if (t->hwid & ~(HWID_MASK >> HWID_OFFSET))
+ hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]);
+ if (hwid & ~(HWID_MASK >> HWID_OFFSET))
return -EINVAL;
}
}
+ err = ipgre_netlink_parms(dev, data, tb, parms, fwmark);
+ if (err)
+ return err;
+
+ /* All attributes parsed here have been validated, we can change @t. */
+ t->erspan_ver = erspan_ver;
+ t->index = index;
+ t->hwid = hwid;
+ t->dir = dir;
+
return 0;
}
--
2.55.0.1032.g73a4cd73de-goog
next prev parent reply other threads:[~2026-09-16 10:02 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-12 15:09 [PATCH net 0/3] ip_gre: fix header lengths and validation on changelink Eric Dumazet
2026-09-12 15:09 ` [PATCH net 1/3] ip_gre: validate netlink attributes before changing the tunnel Eric Dumazet
2026-09-15 12:11 ` netdev-bot+sashiko
2026-09-12 15:09 ` [PATCH net 2/3] ip_gre: compute tunnel lengths absolutely instead of by delta Eric Dumazet
2026-09-15 12:11 ` netdev-bot+sashiko
2026-09-12 15:09 ` [PATCH net 3/3] ip_gre: recompute erspan header lengths after a change Eric Dumazet
2026-09-15 12:11 ` netdev-bot+sashiko
2026-09-15 13:31 ` [PATCH net 0/3] ip_gre: fix header lengths and validation on changelink Eric Dumazet
2026-09-16 10:01 ` [PATCH net v2 0/5] ip_tunnel, ip_gre: fix changelink lengths and ERSPAN receive Eric Dumazet
2026-09-16 10:01 ` [PATCH net v2 1/5] ip_tunnel: do not clear the active encap before validating the new one Eric Dumazet
2026-09-20 10:48 ` netdev-bot+sashiko
2026-09-16 10:01 ` Eric Dumazet [this message]
2026-09-20 10:48 ` [PATCH net v2 2/5] ip_gre: validate netlink attributes before changing the tunnel netdev-bot+sashiko
2026-09-16 10:01 ` [PATCH net v2 3/5] ip_gre: compute tunnel lengths absolutely instead of by delta Eric Dumazet
2026-09-20 10:48 ` netdev-bot+sashiko
2026-09-16 10:01 ` [PATCH net v2 4/5] ip_gre: recompute erspan header lengths after a change Eric Dumazet
2026-09-20 10:48 ` netdev-bot+sashiko
2026-09-16 10:01 ` [PATCH net v2 5/5] gre: fix out-of-bounds read of erspan metadata in collect_md mode Eric Dumazet
2026-09-20 10:48 ` netdev-bot+sashiko
2026-09-16 22:45 ` [PATCH net v2 0/5] ip_tunnel, ip_gre: fix changelink lengths and ERSPAN receive 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=20260916100155.1398403-3-edumazet@google.com \
--to=edumazet@google.com \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=eric.dumazet@gmail.com \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.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.