* [PATCH net-next v4] erspan: drop packets with an unknown ERSPAN version
@ 2026-11-10 15:28 Haishuang Yan
2026-11-15 12:36 ` Ido Schimmel
2026-11-15 19:50 ` patchwork-bot+netdevbpf
0 siblings, 2 replies; 3+ messages in thread
From: Haishuang Yan @ 2026-11-10 15:28 UTC (permalink / raw)
To: netdev
Cc: David Ahern, Ido Schimmel, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, William Tu,
linux-kernel
The ERSPAN type II and III receive paths take the length of the ERSPAN
header from the version field of the packet, with erspan_hdr_len(), but
never check that the version is one they know: 1 for type II or 2 for
type III.
For any other version, erspan_hdr_len() returns 0 or the type III
length. With version 0, the ERSPAN header is not pulled, so it is
passed up as the start of the inner Ethernet frame, and in collect_md
mode the metadata is filled from the wrong part of the header. The
ETH_HLEN pull in __iptunnel_pull_header() still covers the bytes that
are copied, so nothing is read past the pulled data.
Reject such packets, as a packet with a truncated ERSPAN header already
is.
On IPv4, a packet with a 4-byte GRE header is taken as type I without
looking at the protocol. gre_parse_header() treats an ETH_P_ERSPAN2
packet as carrying an ERSPAN header whatever the GRE header length,
but erspan_rcv() then skips that header's version and passes it up as
the inner frame. Type I only uses ETH_P_ERSPAN, so check the protocol
too. Such a packet now goes through the type III path and its version
check.
IPv6 has no type I, but ip6erspan_rcv() does not reject a type I
packet, an ETH_P_ERSPAN packet with a 4-byte GRE header. Such a packet
has no ERSPAN header, so the version is read from the inner destination
MAC address, and if that happens to be 1 or 2, the start of the inner
frame is stripped as an ERSPAN header. Reject these packets too.
Signed-off-by: Haishuang Yan <yanhaishuang@cmss.chinamobile.com>
---
The issue was found with the help of an AI coding assistant.
Tested on x86_64 with ip_gre and ip6_gre built from net-next
fa5196392691 with this patch, by sending hand-built GRE/ERSPAN packets
over a veth into erspan and ip6erspan devices, in plain and collect_md
mode: version 0 packets, ERSPAN2 packets with a 4-byte GRE header and
version 0 or 3, and on IPv6 type I packets whose inner destination MAC
starts with 0x1 or 0x2 are now dropped. Version 1 and 2 packets and
IPv4 type I packets are unchanged, and erspan v1/v2 ping over IPv4 and
IPv6 still works.
v4:
- Also reject type I packets in ip6erspan_rcv() (Sashiko).
v3: https://lore.kernel.org/netdev/20261108193504.73393-1-yanhaishuang@cmss.chinamobile.com/
- Also check the protocol when classifying a packet as type I, so that
an ETH_P_ERSPAN2 packet with a 4-byte GRE header gets the version
check too (Sashiko).
v2: https://lore.kernel.org/netdev/20261107130030.35220-1-yanhaishuang@cmss.chinamobile.com/
- Drop the Fixes tags and correct the commit message: the ETH_HLEN pull
of __iptunnel_pull_header() covers the metadata copy, so there is no
out of bounds read (Ido, Sashiko).
- Drop the patch that skipped the type III sub-header, as no device is
known to send it (Ido).
v1: https://lore.kernel.org/netdev/20261018090236.2487997-1-yanhaishuang@cmss.chinamobile.com/
net/ipv4/ip_gre.c | 12 +++++++-----
net/ipv6/ip6_gre.c | 9 +++++++++
2 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 5485586fa0e6..f8a7c4353502 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -255,13 +255,13 @@ static void gre_err(struct sk_buff *skb, u32 info)
ipgre_err(skb, info, &tpi);
}
-static bool is_erspan_type1(int gre_hdr_len)
+static bool is_erspan_type1(const struct tnl_ptk_info *tpi, int gre_hdr_len)
{
/* Both ERSPAN type I (version 0) and type II (version 1) use
* protocol 0x88BE, but the type I has only 4-byte GRE header,
* while type II has 8-byte.
*/
- return gre_hdr_len == 4;
+ return tpi->proto == htons(ETH_P_ERSPAN) && gre_hdr_len == 4;
}
static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
@@ -282,7 +282,7 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
itn = net_generic(net, erspan_net_id);
iph = ip_hdr(skb);
- if (is_erspan_type1(gre_hdr_len)) {
+ if (is_erspan_type1(tpi, gre_hdr_len)) {
ver = 0;
__set_bit(IP_TUNNEL_NO_KEY_BIT, flags);
tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, flags,
@@ -301,10 +301,12 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
}
if (tunnel) {
- if (is_erspan_type1(gre_hdr_len))
+ if (is_erspan_type1(tpi, gre_hdr_len))
len = gre_hdr_len;
- else
+ else if (ver == ERSPAN_VERSION || ver == ERSPAN_VERSION2)
len = gre_hdr_len + erspan_hdr_len(ver);
+ else
+ return PACKET_REJECT;
if (unlikely(!pskb_may_pull(skb, len)))
return PACKET_REJECT;
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index b5d6ed8f0c36..26c0e1c4de18 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -494,6 +494,12 @@ static int ip6erspan_rcv(struct sk_buff *skb,
struct ip6_tnl *tunnel;
u8 ver;
+ /* There is no type I (ETH_P_ERSPAN with a 4-byte GRE header) on
+ * IPv6, and such a packet carries no ERSPAN header to look at.
+ */
+ if (unlikely(tpi->proto == htons(ETH_P_ERSPAN) && gre_hdr_len == 4))
+ return PACKET_REJECT;
+
if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr))))
return PACKET_REJECT;
@@ -507,6 +513,9 @@ static int ip6erspan_rcv(struct sk_buff *skb,
if (tunnel) {
int len = erspan_hdr_len(ver);
+ if (unlikely(ver != ERSPAN_VERSION && ver != ERSPAN_VERSION2))
+ return PACKET_REJECT;
+
if (unlikely(!pskb_may_pull(skb, len)))
return PACKET_REJECT;
base-commit: fa5196392691051963726787944db872420dfa75
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH net-next v4] erspan: drop packets with an unknown ERSPAN version
2026-11-10 15:28 [PATCH net-next v4] erspan: drop packets with an unknown ERSPAN version Haishuang Yan
@ 2026-11-15 12:36 ` Ido Schimmel
2026-11-15 19:50 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: Ido Schimmel @ 2026-11-15 12:36 UTC (permalink / raw)
To: Haishuang Yan
Cc: netdev, David Ahern, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, William Tu,
linux-kernel
On Wed, Nov 11, 2026 at 12:28:48AM +0900, Haishuang Yan wrote:
> The ERSPAN type II and III receive paths take the length of the ERSPAN
> header from the version field of the packet, with erspan_hdr_len(), but
> never check that the version is one they know: 1 for type II or 2 for
> type III.
>
> For any other version, erspan_hdr_len() returns 0 or the type III
> length. With version 0, the ERSPAN header is not pulled, so it is
> passed up as the start of the inner Ethernet frame, and in collect_md
> mode the metadata is filled from the wrong part of the header. The
> ETH_HLEN pull in __iptunnel_pull_header() still covers the bytes that
> are copied, so nothing is read past the pulled data.
>
> Reject such packets, as a packet with a truncated ERSPAN header already
> is.
>
> On IPv4, a packet with a 4-byte GRE header is taken as type I without
> looking at the protocol. gre_parse_header() treats an ETH_P_ERSPAN2
> packet as carrying an ERSPAN header whatever the GRE header length,
> but erspan_rcv() then skips that header's version and passes it up as
> the inner frame. Type I only uses ETH_P_ERSPAN, so check the protocol
> too. Such a packet now goes through the type III path and its version
> check.
>
> IPv6 has no type I, but ip6erspan_rcv() does not reject a type I
> packet, an ETH_P_ERSPAN packet with a 4-byte GRE header. Such a packet
> has no ERSPAN header, so the version is read from the inner destination
> MAC address, and if that happens to be 1 or 2, the start of the inner
> frame is stripped as an ERSPAN header. Reject these packets too.
>
> Signed-off-by: Haishuang Yan <yanhaishuang@cmss.chinamobile.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net-next v4] erspan: drop packets with an unknown ERSPAN version
2026-11-10 15:28 [PATCH net-next v4] erspan: drop packets with an unknown ERSPAN version Haishuang Yan
2026-11-15 12:36 ` Ido Schimmel
@ 2026-11-15 19:50 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-11-15 19:50 UTC (permalink / raw)
To: Haishuang Yan
Cc: netdev, dsahern, idosch, davem, edumazet, kuba, pabeni, horms,
witu, linux-kernel
Hello:
This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 11 Nov 2026 00:28:48 +0900 you wrote:
> The ERSPAN type II and III receive paths take the length of the ERSPAN
> header from the version field of the packet, with erspan_hdr_len(), but
> never check that the version is one they know: 1 for type II or 2 for
> type III.
>
> For any other version, erspan_hdr_len() returns 0 or the type III
> length. With version 0, the ERSPAN header is not pulled, so it is
> passed up as the start of the inner Ethernet frame, and in collect_md
> mode the metadata is filled from the wrong part of the header. The
> ETH_HLEN pull in __iptunnel_pull_header() still covers the bytes that
> are copied, so nothing is read past the pulled data.
>
> [...]
Here is the summary with links:
- [net-next,v4] erspan: drop packets with an unknown ERSPAN version
https://git.kernel.org/netdev/net-next/c/7ccc5e05043b
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-11-15 19:50 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-10 15:28 [PATCH net-next v4] erspan: drop packets with an unknown ERSPAN version Haishuang Yan
2026-11-15 12:36 ` Ido Schimmel
2026-11-15 19:50 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox