From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Eric Dumazet <edumazet@google.com>,
Simon Horman <horms@kernel.org>, Jakub Kicinski <kuba@kernel.org>,
Sasha Levin <sashal@kernel.org>,
dsahern@kernel.org, idosch@nvidia.com, davem@davemloft.net,
edumazet@kernel.org, pabeni@redhat.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 6.18-6.12] gre: fix ERSPAN o_flags race/corruption in xmit and fill_info
Date: Mon, 19 Oct 2026 09:51:32 -0400 [thread overview]
Message-ID: <20261019135441.1420968-401-sashal@kernel.org> (raw)
In-Reply-To: <20261019135441.1420968-1-sashal@kernel.org>
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit 9958e69b98930834a576e156f6458166d1db1c02 ]
For IPv4 ERSPAN:
In erspan_xmit(), the driver clears IP_TUNNEL_SEQ_BIT (for version 0)
and IP_TUNNEL_KEY_BIT directly in the shared tunnel->parms.o_flags
structure. Since transmit paths can run locklessly and concurrently,
this leads to a data race.
Furthermore, modifying tunnel->parms.o_flags permanently alters the
tunnel configuration. To work around this, erspan_fill_info() (which
reports config to userspace) was setting IP_TUNNEL_KEY_BIT back. If
erspan_fill_info (running under RTNL) and erspan_xmit (running locklessly)
race, erspan_xmit might see IP_TUNNEL_KEY_BIT set when it shouldn't,
leading to GRE header corruption (injecting a key field into the ERSPAN
GRE header).
Fix this by:
1) Passing flags as an argument to __gre_xmit().
2) Using local stack flags in ipgre_xmit(), gre_tap_xmit(), and erspan_xmit()
to prevent TOCTOU data races with concurrent configuration updates,
and passing them to __gre_xmit().
3) Removing the racy modification of t->parms.o_flags in erspan_fill_info().
4) Forcing IP_TUNNEL_KEY_BIT in the reported flags for ERSPAN locally
in ipgre_fill_info().
For IPv6 ERSPAN:
ip6erspan_tunnel_xmit() was locklessly clearing IP_TUNNEL_KEY_BIT in
t->parms.o_flags even though it does not use these flags for building
the GRE header (it uses local flags). This permanently corrupts the
configuration and races with ip6gre_fill_info() which reads it.
Remove the redundant and racy modification.
This should remove false sharing in a fast path.
Add const qualifiers in ipgre_fill_info(), erspan_fill_info()
and ip6gre_fill_info() to clarify that these methods are not
supposed to write any live parameters.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260812142257.21283-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough to decide: the buggy shared `o_flags` mutation is in this
6.12 tree, the APIs match, and the failure mode is GRE header
corruption. Compiling the full analysis.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [gre] [fix] [ERSPAN o_flags race/corruption in xmit and
fill_info]
Subsystem: GRE/ERSPAN tunnels (`net/ipv4/ip_gre.c`,
`net/ipv6/ip6_gre.c`). Action verb is explicitly **fix**.
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record (from the candidate text and from the original mailing-list
submission):
- Signed-off-by: Eric Dumazet <edumazet@google.com> (author; networking
core maintainer)
- Reviewed-by: Simon Horman <horms@kernel.org>
- Link:
https://patch.msgid.link/20260812142257.21283-1-edumazet@google.com
- Signed-off-by: Jakub Kicinski <kuba@kernel.org> (netdev maintainer,
applied to net-next)
- Ignore: pipeline "Signed-off-by: Sasha Levin" / "[Upstream commit
...]" if present
Original v4 submission (verified in `/tmp/erspan_thread.mbox`) also had:
- Fixes: 84e54fe0a5ea ("gre: introduce native tunnel support for
ERSPAN")
- Fixes: ee496694b9ee ("ip_gre: do not report erspan version on GRE
interface")
- Fixes: 5a963eb61b7c ("ip6_gre: Add ERSPAN native tunnel support")
v2 was sent to **net** with **Cc: stable@vger.kernel.org**. v4 dropped
Cc: stable and went to net-next after review. Absence of Cc: stable on
the committed v4 is expected for this review pipeline and is not a
negative signal.
No Reported-by / syzbot / Tested-by on this specific patch. Author found
it while working on RTNL-less fill_info.
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: IPv4 `erspan_xmit()` locklessly clears `IP_TUNNEL_SEQ_BIT` (v0)
and `IP_TUNNEL_KEY_BIT` in the **shared** `tunnel->parms.o_flags`.
That permanently mutates tunnel config. `erspan_fill_info()` then
writes `IP_TUNNEL_KEY_BIT` back so userspace dumps look correct.
- Symptom: TOCTOU data race between lockless xmit and RTNL fill_info. If
xmit observes KEY_BIT set, `gre_build_header()` injects a GRE key
field into the ERSPAN header (malformed GRE / header corruption).
- IPv6: `ip6erspan_tunnel_xmit()` also locklessly clears KEY_BIT on
shared `t->parms.o_flags` even though it builds the GRE header from
**local** flags. That is redundant, races with `ip6gre_fill_info()`,
and causes false sharing on a fast path.
- Root cause: treating per-tunnel `o_flags` as scratch space from
ndo_start_xmit.
- Versions: Fixes tags point at ERSPAN introduction (2017) and the
fill_info KEY_BIT workaround (2022). All three are ancestors of this
6.12 tree.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not disguised. This is an explicit race + packet-corruption fix.
Extra `const` on fill_info is documentation-only. Snapshotting flags in
`ipgre_xmit()`/`gre_tap_xmit()` is extra TOCTOU hardening requested by
Ido Schimmel, still a correctness fix, not a feature.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- `net/ipv4/ip_gre.c`: ~+23/-19 in `__gre_xmit`, `ipgre_xmit`,
`erspan_xmit`, `gre_tap_xmit`, `ipgre_fill_info`, `erspan_fill_info`
- `net/ipv6/ip6_gre.c`: ~+2/-3 in `ip6erspan_tunnel_xmit`,
`ip6gre_fill_info`
- Scope: single-purpose, two-file surgical fix. `__gre_xmit` is file-
static; no public API.
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- `__gre_xmit`: no longer copies `tunnel->parms.o_flags` itself; callers
pass a local flags snapshot.
- `ipgre_xmit` / `gre_tap_xmit`: copy `o_flags` once, use that copy for
CSUM offload check and header build (closes TOCTOU vs concurrent
changelink).
- `erspan_xmit`: copy flags, then `__clear_bit` KEY (and SEQ for v0) on
the **stack copy**, pass that to `__gre_xmit`. Shared `parms.o_flags`
is no longer written from xmit.
- `erspan_fill_info`: stop writing KEY_BIT into live `t->parms.o_flags`.
- `ipgre_fill_info`: if `erspan_ver != 0 && !collect_md`, set KEY_BIT on
a **local** dump copy. Regular GRE/GRETAP keep `erspan_ver == 0`
(`erspan_setup()` is the only path that sets it to 1).
- `ip6erspan_tunnel_xmit`: delete the unused shared
`__clear_bit(IP_TUNNEL_KEY_BIT, t->parms.o_flags)`.
- fill_info functions: `const` on tunnel/parm pointers.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record: [Race + packet corruption + config corruption]
Mechanism: RMW of a shared bitmap from xmit (`__clear_bit`) vs fill_info
(`__set_bit`). `gre_build_header()` then uses `tun_hlen` (8 for ERSPAN
v1/v2) **and** the flags word. If KEY_BIT is set with SEQ, it writes key
then seq into an 8-byte push, and the key write lands on the GRE
flags/protocol word:
```102:144:include/net/gre.h
static inline void gre_build_header(struct sk_buff *skb, int hdr_len,
const unsigned long *flags, __be16
proto,
__be32 key, __be32 seq)
{
...
skb_push(skb, hdr_len);
...
if (ip_tunnel_flags_intersect(flags, cond)) {
__be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4);
if (test_bit(IP_TUNNEL_SEQ_BIT, flags)) {
*ptr = seq;
ptr--;
}
if (test_bit(IP_TUNNEL_KEY_BIT, flags)) {
*ptr = key;
ptr--;
}
```
With `hdr_len == 8` and both SEQ and KEY, KEY overwrites the GRE base
header. That is real on-wire corruption of mirrored traffic.
Step 2.4: ASSESS THE FIX QUALITY
Record: Obviously correct. Local snapshot + mutate the copy is the
standard pattern (IPv6 xmit already used local flags). v4 dropped v2's
`gre_calc_hlen(flags)` substitution after review showed it could emit a
4-byte GRE header when SEQ was absent from o_flags; v4 keeps
`tunnel->tun_hlen`, which is the safer stable-friendly approach.
Regression risk is low: no new locks, no API change, fill_info dump
semantics preserved for ERSPAN KEY reporting.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record: Shared-flag mutation dates to ERSPAN introduction:
- `f551c91de262ba` (2017-12-13) / `84e54fe0a5ea` (2017-08-22): IPv4
ERSPAN xmit
- `5a963eb61b7c` / `e41c7c68ea7716` (2017): IPv6 ERSPAN
- `ee496694b9ee` (2022-12-03): `erspan_fill_info` KEY_BIT restore
workaround
- `5832c4a77d693` (2024-03-27): `__be16` flags → bitmaps
(`__clear_bit`/`__set_bit`); **in this tree**
Bug has been in the driver since 2017; bitmap conversion only changed
the accessor.
Step 3.2: FOLLOW THE FIXES: TAG
Record: All three Fixes SHAs **are ancestors of HEAD**:
- `84e54fe0a5ea` IS ancestor
- `ee496694b9ee` IS ancestor
- `5a963eb61b7c` IS ancestor
Mainline commit `9958e69b9893` is **not** an ancestor of this checkout.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record: Recent GRE work in this tree includes `9f948e9aede96` (restore
GRE/GRETAP `lltx`) and capability checks. No prior fix of this o_flags
xmit/fill_info race. Standalone commit (not patch X/Y). v1–v4 were
revisions of the **same** patch.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Eric Dumazet is a net core maintainer with many GRE/tunnel
commits here (`erspan: make sure erspan_base_hdr is present`, header
robustness, etc.). High-confidence author.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: Needs `IP_TUNNEL_DECLARE_FLAGS` / `ip_tunnel_flags_copy` /
`ip_tunnel_parm_kern` — all present (`5832c4a77d693`, `117aef12a7b1b`).
`__gre_xmit` is static to `ip_gre.c`. Can apply standalone.
Later mainline discussion (Sept 2026, `net: erspan: set lltx to avoid
sch_direct_xmit deadlock`) names **this commit as a stable
prerequisite** before enabling ERSPAN `lltx`. That later patch is not in
this tree (`erspan_tunnel_init` still does not set `dev->lltx`). This
fix is still valuable on its own because fill_info (RTNL) vs xmit (TX
lock) already race.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- b4 dig matched v4:
https://patch.msgid.link/20260812142257.21283-1-edumazet@google.com
- Revisions: v1 net-next (2026-06-15), v2 **net + Cc: stable**
(2026-07-20), v3 net-next (2026-08-11), v4 net-next (2026-08-12,
applied)
- v1 was sent to net-next because “7.1 was just released” (merge-window
timing), not because it was considered a feature.
- v2 review (Sashiko): using `gre_calc_hlen(flags)` could emit a 4-byte
GRE header when SEQ is missing from o_flags; `tun_hlen` previously
forced 8 bytes. Eric marked CR (“What a mess”).
- v4 dropped that `gre_calc_hlen` change and kept `tun_hlen`.
- No NAK. Horman Reviewed-by. Jakub applied to netdev/net-next as
`9958e69b9893`.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: Recipients: davem, kuba, pabeni, horms, idosch, netdev. Ido
asked v1 to snapshot flags in ipgre/gretap too (done in v4). Horman
reviewed v4. Appropriate maintainers.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla for this race. Author discovered it while
working on RTNL-less fill_info. Trigger is ordinary: ERSPAN TX plus `ip
-d link show` / RTNL dump.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Single-patch series. Follow-up ERSPAN `lltx` deadlock fix
depends on this for “no shared mutable o_flags in xmit.” Author agreed
to list this as a stable prerequisite for that later patch.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: No lore.kernel.org/stable thread found that rejected this fix.
v2 was explicitly Cc'd to stable. The later lltx discussion notes this
commit was **not auto-queued** because v4 lacked Cc: stable — which is
why it is in this evaluation pipeline.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `__gre_xmit`, `ipgre_xmit`, `erspan_xmit`, `gre_tap_xmit`,
`ipgre_fill_info`, `erspan_fill_info`, `ip6erspan_tunnel_xmit`,
`ip6gre_fill_info`.
Step 5.2: TRACE CALLERS
Record:
- `erspan_xmit` / `ipgre_xmit` / `gre_tap_xmit` /
`ip6erspan_tunnel_xmit`: `ndo_start_xmit` (hot path).
- `ipgre_fill_info`: GRE and GRETAP `rtnl_link_ops.fill_info`; also
called from `erspan_fill_info`.
- `erspan_fill_info` / `ip6gre_fill_info`: netlink dump.
Step 5.3: TRACE CALLEES
Record: `gre_build_header`, `gre_handle_offloads` →
`iptunnel_handle_offloads`, `ip_tunnel_xmit` / `ip6_tnl_xmit`,
`ip_tunnel_flags_copy`, `__clear_bit`/`__set_bit`.
Step 5.4: FOLLOW THE CALL CHAIN
Record: Userspace-reachable: send on an ERSPAN/GRE/GRETAP netdev; dump
via RTNL (`ip link`). Unprivileged users typically cannot create tunnels
(needs CAP_NET_ADMIN), but once created, TX is a normal data path. Not
theoretical.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: IPv6 native GRE already snapshots flags in `__gre6_xmit`. IPv6
fill_info already set KEY_BIT on a **local** copy. IPv4 ERSPAN was the
inconsistent leftover that mutated live parms.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: **Yes.** Local tree is **6.12.111** (`pending-6.12`,
`p-6.12-3-gc504cf0baa3d8`).
Verified present:
```746:747:net/ipv4/ip_gre.c
__clear_bit(IP_TUNNEL_KEY_BIT, tunnel->parms.o_flags);
__gre_xmit(skb, dev, &tunnel->parms.iph, proto);
```
```1603:1604:net/ipv4/ip_gre.c
if (t->erspan_ver != 0 && !t->collect_md)
__set_bit(IP_TUNNEL_KEY_BIT, t->parms.o_flags);
```
```999:999:net/ipv6/ip6_gre.c
__clear_bit(IP_TUNNEL_KEY_BIT, t->parms.o_flags);
```
Bug introduced 2017; fill_info KEY restore 2022. Both long before 6.12.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Expected apply: **minor context fuzz**, not a rewrite.
This tree’s `gre_rcv` drop path lacks `dev_core_stats_rx_dropped_inc()`
that appears as context in the mainline hunk; `__gre_xmit` itself
matches. All other hunks match current 6.12 code
(`IP_TUNNEL_DECLARE_FLAGS`, `ip_tunnel_parm_kern`, function layout). No
conflicting refactor.
Note: IPv4/IPv6 ERSPAN **do not** set `dev->lltx` here
(`erspan_tunnel_init` / `ip6erspan_tap_init`). Concurrent xmit on one
ERSPAN device is still serialized by `_xmit_lock`. The **fill_info
(RTNL) vs xmit (TX lock)** race remains, and any future ERSPAN lltx
backport would make concurrent xmit racy without this patch.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: `git log --grep="fix ERSPAN o_flags race"` on these files:
empty. No equivalent fix in this tree.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: [net/ipv4 GRE + net/ipv6 GRE ERSPAN] [IMPORTANT]
Not core mm/VFS, but a widely used tunnel type (SPAN/ERSPAN mirroring,
cloud TAP, Kubernetes). Packet corruption on the mirror path is user-
visible.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Mature GRE/ERSPAN (since 4.x). Still receiving correctness fixes
(lltx, headroom, capability checks). This is a long-standing bug, not
churn from new code.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver/config-specific: IPv4 ERSPAN (primary), IPv6 ERSPAN
(shared o_flags clear), plus GRE/GRETAP get a small TOCTOU snapshot.
Anyone running ERSPAN mirrors plus netlink dumps.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Trigger: ERSPAN transmit concurrent with RTNL dump (`ip -d link
show`, monitoring agents). Common in production TAP setups. Creating the
tunnel needs CAP_NET_ADMIN; TX after that is the normal data path.
Timing-dependent, but the window is every dump-vs-packet overlap, not a
one-in-a-billion theoretical race.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: [GRE header corruption / wrong optional fields / overwrite of
GRE flags+protocol when KEY is injected into an 8-byte header] [HIGH]
Also: permanent clear of KEY_BIT in live config until fill_info writes
it back; data race on a bitmap word (KCSAN-class). Not a panic by
itself, but corrupted mirrored packets and broken GRE layout. Stable
rules treat this class of correctness bugs as important.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: HIGH for ERSPAN users (stops header corruption and config
clobber; unblocks a correct lltx backport later).
- Risk: LOW (~25 net lines, local stack flags, no locking change, no
uAPI change, reviewed by Horman/Ido, written by Dumazet).
- Ratio: strongly favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Real race: xmit mutates shared `o_flags`; fill_info writes KEY_BIT
back under a different lock (RTNL vs TX lock).
- Concrete failure: KEY_BIT observed in `gre_build_header()` with
`tun_hlen==8` overwrites the GRE base header.
- Buggy code is in this 6.12 tree; Fixes commits are ancestors.
- Small, obviously correct, no new APIs.
- Author is a net maintainer; Horman Reviewed-by; Ido requested the
GRE/GRETAP snapshot.
- v2 was Cc: stable; later ERSPAN lltx work calls this a stable
prerequisite.
- v4 kept `tun_hlen` after review found v2’s `gre_calc_hlen` unsafe.
AGAINST:
- v4 landed in net-next without Cc: stable (timing/review, not a NAK).
- IPv4 ERSPAN is not yet lltx here, so concurrent xmit is serialized;
the remaining race is dump vs TX (still real).
- First hunk may need trivial context adjustment around `gre_rcv`.
- Extra snapshots in `ipgre_xmit`/`gre_tap_xmit` are slightly broader
than the ERSPAN-only bug, but they are the same pattern and low risk.
UNRESOLVED: none that affect the verdict. Could not fetch
lore.kernel.org HTML (403); used b4 mbox + openwall mirrors instead.
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — local snapshot, reviewed,
applied upstream.
2. Fixes a real bug that affects users? **PASS** — ERSPAN GRE
header/config corruption.
3. Important issue? **PASS** — HIGH: on-wire header corruption (not a
panic, but not cosmetic).
4. Small and contained? **PASS** — ~25 lines, two files, static helper
signature only.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — buggy code and bitmap APIs
present; minor gre_rcv context at most.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: Not a device-ID/quirk/DT/build/docs exception. Ordinary
networking correctness fix.
Step 9.4: MAKE YOUR DECISION
This belongs in **this** 6.12 tree. The bug is here, the fix is small
and correct, and it prevents GRE header corruption on ERSPAN plus
shared-state races that a later lltx change would make worse.
What the commit solves for stable users: ERSPAN xmit must not clear
KEY/SEQ in the live tunnel parms. Doing so races with netlink fill_info
and can inject a GRE key into an 8-byte ERSPAN GRE header, corrupting
mirrored packets. Snapshot flags on the stack and report KEY only on the
dump copy.
Risk vs benefit: low risk, high benefit for ERSPAN. Apply with at most a
small context tweak on the `__gre_xmit` hunk.
Verification:
- [Phase 1] Parsed subject/tags; original v4 mbox has Fixes:
84e54fe0a5ea, ee496694b9ee, 5a963eb61b7c; v2 had Cc: stable
- [Phase 2] Diff: local flags to `__gre_xmit`; stop mutating
`parms.o_flags` in erspan_xmit/fill_info and ip6erspan xmit
- [Phase 2] `gre_build_header()` with hdr_len=8 + KEY+SEQ overwrites GRE
base header — verified in `include/net/gre.h`
- [Phase 3] blame: mutation since 2017 ERSPAN; bitmap conversion
5832c4a77d693 in this tree
- [Phase 3] `git merge-base --is-ancestor` all three Fixes SHAs: yes;
9958e69b9893: no
- [Phase 4] `b4 dig -c 9958e69b9893`: lore msgid 20260812142257.21283-1;
v2/v3/v4; Horman Reviewed-by; no NAK
- [Phase 4] Ido asked for ipgre/gretap snapshots; Sashiko caught v2
gre_calc_hlen malformation; v4 dropped that
- [Phase 4] Later lltx deadlock thread names this commit as stable
prerequisite
- [Phase 5] Callers are ndo_start_xmit and RTNL fill_info
- [Phase 6] `git describe HEAD`: p-6.12-3-gc504cf0baa3d8; `make
kernelversion`: 6.12.111; buggy `__clear_bit`/`__set_bit` present
- [Phase 6] ERSPAN init does not set lltx in this tree; fill_info vs
xmit still races
- [Phase 8] Failure mode: GRE header corruption, severity HIGH
- UNVERIFIED: lore.kernel.org HTML 403 (used b4 + openwall); no stable-
list rejection found
**YES**
net/ipv4/ip_gre.c | 42 +++++++++++++++++++++++-------------------
net/ipv6/ip6_gre.c | 5 ++---
2 files changed, 25 insertions(+), 22 deletions(-)
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index b15cc4ee0d920..b1ec4f92d3462 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -474,12 +474,9 @@ static int gre_rcv(struct sk_buff *skb)
static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
const struct iphdr *tnl_params,
- __be16 proto)
+ __be16 proto, const unsigned long *flags)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
- IP_TUNNEL_DECLARE_FLAGS(flags);
-
- ip_tunnel_flags_copy(flags, tunnel->parms.o_flags);
/* Push GRE header. */
gre_build_header(skb, tunnel->tun_hlen,
@@ -652,6 +649,7 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
+ IP_TUNNEL_DECLARE_FLAGS(flags);
const struct iphdr *tnl_params;
if (!pskb_inet_may_pull(skb))
@@ -687,11 +685,12 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
tnl_params = &tunnel->parms.iph;
}
- if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT,
- tunnel->parms.o_flags)))
+ ip_tunnel_flags_copy(flags, tunnel->parms.o_flags);
+
+ if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT, flags)))
goto free_skb;
- __gre_xmit(skb, dev, tnl_params, skb->protocol);
+ __gre_xmit(skb, dev, tnl_params, skb->protocol, flags);
return NETDEV_TX_OK;
free_skb:
@@ -704,6 +703,7 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
+ IP_TUNNEL_DECLARE_FLAGS(flags);
bool truncate = false;
__be16 proto;
@@ -727,10 +727,12 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
truncate = true;
}
+ ip_tunnel_flags_copy(flags, tunnel->parms.o_flags);
+
/* Push ERSPAN header */
if (tunnel->erspan_ver == 0) {
proto = htons(ETH_P_ERSPAN);
- __clear_bit(IP_TUNNEL_SEQ_BIT, tunnel->parms.o_flags);
+ __clear_bit(IP_TUNNEL_SEQ_BIT, flags);
} else if (tunnel->erspan_ver == 1) {
erspan_build_header(skb, ntohl(tunnel->parms.o_key),
tunnel->index,
@@ -745,8 +747,8 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
goto free_skb;
}
- __clear_bit(IP_TUNNEL_KEY_BIT, tunnel->parms.o_flags);
- __gre_xmit(skb, dev, &tunnel->parms.iph, proto);
+ __clear_bit(IP_TUNNEL_KEY_BIT, flags);
+ __gre_xmit(skb, dev, &tunnel->parms.iph, proto, flags);
return NETDEV_TX_OK;
free_skb:
@@ -759,6 +761,7 @@ static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
+ IP_TUNNEL_DECLARE_FLAGS(flags);
if (!pskb_inet_may_pull(skb))
goto free_skb;
@@ -768,14 +771,15 @@ static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
- if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT,
- tunnel->parms.o_flags)))
+ ip_tunnel_flags_copy(flags, tunnel->parms.o_flags);
+
+ if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT, flags)))
goto free_skb;
if (skb_cow_head(skb, dev->needed_headroom))
goto free_skb;
- __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
+ __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB), flags);
return NETDEV_TX_OK;
free_skb:
@@ -1571,12 +1575,15 @@ static size_t ipgre_get_size(const struct net_device *dev)
static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
{
- struct ip_tunnel *t = netdev_priv(dev);
- struct ip_tunnel_parm_kern *p = &t->parms;
+ const struct ip_tunnel *t = netdev_priv(dev);
+ const struct ip_tunnel_parm_kern *p = &t->parms;
IP_TUNNEL_DECLARE_FLAGS(o_flags);
ip_tunnel_flags_copy(o_flags, p->o_flags);
+ if (t->erspan_ver != 0 && !t->collect_md)
+ __set_bit(IP_TUNNEL_KEY_BIT, o_flags);
+
if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
nla_put_be16(skb, IFLA_GRE_IFLAGS,
gre_tnl_flags_to_gre_flags(p->i_flags)) ||
@@ -1619,12 +1626,9 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
static int erspan_fill_info(struct sk_buff *skb, const struct net_device *dev)
{
- struct ip_tunnel *t = netdev_priv(dev);
+ const struct ip_tunnel *t = netdev_priv(dev);
if (t->erspan_ver <= 2) {
- if (t->erspan_ver != 0 && !t->collect_md)
- __set_bit(IP_TUNNEL_KEY_BIT, t->parms.o_flags);
-
if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver))
goto nla_put_failure;
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index ebd0198458cd3..905c22e6990b8 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -967,7 +967,6 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
if (skb_cow_head(skb, dev->needed_headroom ?: t->hlen))
goto tx_err;
- __clear_bit(IP_TUNNEL_KEY_BIT, t->parms.o_flags);
IPCB(skb)->flags = 0;
/* For collect_md mode, derive fl6 from the tunnel key,
@@ -2116,8 +2115,8 @@ static size_t ip6gre_get_size(const struct net_device *dev)
static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
{
- struct ip6_tnl *t = netdev_priv(dev);
- struct __ip6_tnl_parm *p = &t->parms;
+ const struct ip6_tnl *t = netdev_priv(dev);
+ const struct __ip6_tnl_parm *p = &t->parms;
IP_TUNNEL_DECLARE_FLAGS(o_flags);
ip_tunnel_flags_copy(o_flags, p->o_flags);
--
2.53.0
next prev parent reply other threads:[~2026-10-19 14:04 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-19 13:44 [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check CORE_PLL_GROUP4 access in mt7531_setup() Sasha Levin
2026-10-19 13:44 ` [PATCH AUTOSEL 6.18-5.10] net/rds: don't use unpin_user_pages_dirty_lock() from atomic context Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] selftests: net: reuseport_bpf_numa: consider cpuless numa node Sasha Levin
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-6.1] net: stmmac: fix device node reference leaks in stmmac_mtl_setup() Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] netfilter: conntrack: tcp: use UNACK timeout for non-closing RST packets Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] net: usb: qmi_wwan: add Rolling Wireless RN947R Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] net: usb: rtl8150: handle link status read failures Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.1] net: prestera: ignore duplicate RIF destruction events Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] net: dsa: mt7530: error out on failed PHY_IAC command writes Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.6] tap: fix incorrect variable used for USO check in set_offload() Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.12] net: dsa: mt7530: check bus->read() error in core_rmw() Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] net/rds: unpin MR pages with unpin_user_pages_dirty_lock() Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18] netpoll: do not warn when the best-effort pool refill fails Sasha Levin
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18] net: libwx: disable TX VLAN offload for packets with >2 VLAN tags Sasha Levin
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18-6.6] net: sfp: add quirk for HORACO copper SFP+ module Sasha Levin
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18-5.15] net: usb: cdc_ether: add quirk for AMI BMC stale link events Sasha Levin
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] sctp: auth: propagate HMAC calculation errors to callers Sasha Levin
2026-10-19 17:28 ` Eric Biggers
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] net/rds: fix rds_message leak in the rds_send_xmit() drop path Sasha Levin
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] selftests/net: fin_ack_lat: fix latency threshold typo Sasha Levin
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] netfilter: ebtables: bound num_counters like nentries in do_replace() Sasha Levin
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-6.6] xsk: account ring allocations to memcg Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.10] net: mvneta_bm: add suspend/resume support to prevent crash after resume Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.10] net: stmmac: use dma_addr_t for DMA addresses Sasha Levin
2026-10-19 13:51 ` Sasha Levin [this message]
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.10] netfilter: nf_tables: call skb_valid_dst() before skb_dst() Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.15] net: stmmac: raise TX completion interrupt at the end of an xmit burst Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-6.6] net: pcs: mtk-lynxi: check regmap reads in mtk_pcs_lynxi_get_state() Sasha Levin
2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-5.10] net/rds: hold the socket while an rds_mr references it Sasha Levin
2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-6.12] sfc: add X4D PF support Sasha Levin
2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-6.1] netfilter: tproxy: use DEBUG_NET_WARN_ON_ONCE for protocol fallbacks Sasha Levin
2026-10-19 13:53 ` [PATCH AUTOSEL 6.18-6.12] net: ethernet: mtk_wed: increase WED v2 WDMA RESV_BUFF to 0x80 Sasha Levin
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=20261019135441.1420968-401-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=edumazet@kernel.org \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=patches@lists.linux.dev \
--cc=stable@vger.kernel.org \
/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