Netdev List
 help / color / mirror / Atom feed
* [PATCH net 0/5] net: reject short linear Ethernet headers from tc actions, tun and OVS
@ 2026-10-22  9:22 Jamal Hadi Salim
  2026-10-22  9:22 ` [PATCH net 1/5] net/sched: act_vlan: reject short linear Ethernet headers after POP_ETH Jamal Hadi Salim
  0 siblings, 1 reply; 19+ messages in thread
From: Jamal Hadi Salim @ 2026-10-22  9:22 UTC (permalink / raw)
  To: netdev
  Cc: Jamal Hadi Salim, Jiri Pirko, Victor Nogueira, Vega, Andrew Lunn,
	David S . Miller, Eric Dumazet, Guillaume Nault, Simon Horman,
	Paolo Abeni, Jakub Kicinski, Herbert Xu, Jason Wang,
	Willem de Bruijn, Ren Wei, Aaron Conole, Eelco Chaudron,
	Ilya Maximets, Martin Varghese, Eric Garver, Yi Yang, Jiri Benc,
	dev

A recent flurry of bug fixes for dealing with kernel crashes around
eth_type_trans() showed up on the list. The earliest attempt to fix
this came from Ren Wei <n05ec@lzu.edu.cn>. There are many others
(but i lost track of them). Ren Wei's latest attempt hit a roadblock
with a NACK from Eric[1] asking to fix at the "producers"

These producers can hand a packet to a shared consumer with less than a
full Ethernet header in the linear area.
This series identifies and fixes the following producers:

  1. act_vlan POP_ETH rejects a short linear Ethernet header at the tc
     action boundary.
  2. act_mpls POP does the same, standalone or chained after POP_ETH.
  3. tun keeps the no-offload copy hint safe (raising a short hint instead
     of rejecting a valid write) while guaranteeing a linear Ethernet
     header for the redirected consumer.
  4. OVS pop_mpls(ETH_P_TEB) pulls the inner Ethernet header before
     restoring MAC_PROTO_ETHERNET.
  5. OVS pop_nsh(TUN_P_ETHERNET) does the same for the NSH producer.

1: https://lore.kernel.org/netdev/e85fa16e-df3c-43dd-bb3a-9edca07200ea@kernel.org/
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>

Jamal Hadi Salim (5):
  net/sched: act_vlan: reject short linear Ethernet headers after POP_ETH
  net/sched: act_mpls: reject short linear Ethernet headers after pop
  net: tun: keep TUN short linear copy hints safe
  net: openvswitch: ensure a linear inner Ethernet header on TEB pop
  net: openvswitch: ensure a linear inner Ethernet header on NSH pop

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH net 1/5] net/sched: act_vlan: reject short linear Ethernet headers after POP_ETH
  2026-10-22  9:22 [PATCH net 0/5] net: reject short linear Ethernet headers from tc actions, tun and OVS Jamal Hadi Salim
@ 2026-10-22  9:22 ` Jamal Hadi Salim
  2026-10-22  9:22   ` [PATCH net 2/5] net/sched: act_mpls: reject short linear Ethernet headers after pop Jamal Hadi Salim
  2026-10-22 15:21   ` [PATCH net 1/5] net/sched: act_vlan: reject short linear Ethernet headers after POP_ETH Willem de Bruijn
  0 siblings, 2 replies; 19+ messages in thread
From: Jamal Hadi Salim @ 2026-10-22  9:22 UTC (permalink / raw)
  To: netdev
  Cc: Jamal Hadi Salim, Jiri Pirko, Andrew Lunn, David S . Miller,
	Eric Dumazet, Guillaume Nault, Simon Horman, Paolo Abeni,
	Jakub Kicinski, Victor Nogueira, Vega, Ren Wei, Herbert Xu,
	Jason Wang, Willem de Bruijn, stable

The issue:
act_vlan POP_ETH can leave a linear area shorter than ETH_HLEN; a
subsequent eth_type_trans() may then BUG in __skb_pull() when the frame
is redirected to an Ethernet device.

The Fix:
Drop the packet at the producer boundary when skb_headlen() is shorter
than ETH_HLEN after skb_eth_pop().

Conditions to recreate the bug:
- egress tc filter on lo: action vlan pop_eth.
- AF_PACKET SOCK_RAW with PACKET_VNET_HDR, hdr_len=28, and a non-linear
  eth / inner-eth frame.
- The pop leaves skb_headlen(skb) < ETH_HLEN; a following
  eth_type_trans() can BUG in __skb_pull().

Fixes: 19fbcb36a39e ("net/sched: act_vlan: Add {POP,PUSH}_ETH actions")
Reported-by: Vega <vega@nebusec.ai>
Link: https://lore.kernel.org/r/40fe2d7dfce13411bfbe9271c0f7c54fb7e88e3b.1782548651.git.bronzed_45_vested@icloud.com/
Cc: stable@vger.kernel.org
Suggested-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
 net/sched/act_vlan.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index 6a375fdc63dd..ddf03b08bfe8 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -79,6 +79,8 @@ TC_INDIRECT_SCOPE int tcf_vlan_act(struct sk_buff *skb,
 		err = skb_eth_pop(skb);
 		if (err)
 			goto drop;
+		if (unlikely(skb_headlen(skb) < ETH_HLEN))
+			goto drop;
 		break;
 	case TCA_VLAN_ACT_PUSH_ETH:
 		err = skb_eth_push(skb, p->tcfv_push_dst, p->tcfv_push_src);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH net 2/5] net/sched: act_mpls: reject short linear Ethernet headers after pop
  2026-10-22  9:22 ` [PATCH net 1/5] net/sched: act_vlan: reject short linear Ethernet headers after POP_ETH Jamal Hadi Salim
@ 2026-10-22  9:22   ` Jamal Hadi Salim
  2026-10-22  9:22     ` [PATCH net 3/5] net: tun: keep TUN short linear copy hints safe Jamal Hadi Salim
  2026-10-22 17:52     ` [PATCH net 2/5] net/sched: act_mpls: reject short linear Ethernet headers after pop Eric Dumazet
  2026-10-22 15:21   ` [PATCH net 1/5] net/sched: act_vlan: reject short linear Ethernet headers after POP_ETH Willem de Bruijn
  1 sibling, 2 replies; 19+ messages in thread
From: Jamal Hadi Salim @ 2026-10-22  9:22 UTC (permalink / raw)
  To: netdev
  Cc: Jamal Hadi Salim, Jiri Pirko, Victor Nogueira, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Martin Varghese, Pravin B Shelar, Vega, stable

The issue:
act_mpls POP can leave fewer than ETH_HLEN linear bytes after
skb_mpls_pop(), either standalone on an Ethernet device or chained after
act_vlan POP_ETH.  A subsequent eth_type_trans() can then BUG in
__skb_pull().

The Fix:
After the pop, when the skb started as MPLS, drop it if the linear head
is shorter than ETH_HLEN.  Non-MPLS pops and pushes are unaffected.

Conditions to recreate the bug:
- egress tc filter on lo: action mpls pop (standalone), or
  action vlan pop_eth action mpls pop (chained).
- AF_PACKET SOCK_RAW with PACKET_VNET_HDR, hdr_len=28, and a non-linear
  eth / mpls / inner-eth frame.
- The pop leaves skb_headlen(skb) < ETH_HLEN; a following
  eth_type_trans() can BUG in __skb_pull().

Fixes: 040b5cfbcefa ("Fixed updating of ethertype in function skb_mpls_pop")
Reported-by: Vega <vega@nebusec.ai>
Link: https://lore.kernel.org/r/40fe2d7dfce13411bfbe9271c0f7c54fb7e88e3b.1782548651.git.bronzed_45_vested@icloud.com/
Cc: stable@vger.kernel.org
Suggested-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
 net/sched/act_mpls.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/sched/act_mpls.c b/net/sched/act_mpls.c
index 4ea8b2e08c3a..4d375033400b 100644
--- a/net/sched/act_mpls.c
+++ b/net/sched/act_mpls.c
@@ -57,6 +57,7 @@ TC_INDIRECT_SCOPE int tcf_mpls_act(struct sk_buff *skb,
 	struct tcf_mpls *m = to_mpls(a);
 	struct tcf_mpls_params *p;
 	__be32 new_lse;
+	bool was_mpls;
 	int mac_len;
 
 	tcf_lastuse_update(&m->tcf_tm);
@@ -76,9 +77,12 @@ TC_INDIRECT_SCOPE int tcf_mpls_act(struct sk_buff *skb,
 
 	switch (p->tcfm_action) {
 	case TCA_MPLS_ACT_POP:
+		was_mpls = eth_p_mpls(skb->protocol);
 		if (skb_mpls_pop(skb, p->tcfm_proto, mac_len,
 				 skb->dev && skb->dev->type == ARPHRD_ETHER))
 			goto drop;
+		if (was_mpls && unlikely(skb_headlen(skb) < ETH_HLEN))
+			goto drop;
 		break;
 	case TCA_MPLS_ACT_PUSH:
 		new_lse = tcf_mpls_get_lse(NULL, p, !eth_p_mpls(skb_protocol(skb, true)));
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH net 3/5] net: tun: keep TUN short linear copy hints safe
  2026-10-22  9:22   ` [PATCH net 2/5] net/sched: act_mpls: reject short linear Ethernet headers after pop Jamal Hadi Salim
@ 2026-10-22  9:22     ` Jamal Hadi Salim
  2026-10-22  9:22       ` [PATCH net 4/5] net: openvswitch: ensure a linear inner Ethernet header on TEB pop Jamal Hadi Salim
  2026-10-22 15:22       ` [PATCH net 3/5] net: tun: keep TUN short linear copy hints safe Willem de Bruijn
  2026-10-22 17:52     ` [PATCH net 2/5] net/sched: act_mpls: reject short linear Ethernet headers after pop Eric Dumazet
  1 sibling, 2 replies; 19+ messages in thread
From: Jamal Hadi Salim @ 2026-10-22  9:22 UTC (permalink / raw)
  To: netdev
  Cc: Jamal Hadi Salim, Willem de Bruijn, Jason Wang, Andrew Lunn,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Rusty Russell, Max Krasnyansky, Jiri Pirko, Victor Nogueira,
	stable

The issue:
A TUN skb can be redirected by tc mirred to an Ethernet xmit path, which
calls eth_type_trans() and needs a full Ethernet header in the linear
area.  tun_get_user() currently validates len and the GSO header length
only for IFF_TAP, so an IFF_TUN | IFF_VNET_HDR packet can set hdr_len to
1..13 and leave fewer than ETH_HLEN linear bytes.  The redirected packet
then BUGs in eth_type_trans().

The Fix:
Reject packets shorter than ETH_HLEN in both modes.  For IFF_TUN, where
hdr_len is only an allocation/copy hint when GSO and checksum offload are
off, raise a short nonzero hdr_len to ETH_HLEN instead of rejecting the
write.  Keep the TAP rejection and its NET_IP_ALIGN adjustment unchanged.
This preserves valid no-offload TUN writes with hints below ETH_HLEN while
guaranteeing at least ETH_HLEN linear bytes for the redirected consumer.

The maximum receive headroom advertised through tun_set_headroom() must
reserve the same linear minimum.  A large upper-device needed_headroom
(for example an L2 netkit port behind a VLAN in an OVS datapath) otherwise
caps good_linear below ETH_HLEN and defeats the clamp.  Reserve ETH_HLEN
for TUN; the TAP branch already reserves ETH_HLEN + NET_IP_ALIGN.

Conditions to recreate the bug (repro available):
- create a TUN device with IFF_TUN | IFF_VNET_HDR | IFF_NO_PI;
- attach ingress mirred egress redirect dev lo;
- write a virtio_net_hdr with hdr_len=1 and an 8192-byte payload.
Unfixed kernel will panic in eth_type_trans via loopback_xmit.
In a fixed kernel the write is accepted with hdr_len clamped to ETH_HLEN and the
packet is forwarded without a BUG.
- no-offload acceptance: a separate check writes a 28-byte IPv4/UDP-shaped
  packet with hdr_len 0, 1, 13, 14 and 20; all writes are accepted.
- high headroom: create an L2 netkit pair with headroom 4096, put a VLAN
  over it, and add both the VLAN and the TUN to one OVS datapath so the
  TUN receive headroom is raised to 4100.  The same hdr_len=1 jumbo must
  keep at least ETH_HLEN linear bytes; without the setter reservation it
  still BUGs.

Fixes: f42157cb568c ("tun: fallback if skb_alloc() fails on big packets")
Cc: stable@vger.kernel.org
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
 drivers/net/tun.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 242899f7fd07..1e235c2f0aee 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1193,7 +1193,7 @@ static void tun_set_headroom(struct net_device *dev, int new_hr)
 	if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP)
 		max_headroom -= ETH_HLEN + NET_IP_ALIGN;
 	else
-		max_headroom -= 1;
+		max_headroom -= ETH_HLEN;
 
 	tun->align = clamp_t(int, new_hr, NET_SKB_PAD, max_headroom);
 }
@@ -1830,6 +1830,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
 		align += NET_IP_ALIGN;
 		if (unlikely(len < ETH_HLEN || (hdr_len && hdr_len < ETH_HLEN)))
 			return -EINVAL;
+	} else {
+		if (unlikely(len < ETH_HLEN))
+			return -EINVAL;
+		if (hdr_len)
+			hdr_len = max_t(int, hdr_len, ETH_HLEN);
 	}
 
 	good_linear = SKB_MAX_HEAD(align);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH net 4/5] net: openvswitch: ensure a linear inner Ethernet header on TEB pop
  2026-10-22  9:22     ` [PATCH net 3/5] net: tun: keep TUN short linear copy hints safe Jamal Hadi Salim
@ 2026-10-22  9:22       ` Jamal Hadi Salim
  2026-10-22  9:22         ` [PATCH net 5/5] net: openvswitch: ensure a linear inner Ethernet header on NSH pop Jamal Hadi Salim
  2026-10-22 12:41         ` [PATCH net 4/5] net: openvswitch: ensure a linear inner Ethernet header on TEB pop Ilya Maximets
  2026-10-22 15:22       ` [PATCH net 3/5] net: tun: keep TUN short linear copy hints safe Willem de Bruijn
  1 sibling, 2 replies; 19+ messages in thread
From: Jamal Hadi Salim @ 2026-10-22  9:22 UTC (permalink / raw)
  To: netdev
  Cc: Jamal Hadi Salim, Aaron Conole, Eelco Chaudron, Ilya Maximets,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Pravin B Shelar, Martin Varghese, Jiri Pirko,
	Victor Nogueira, dev, stable

The issue:
pop_mpls() restores MAC_PROTO_ETHERNET when the popped ethertype is
ETH_P_TEB, but skb_mpls_pop() only guarantees that the MPLS shim is in
the linear area.  When the inner Ethernet header sits in a page
fragment, the datapath now claims an Ethernet header it cannot access
linearly.

Output to an OVS internal vport then calls eth_type_trans(), which
pulls ETH_HLEN from an empty linear area and triggers the BUG in
__skb_pull():

  kernel BUG at ./include/linux/skbuff.h:2830!
  RIP: 0010:eth_type_trans+0x335/0x500
  internal_dev_recv
  ovs_vport_send
  do_output
  do_execute_actions
  ovs_execute_actions
  ovs_dp_process_packet
  ovs_vport_receive
  internal_dev_xmit

Conditions to recreate the bug:
On a system with 4 KiB pages and CONFIG_OPENVSWITCH and CONFIG_PACKET
enabled, use CAP_NET_ADMIN to create an OVS datapath and bring its local
internal port up with MTU 9000.  Install a flow matching an Ethernet/MPLS
packet with one bottom-of-stack label and actions pop_eth,
pop_mpls(0x6558), output to the local port.  With CAP_NET_RAW, send a
4128-byte AF_PACKET/SOCK_RAW frame containing outer Ethernet, the MPLS
label, inner Ethernet and 4096 payload bytes.  The two pops consume the
linear headers and expose the inner Ethernet header in page fragments.

The Fix:
Pull the inner Ethernet header into the linear area before restoring
MAC_PROTO_ETHERNET.

Fixes: f66b53fdbb22 ("openvswitch: New MPLS actions for layer 2 tunnelling")
Link: https://lore.kernel.org/netdev/e85fa16e-df3c-43dd-bb3a-9edca07200ea@kernel.org/
Cc: stable@vger.kernel.org
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
 net/openvswitch/actions.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 27152bca8a8c..03b31e33e880 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -153,8 +153,11 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
 	if (err)
 		return err;
 
-	if (ethertype == htons(ETH_P_TEB))
+	if (ethertype == htons(ETH_P_TEB)) {
+		if (!pskb_may_pull(skb, ETH_HLEN))
+			return -ENOMEM;
 		key->mac_proto = MAC_PROTO_ETHERNET;
+	}
 
 	invalidate_flow_key(key);
 	return 0;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH net 5/5] net: openvswitch: ensure a linear inner Ethernet header on NSH pop
  2026-10-22  9:22       ` [PATCH net 4/5] net: openvswitch: ensure a linear inner Ethernet header on TEB pop Jamal Hadi Salim
@ 2026-10-22  9:22         ` Jamal Hadi Salim
  2026-10-22  9:54           ` Jiri Benc
  2026-10-22 12:42           ` Ilya Maximets
  2026-10-22 12:41         ` [PATCH net 4/5] net: openvswitch: ensure a linear inner Ethernet header on TEB pop Ilya Maximets
  1 sibling, 2 replies; 19+ messages in thread
From: Jamal Hadi Salim @ 2026-10-22  9:22 UTC (permalink / raw)
  To: netdev
  Cc: Jamal Hadi Salim, Aaron Conole, Eelco Chaudron, Ilya Maximets,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Eric Garver, Yi Yang, Jiri Benc, Pravin Shelar,
	Jiri Pirko, Victor Nogueira, dev, stable

The issue:
pop_nsh() restores MAC_PROTO_ETHERNET when the popped NSH next-protocol
is TUN_P_ETHERNET, but nsh_pop() only guarantees that the NSH header is
in the linear area.  When the inner Ethernet header sits in a page
fragment, the datapath then claims an Ethernet header it cannot access
linearly.

Output to an OVS internal vport then calls eth_type_trans(), which
pulls ETH_HLEN from an empty linear area and triggers the BUG in
__skb_pull():

  kernel BUG at ./include/linux/skbuff.h:2830!
  RIP: 0010:eth_type_trans+0x335/0x500
  internal_dev_recv
  ovs_vport_send
  do_output
  do_execute_actions
  ovs_execute_actions
  ovs_dp_process_packet
  ovs_vport_receive
  internal_dev_xmit

Conditions to recreate the bug:
On a system with 4 KiB pages and CONFIG_OPENVSWITCH and CONFIG_PACKET
enabled, use CAP_NET_ADMIN to create an OVS datapath and bring its local
internal port up with MTU 9000.  Install a flow matching an Ethernet/NSH
packet with a 24-byte MD1 header whose next-protocol is TUN_P_ETHERNET,
and actions pop_eth, pop_nsh, output to the local port.  With
CAP_NET_RAW, send a 4148-byte AF_PACKET/SOCK_RAW frame containing outer
Ethernet, the NSH header, inner Ethernet and 4096 payload bytes.  The
two pops consume the linear headers and expose the inner Ethernet header
in page fragments.

The fix:
Pull the inner Ethernet header into the linear area before restoring
MAC_PROTO_ETHERNET.  This is the NSH counterpart of the MPLS/TEB
producer fix in the previous patch.

Fixes: b2d0f5d5dc53 ("openvswitch: enable NSH support")
Link: https://lore.kernel.org/netdev/e85fa16e-df3c-43dd-bb3a-9edca07200ea@kernel.org/
Cc: stable@vger.kernel.org
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
 net/openvswitch/actions.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 03b31e33e880..cb7e16c6a8ef 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -314,10 +314,13 @@ static int pop_nsh(struct sk_buff *skb, struct sw_flow_key *key)
 		return err;
 
 	/* safe right before invalidate_flow_key */
-	if (skb->protocol == htons(ETH_P_TEB))
+	if (skb->protocol == htons(ETH_P_TEB)) {
+		if (!pskb_may_pull(skb, ETH_HLEN))
+			return -ENOMEM;
 		key->mac_proto = MAC_PROTO_ETHERNET;
-	else
+	} else {
 		key->mac_proto = MAC_PROTO_NONE;
+	}
 	invalidate_flow_key(key);
 	return 0;
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH net 5/5] net: openvswitch: ensure a linear inner Ethernet header on NSH pop
  2026-10-22  9:22         ` [PATCH net 5/5] net: openvswitch: ensure a linear inner Ethernet header on NSH pop Jamal Hadi Salim
@ 2026-10-22  9:54           ` Jiri Benc
  2026-10-22 12:42           ` Ilya Maximets
  1 sibling, 0 replies; 19+ messages in thread
From: Jiri Benc @ 2026-10-22  9:54 UTC (permalink / raw)
  To: Jamal Hadi Salim
  Cc: netdev, Aaron Conole, Eelco Chaudron, Ilya Maximets,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Yi Yang, Pravin Shelar, Jiri Pirko, Victor Nogueira,
	dev, stable

On Thu, 22 Oct 2026 05:22:22 -0400, Jamal Hadi Salim wrote:
> The fix:
> Pull the inner Ethernet header into the linear area before restoring
> MAC_PROTO_ETHERNET.  This is the NSH counterpart of the MPLS/TEB
> producer fix in the previous patch.
> 
> Fixes: b2d0f5d5dc53 ("openvswitch: enable NSH support")
> Link: https://lore.kernel.org/netdev/e85fa16e-df3c-43dd-bb3a-9edca07200ea@kernel.org/
> Cc: stable@vger.kernel.org
> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>

Reviewed-by: Jiri Benc <jbenc@redhat.com>


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net 4/5] net: openvswitch: ensure a linear inner Ethernet header on TEB pop
  2026-10-22  9:22       ` [PATCH net 4/5] net: openvswitch: ensure a linear inner Ethernet header on TEB pop Jamal Hadi Salim
  2026-10-22  9:22         ` [PATCH net 5/5] net: openvswitch: ensure a linear inner Ethernet header on NSH pop Jamal Hadi Salim
@ 2026-10-22 12:41         ` Ilya Maximets
  2026-10-22 17:47           ` Eric Dumazet
  1 sibling, 1 reply; 19+ messages in thread
From: Ilya Maximets @ 2026-10-22 12:41 UTC (permalink / raw)
  To: Jamal Hadi Salim, netdev
  Cc: Aaron Conole, Eelco Chaudron, Ilya Maximets, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Martin Varghese, Jiri Pirko, Victor Nogueira, dev, stable

On 10/22/26 11:22 AM, Jamal Hadi Salim wrote:
> The issue:
> pop_mpls() restores MAC_PROTO_ETHERNET when the popped ethertype is
> ETH_P_TEB, but skb_mpls_pop() only guarantees that the MPLS shim is in
> the linear area.  When the inner Ethernet header sits in a page
> fragment, the datapath now claims an Ethernet header it cannot access
> linearly.
> 
> Output to an OVS internal vport then calls eth_type_trans(), which
> pulls ETH_HLEN from an empty linear area and triggers the BUG in
> __skb_pull():
> 
>   kernel BUG at ./include/linux/skbuff.h:2830!
>   RIP: 0010:eth_type_trans+0x335/0x500
>   internal_dev_recv
>   ovs_vport_send
>   do_output
>   do_execute_actions
>   ovs_execute_actions
>   ovs_dp_process_packet
>   ovs_vport_receive
>   internal_dev_xmit
> 
> Conditions to recreate the bug:
> On a system with 4 KiB pages and CONFIG_OPENVSWITCH and CONFIG_PACKET
> enabled, use CAP_NET_ADMIN to create an OVS datapath and bring its local
> internal port up with MTU 9000.  Install a flow matching an Ethernet/MPLS
> packet with one bottom-of-stack label and actions pop_eth,
> pop_mpls(0x6558), output to the local port.  With CAP_NET_RAW, send a
> 4128-byte AF_PACKET/SOCK_RAW frame containing outer Ethernet, the MPLS
> label, inner Ethernet and 4096 payload bytes.  The two pops consume the
> linear headers and expose the inner Ethernet header in page fragments.
> 
> The Fix:
> Pull the inner Ethernet header into the linear area before restoring
> MAC_PROTO_ETHERNET.
> 
> Fixes: f66b53fdbb22 ("openvswitch: New MPLS actions for layer 2 tunnelling")
> Link: https://lore.kernel.org/netdev/e85fa16e-df3c-43dd-bb3a-9edca07200ea@kernel.org/
> Cc: stable@vger.kernel.org
> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> ---
>  net/openvswitch/actions.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
> index 27152bca8a8c..03b31e33e880 100644
> --- a/net/openvswitch/actions.c
> +++ b/net/openvswitch/actions.c
> @@ -153,8 +153,11 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
>  	if (err)
>  		return err;
>  
> -	if (ethertype == htons(ETH_P_TEB))
> +	if (ethertype == htons(ETH_P_TEB)) {
> +		if (!pskb_may_pull(skb, ETH_HLEN))
> +			return -ENOMEM;
>  		key->mac_proto = MAC_PROTO_ETHERNET;
> +	}
>  
>  	invalidate_flow_key(key);
>  	return 0;

Reviewed-by: Ilya Maximets <i.maximets@ovn.org>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net 5/5] net: openvswitch: ensure a linear inner Ethernet header on NSH pop
  2026-10-22  9:22         ` [PATCH net 5/5] net: openvswitch: ensure a linear inner Ethernet header on NSH pop Jamal Hadi Salim
  2026-10-22  9:54           ` Jiri Benc
@ 2026-10-22 12:42           ` Ilya Maximets
  2026-10-22 17:47             ` Eric Dumazet
  1 sibling, 1 reply; 19+ messages in thread
From: Ilya Maximets @ 2026-10-22 12:42 UTC (permalink / raw)
  To: Jamal Hadi Salim, netdev
  Cc: Aaron Conole, Eelco Chaudron, Ilya Maximets, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Eric Garver, Yi Yang, Jiri Benc, Pravin Shelar, Jiri Pirko,
	Victor Nogueira, dev, stable

On 10/22/26 11:22 AM, Jamal Hadi Salim wrote:
> The issue:
> pop_nsh() restores MAC_PROTO_ETHERNET when the popped NSH next-protocol
> is TUN_P_ETHERNET, but nsh_pop() only guarantees that the NSH header is
> in the linear area.  When the inner Ethernet header sits in a page
> fragment, the datapath then claims an Ethernet header it cannot access
> linearly.
> 
> Output to an OVS internal vport then calls eth_type_trans(), which
> pulls ETH_HLEN from an empty linear area and triggers the BUG in
> __skb_pull():
> 
>   kernel BUG at ./include/linux/skbuff.h:2830!
>   RIP: 0010:eth_type_trans+0x335/0x500
>   internal_dev_recv
>   ovs_vport_send
>   do_output
>   do_execute_actions
>   ovs_execute_actions
>   ovs_dp_process_packet
>   ovs_vport_receive
>   internal_dev_xmit
> 
> Conditions to recreate the bug:
> On a system with 4 KiB pages and CONFIG_OPENVSWITCH and CONFIG_PACKET
> enabled, use CAP_NET_ADMIN to create an OVS datapath and bring its local
> internal port up with MTU 9000.  Install a flow matching an Ethernet/NSH
> packet with a 24-byte MD1 header whose next-protocol is TUN_P_ETHERNET,
> and actions pop_eth, pop_nsh, output to the local port.  With
> CAP_NET_RAW, send a 4148-byte AF_PACKET/SOCK_RAW frame containing outer
> Ethernet, the NSH header, inner Ethernet and 4096 payload bytes.  The
> two pops consume the linear headers and expose the inner Ethernet header
> in page fragments.
> 
> The fix:
> Pull the inner Ethernet header into the linear area before restoring
> MAC_PROTO_ETHERNET.  This is the NSH counterpart of the MPLS/TEB
> producer fix in the previous patch.
> 
> Fixes: b2d0f5d5dc53 ("openvswitch: enable NSH support")
> Link: https://lore.kernel.org/netdev/e85fa16e-df3c-43dd-bb3a-9edca07200ea@kernel.org/
> Cc: stable@vger.kernel.org
> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> ---
>  net/openvswitch/actions.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
> index 03b31e33e880..cb7e16c6a8ef 100644
> --- a/net/openvswitch/actions.c
> +++ b/net/openvswitch/actions.c
> @@ -314,10 +314,13 @@ static int pop_nsh(struct sk_buff *skb, struct sw_flow_key *key)
>  		return err;
>  
>  	/* safe right before invalidate_flow_key */
> -	if (skb->protocol == htons(ETH_P_TEB))
> +	if (skb->protocol == htons(ETH_P_TEB)) {
> +		if (!pskb_may_pull(skb, ETH_HLEN))
> +			return -ENOMEM;
>  		key->mac_proto = MAC_PROTO_ETHERNET;
> -	else
> +	} else {
>  		key->mac_proto = MAC_PROTO_NONE;
> +	}
>  	invalidate_flow_key(key);
>  	return 0;
>  }

Reviewed-by: Ilya Maximets <i.maximets@ovn.org>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net 1/5] net/sched: act_vlan: reject short linear Ethernet headers after POP_ETH
  2026-10-22  9:22 ` [PATCH net 1/5] net/sched: act_vlan: reject short linear Ethernet headers after POP_ETH Jamal Hadi Salim
  2026-10-22  9:22   ` [PATCH net 2/5] net/sched: act_mpls: reject short linear Ethernet headers after pop Jamal Hadi Salim
@ 2026-10-22 15:21   ` Willem de Bruijn
  2026-10-22 16:01     ` Jamal Hadi Salim
  1 sibling, 1 reply; 19+ messages in thread
From: Willem de Bruijn @ 2026-10-22 15:21 UTC (permalink / raw)
  To: Jamal Hadi Salim, netdev
  Cc: Jamal Hadi Salim, Jiri Pirko, Andrew Lunn, David S . Miller,
	Eric Dumazet, Guillaume Nault, Simon Horman, Paolo Abeni,
	Jakub Kicinski, Victor Nogueira, Vega, Ren Wei, Herbert Xu,
	Jason Wang, Willem de Bruijn, stable

Jamal Hadi Salim wrote:
> The issue:
> act_vlan POP_ETH can leave a linear area shorter than ETH_HLEN; a
> subsequent eth_type_trans() may then BUG in __skb_pull() when the frame
> is redirected to an Ethernet device.
> 
> The Fix:
> Drop the packet at the producer boundary when skb_headlen() is shorter
> than ETH_HLEN after skb_eth_pop().
> 
> Conditions to recreate the bug:
> - egress tc filter on lo: action vlan pop_eth.
> - AF_PACKET SOCK_RAW with PACKET_VNET_HDR, hdr_len=28, and a non-linear
>   eth / inner-eth frame.
> - The pop leaves skb_headlen(skb) < ETH_HLEN; a following
>   eth_type_trans() can BUG in __skb_pull().
> 
> Fixes: 19fbcb36a39e ("net/sched: act_vlan: Add {POP,PUSH}_ETH actions")
> Reported-by: Vega <vega@nebusec.ai>
> Link: https://lore.kernel.org/r/40fe2d7dfce13411bfbe9271c0f7c54fb7e88e3b.1782548651.git.bronzed_45_vested@icloud.com/
> Cc: stable@vger.kernel.org
> Suggested-by: Jakub Kicinski <kuba@kernel.org>
> Reviewed-by: Victor Nogueira <victor@mojatatu.com>
> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> ---
>  net/sched/act_vlan.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
> index 6a375fdc63dd..ddf03b08bfe8 100644
> --- a/net/sched/act_vlan.c
> +++ b/net/sched/act_vlan.c
> @@ -79,6 +79,8 @@ TC_INDIRECT_SCOPE int tcf_vlan_act(struct sk_buff *skb,
>  		err = skb_eth_pop(skb);
>  		if (err)
>  			goto drop;
> +		if (unlikely(skb_headlen(skb) < ETH_HLEN))
> +			goto drop;

Could it try to pull the header and only drop if the packet is too short?

>  		break;
>  	case TCA_VLAN_ACT_PUSH_ETH:
>  		err = skb_eth_push(skb, p->tcfv_push_dst, p->tcfv_push_src);
> -- 
> 2.43.0
> 



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net 3/5] net: tun: keep TUN short linear copy hints safe
  2026-10-22  9:22     ` [PATCH net 3/5] net: tun: keep TUN short linear copy hints safe Jamal Hadi Salim
  2026-10-22  9:22       ` [PATCH net 4/5] net: openvswitch: ensure a linear inner Ethernet header on TEB pop Jamal Hadi Salim
@ 2026-10-22 15:22       ` Willem de Bruijn
  2026-10-22 16:17         ` Jamal Hadi Salim
  1 sibling, 1 reply; 19+ messages in thread
From: Willem de Bruijn @ 2026-10-22 15:22 UTC (permalink / raw)
  To: Jamal Hadi Salim, netdev
  Cc: Jamal Hadi Salim, Willem de Bruijn, Jason Wang, Andrew Lunn,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Rusty Russell, Max Krasnyansky, Jiri Pirko, Victor Nogueira,
	stable

Jamal Hadi Salim wrote:
> The issue:
> A TUN skb can be redirected by tc mirred to an Ethernet xmit path, which
> calls eth_type_trans() and needs a full Ethernet header in the linear
> area.  tun_get_user() currently validates len and the GSO header length
> only for IFF_TAP, so an IFF_TUN | IFF_VNET_HDR packet can set hdr_len to
> 1..13 and leave fewer than ETH_HLEN linear bytes.  The redirected packet
> then BUGs in eth_type_trans().

TUN mode does not imply Ethernet. Indeed, TUN implies an L3 packet?
> 
> The Fix:
> Reject packets shorter than ETH_HLEN in both modes.  For IFF_TUN, where
> hdr_len is only an allocation/copy hint when GSO and checksum offload are
> off, raise a short nonzero hdr_len to ETH_HLEN instead of rejecting the
> write.  Keep the TAP rejection and its NET_IP_ALIGN adjustment unchanged.
> This preserves valid no-offload TUN writes with hints below ETH_HLEN while
> guaranteeing at least ETH_HLEN linear bytes for the redirected consumer.
> 
> The maximum receive headroom advertised through tun_set_headroom() must
> reserve the same linear minimum.  A large upper-device needed_headroom
> (for example an L2 netkit port behind a VLAN in an OVS datapath) otherwise
> caps good_linear below ETH_HLEN and defeats the clamp.  Reserve ETH_HLEN
> for TUN; the TAP branch already reserves ETH_HLEN + NET_IP_ALIGN.
> 
> Conditions to recreate the bug (repro available):
> - create a TUN device with IFF_TUN | IFF_VNET_HDR | IFF_NO_PI;
> - attach ingress mirred egress redirect dev lo;
> - write a virtio_net_hdr with hdr_len=1 and an 8192-byte payload.
> Unfixed kernel will panic in eth_type_trans via loopback_xmit.
> In a fixed kernel the write is accepted with hdr_len clamped to ETH_HLEN and the
> packet is forwarded without a BUG.
> - no-offload acceptance: a separate check writes a 28-byte IPv4/UDP-shaped
>   packet with hdr_len 0, 1, 13, 14 and 20; all writes are accepted.
> - high headroom: create an L2 netkit pair with headroom 4096, put a VLAN
>   over it, and add both the VLAN and the TUN to one OVS datapath so the
>   TUN receive headroom is raised to 4100.  The same hdr_len=1 jumbo must
>   keep at least ETH_HLEN linear bytes; without the setter reservation it
>   still BUGs.
> 
> Fixes: f42157cb568c ("tun: fallback if skb_alloc() fails on big packets")
> Cc: stable@vger.kernel.org
> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> ---
>  drivers/net/tun.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> index 242899f7fd07..1e235c2f0aee 100644
> --- a/drivers/net/tun.c
> +++ b/drivers/net/tun.c
> @@ -1193,7 +1193,7 @@ static void tun_set_headroom(struct net_device *dev, int new_hr)
>  	if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP)
>  		max_headroom -= ETH_HLEN + NET_IP_ALIGN;
>  	else
> -		max_headroom -= 1;
> +		max_headroom -= ETH_HLEN;
>  
>  	tun->align = clamp_t(int, new_hr, NET_SKB_PAD, max_headroom);
>  }
> @@ -1830,6 +1830,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
>  		align += NET_IP_ALIGN;
>  		if (unlikely(len < ETH_HLEN || (hdr_len && hdr_len < ETH_HLEN)))
>  			return -EINVAL;
> +	} else {
> +		if (unlikely(len < ETH_HLEN))
> +			return -EINVAL;
> +		if (hdr_len)
> +			hdr_len = max_t(int, hdr_len, ETH_HLEN);
>  	}
>  
>  	good_linear = SKB_MAX_HEAD(align);
> -- 
> 2.43.0
> 



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net 1/5] net/sched: act_vlan: reject short linear Ethernet headers after POP_ETH
  2026-10-22 15:21   ` [PATCH net 1/5] net/sched: act_vlan: reject short linear Ethernet headers after POP_ETH Willem de Bruijn
@ 2026-10-22 16:01     ` Jamal Hadi Salim
  2026-10-22 17:57       ` Eric Dumazet
  0 siblings, 1 reply; 19+ messages in thread
From: Jamal Hadi Salim @ 2026-10-22 16:01 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: netdev, Jiri Pirko, Andrew Lunn, David S . Miller, Eric Dumazet,
	Guillaume Nault, Simon Horman, Paolo Abeni, Jakub Kicinski,
	Victor Nogueira, Vega, Ren Wei, Herbert Xu, Jason Wang, stable

On Thu, Oct 22, 2026 at 11:21 AM Willem de Bruijn
<willemdebruijn.kernel@gmail.com> wrote:
>
> Jamal Hadi Salim wrote:
> > The issue:
> > act_vlan POP_ETH can leave a linear area shorter than ETH_HLEN; a
> > subsequent eth_type_trans() may then BUG in __skb_pull() when the frame
> > is redirected to an Ethernet device.
> >
> > The Fix:
> > Drop the packet at the producer boundary when skb_headlen() is shorter
> > than ETH_HLEN after skb_eth_pop().
> >
> > Conditions to recreate the bug:
> > - egress tc filter on lo: action vlan pop_eth.
> > - AF_PACKET SOCK_RAW with PACKET_VNET_HDR, hdr_len=28, and a non-linear
> >   eth / inner-eth frame.
> > - The pop leaves skb_headlen(skb) < ETH_HLEN; a following
> >   eth_type_trans() can BUG in __skb_pull().
> >
> > Fixes: 19fbcb36a39e ("net/sched: act_vlan: Add {POP,PUSH}_ETH actions")
> > Reported-by: Vega <vega@nebusec.ai>
> > Link: https://lore.kernel.org/r/40fe2d7dfce13411bfbe9271c0f7c54fb7e88e3b.1782548651.git.bronzed_45_vested@icloud.com/
> > Cc: stable@vger.kernel.org
> > Suggested-by: Jakub Kicinski <kuba@kernel.org>
> > Reviewed-by: Victor Nogueira <victor@mojatatu.com>
> > Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> > ---
> >  net/sched/act_vlan.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
> > index 6a375fdc63dd..ddf03b08bfe8 100644
> > --- a/net/sched/act_vlan.c
> > +++ b/net/sched/act_vlan.c
> > @@ -79,6 +79,8 @@ TC_INDIRECT_SCOPE int tcf_vlan_act(struct sk_buff *skb,
> >               err = skb_eth_pop(skb);
> >               if (err)
> >                       goto drop;
> > +             if (unlikely(skb_headlen(skb) < ETH_HLEN))
> > +                     goto drop;
>
> Could it try to pull the header and only drop if the packet is too short?
>

What would be the benefit?
Note: the OVS patches pull because they must restore
MAC_PROTO_ETHERNET and already return an action error, i see a good
reason there.

cheers,
jamal

> >               break;
> >       case TCA_VLAN_ACT_PUSH_ETH:
> >               err = skb_eth_push(skb, p->tcfv_push_dst, p->tcfv_push_src);
> > --
> > 2.43.0
> >
>
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net 3/5] net: tun: keep TUN short linear copy hints safe
  2026-10-22 15:22       ` [PATCH net 3/5] net: tun: keep TUN short linear copy hints safe Willem de Bruijn
@ 2026-10-22 16:17         ` Jamal Hadi Salim
  2026-10-22 18:00           ` Eric Dumazet
  0 siblings, 1 reply; 19+ messages in thread
From: Jamal Hadi Salim @ 2026-10-22 16:17 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: netdev, Jason Wang, Andrew Lunn, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Rusty Russell, Max Krasnyansky,
	Jiri Pirko, Victor Nogueira, stable

On Thu, Oct 22, 2026 at 11:22 AM Willem de Bruijn
<willemdebruijn.kernel@gmail.com> wrote:
>
> Jamal Hadi Salim wrote:
> > The issue:
> > A TUN skb can be redirected by tc mirred to an Ethernet xmit path, which
> > calls eth_type_trans() and needs a full Ethernet header in the linear
> > area.  tun_get_user() currently validates len and the GSO header length
> > only for IFF_TAP, so an IFF_TUN | IFF_VNET_HDR packet can set hdr_len to
> > 1..13 and leave fewer than ETH_HLEN linear bytes.  The redirected packet
> > then BUGs in eth_type_trans().
>
> TUN mode does not imply Ethernet. Indeed, TUN implies an L3 packet?

I have a feeling i am missing something: True, TUN is L3  but we are
not adding or parsing eth headers to TUN.

The patch only bounds the linear copy hint and receive headroom so a
TUN skb redirected by tc to an some ethernet xmit path satisfies
eth_type_trans()'s precondition in the patchset. IOW, with current
code does it matter if TUN is l3? The other side will assume the
payload to be ethernet..
If the redirect itself should be rejected for TUN, that is a different
fix; earlier ask from Eric is to fix the producer not for example the
driver (like loopback).
The "reject redirect from TUN" could probably be done but i dont see a
cheap way of doing it.

Thoughts?

cheers,
jamal
> >
> > The Fix:
> > Reject packets shorter than ETH_HLEN in both modes.  For IFF_TUN, where
> > hdr_len is only an allocation/copy hint when GSO and checksum offload are
> > off, raise a short nonzero hdr_len to ETH_HLEN instead of rejecting the
> > write.  Keep the TAP rejection and its NET_IP_ALIGN adjustment unchanged.
> > This preserves valid no-offload TUN writes with hints below ETH_HLEN while
> > guaranteeing at least ETH_HLEN linear bytes for the redirected consumer.
> >
> > The maximum receive headroom advertised through tun_set_headroom() must
> > reserve the same linear minimum.  A large upper-device needed_headroom
> > (for example an L2 netkit port behind a VLAN in an OVS datapath) otherwise
> > caps good_linear below ETH_HLEN and defeats the clamp.  Reserve ETH_HLEN
> > for TUN; the TAP branch already reserves ETH_HLEN + NET_IP_ALIGN.
> >
> > Conditions to recreate the bug (repro available):
> > - create a TUN device with IFF_TUN | IFF_VNET_HDR | IFF_NO_PI;
> > - attach ingress mirred egress redirect dev lo;
> > - write a virtio_net_hdr with hdr_len=1 and an 8192-byte payload.
> > Unfixed kernel will panic in eth_type_trans via loopback_xmit.
> > In a fixed kernel the write is accepted with hdr_len clamped to ETH_HLEN and the
> > packet is forwarded without a BUG.
> > - no-offload acceptance: a separate check writes a 28-byte IPv4/UDP-shaped
> >   packet with hdr_len 0, 1, 13, 14 and 20; all writes are accepted.
> > - high headroom: create an L2 netkit pair with headroom 4096, put a VLAN
> >   over it, and add both the VLAN and the TUN to one OVS datapath so the
> >   TUN receive headroom is raised to 4100.  The same hdr_len=1 jumbo must
> >   keep at least ETH_HLEN linear bytes; without the setter reservation it
> >   still BUGs.
> >
> > Fixes: f42157cb568c ("tun: fallback if skb_alloc() fails on big packets")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> > ---
> >  drivers/net/tun.c | 7 ++++++-
> >  1 file changed, 6 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> > index 242899f7fd07..1e235c2f0aee 100644
> > --- a/drivers/net/tun.c
> > +++ b/drivers/net/tun.c
> > @@ -1193,7 +1193,7 @@ static void tun_set_headroom(struct net_device *dev, int new_hr)
> >       if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP)
> >               max_headroom -= ETH_HLEN + NET_IP_ALIGN;
> >       else
> > -             max_headroom -= 1;
> > +             max_headroom -= ETH_HLEN;
> >
> >       tun->align = clamp_t(int, new_hr, NET_SKB_PAD, max_headroom);
> >  }
> > @@ -1830,6 +1830,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
> >               align += NET_IP_ALIGN;
> >               if (unlikely(len < ETH_HLEN || (hdr_len && hdr_len < ETH_HLEN)))
> >                       return -EINVAL;
> > +     } else {
> > +             if (unlikely(len < ETH_HLEN))
> > +                     return -EINVAL;
> > +             if (hdr_len)
> > +                     hdr_len = max_t(int, hdr_len, ETH_HLEN);
> >       }
> >
> >       good_linear = SKB_MAX_HEAD(align);
> > --
> > 2.43.0
> >
>
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net 4/5] net: openvswitch: ensure a linear inner Ethernet header on TEB pop
  2026-10-22 12:41         ` [PATCH net 4/5] net: openvswitch: ensure a linear inner Ethernet header on TEB pop Ilya Maximets
@ 2026-10-22 17:47           ` Eric Dumazet
  0 siblings, 0 replies; 19+ messages in thread
From: Eric Dumazet @ 2026-10-22 17:47 UTC (permalink / raw)
  To: Ilya Maximets
  Cc: Jamal Hadi Salim, netdev, Aaron Conole, Eelco Chaudron,
	David S . Miller, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Martin Varghese, Jiri Pirko, Victor Nogueira, dev, stable

Le jeu. 22 oct. 2026 à 14:42, Ilya Maximets <i.maximets@ovn.org> a écrit :
>
> On 10/22/26 11:22 AM, Jamal Hadi Salim wrote:
> > The issue:
> > pop_mpls() restores MAC_PROTO_ETHERNET when the popped ethertype is
> > ETH_P_TEB, but skb_mpls_pop() only guarantees that the MPLS shim is in
> > the linear area.  When the inner Ethernet header sits in a page
> > fragment, the datapath now claims an Ethernet header it cannot access
> > linearly.
> >
> > Output to an OVS internal vport then calls eth_type_trans(), which
> > pulls ETH_HLEN from an empty linear area and triggers the BUG in
> > __skb_pull():
> >
> >   kernel BUG at ./include/linux/skbuff.h:2830!
> >   RIP: 0010:eth_type_trans+0x335/0x500
> >   internal_dev_recv
> >   ovs_vport_send
> >   do_output
> >   do_execute_actions
> >   ovs_execute_actions
> >   ovs_dp_process_packet
> >   ovs_vport_receive
> >   internal_dev_xmit
> >
> > Conditions to recreate the bug:
> > On a system with 4 KiB pages and CONFIG_OPENVSWITCH and CONFIG_PACKET
> > enabled, use CAP_NET_ADMIN to create an OVS datapath and bring its local
> > internal port up with MTU 9000.  Install a flow matching an Ethernet/MPLS
> > packet with one bottom-of-stack label and actions pop_eth,
> > pop_mpls(0x6558), output to the local port.  With CAP_NET_RAW, send a
> > 4128-byte AF_PACKET/SOCK_RAW frame containing outer Ethernet, the MPLS
> > label, inner Ethernet and 4096 payload bytes.  The two pops consume the
> > linear headers and expose the inner Ethernet header in page fragments.
> >
> > The Fix:
> > Pull the inner Ethernet header into the linear area before restoring
> > MAC_PROTO_ETHERNET.
> >
> > Fixes: f66b53fdbb22 ("openvswitch: New MPLS actions for layer 2 tunnelling")
> > Link: https://lore.kernel.org/netdev/e85fa16e-df3c-43dd-bb3a-9edca07200ea@kernel.org/
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> > ---
> >  net/openvswitch/actions.c | 5 ++++-
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
> > index 27152bca8a8c..03b31e33e880 100644
> > --- a/net/openvswitch/actions.c
> > +++ b/net/openvswitch/actions.c
> > @@ -153,8 +153,11 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
> >       if (err)
> >               return err;
> >
> > -     if (ethertype == htons(ETH_P_TEB))
> > +     if (ethertype == htons(ETH_P_TEB)) {
> > +             if (!pskb_may_pull(skb, ETH_HLEN))
> > +                     return -ENOMEM;
> >               key->mac_proto = MAC_PROTO_ETHERNET;
> > +     }
> >
> >       invalidate_flow_key(key);
> >       return 0;
>
> Reviewed-by: Ilya Maximets <i.maximets@ovn.org>

Reviewed-by: Eric Dumazet <edumazet@kernel.org>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net 5/5] net: openvswitch: ensure a linear inner Ethernet header on NSH pop
  2026-10-22 12:42           ` Ilya Maximets
@ 2026-10-22 17:47             ` Eric Dumazet
  0 siblings, 0 replies; 19+ messages in thread
From: Eric Dumazet @ 2026-10-22 17:47 UTC (permalink / raw)
  To: Ilya Maximets
  Cc: Jamal Hadi Salim, netdev, Aaron Conole, Eelco Chaudron,
	David S . Miller, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Eric Garver, Yi Yang, Jiri Benc, Pravin Shelar, Jiri Pirko,
	Victor Nogueira, dev, stable

Le jeu. 22 oct. 2026 à 14:43, Ilya Maximets <i.maximets@ovn.org> a écrit :
>
> On 10/22/26 11:22 AM, Jamal Hadi Salim wrote:
> > The issue:
> > pop_nsh() restores MAC_PROTO_ETHERNET when the popped NSH next-protocol
> > is TUN_P_ETHERNET, but nsh_pop() only guarantees that the NSH header is
> > in the linear area.  When the inner Ethernet header sits in a page
> > fragment, the datapath then claims an Ethernet header it cannot access
> > linearly.
> >
> > Output to an OVS internal vport then calls eth_type_trans(), which
> > pulls ETH_HLEN from an empty linear area and triggers the BUG in
> > __skb_pull():
> >
> >   kernel BUG at ./include/linux/skbuff.h:2830!
> >   RIP: 0010:eth_type_trans+0x335/0x500
> >   internal_dev_recv
> >   ovs_vport_send
> >   do_output
> >   do_execute_actions
> >   ovs_execute_actions
> >   ovs_dp_process_packet
> >   ovs_vport_receive
> >   internal_dev_xmit
> >
> > Conditions to recreate the bug:
> > On a system with 4 KiB pages and CONFIG_OPENVSWITCH and CONFIG_PACKET
> > enabled, use CAP_NET_ADMIN to create an OVS datapath and bring its local
> > internal port up with MTU 9000.  Install a flow matching an Ethernet/NSH
> > packet with a 24-byte MD1 header whose next-protocol is TUN_P_ETHERNET,
> > and actions pop_eth, pop_nsh, output to the local port.  With
> > CAP_NET_RAW, send a 4148-byte AF_PACKET/SOCK_RAW frame containing outer
> > Ethernet, the NSH header, inner Ethernet and 4096 payload bytes.  The
> > two pops consume the linear headers and expose the inner Ethernet header
> > in page fragments.
> >
> > The fix:
> > Pull the inner Ethernet header into the linear area before restoring
> > MAC_PROTO_ETHERNET.  This is the NSH counterpart of the MPLS/TEB
> > producer fix in the previous patch.
> >
> > Fixes: b2d0f5d5dc53 ("openvswitch: enable NSH support")
> > Link: https://lore.kernel.org/netdev/e85fa16e-df3c-43dd-bb3a-9edca07200ea@kernel.org/
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> > ---
> >  net/openvswitch/actions.c | 7 +++++--
> >  1 file changed, 5 insertions(+), 2 deletions(-)
> >
> > diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
> > index 03b31e33e880..cb7e16c6a8ef 100644
> > --- a/net/openvswitch/actions.c
> > +++ b/net/openvswitch/actions.c
> > @@ -314,10 +314,13 @@ static int pop_nsh(struct sk_buff *skb, struct sw_flow_key *key)
> >               return err;
> >
> >       /* safe right before invalidate_flow_key */
> > -     if (skb->protocol == htons(ETH_P_TEB))
> > +     if (skb->protocol == htons(ETH_P_TEB)) {
> > +             if (!pskb_may_pull(skb, ETH_HLEN))
> > +                     return -ENOMEM;
> >               key->mac_proto = MAC_PROTO_ETHERNET;
> > -     else
> > +     } else {
> >               key->mac_proto = MAC_PROTO_NONE;
> > +     }
> >       invalidate_flow_key(key);
> >       return 0;
> >  }
>
> Reviewed-by: Ilya Maximets <i.maximets@ovn.org>

Reviewed-by: Eric Dumazet <edumazet@kernel.org>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net 2/5] net/sched: act_mpls: reject short linear Ethernet headers after pop
  2026-10-22  9:22   ` [PATCH net 2/5] net/sched: act_mpls: reject short linear Ethernet headers after pop Jamal Hadi Salim
  2026-10-22  9:22     ` [PATCH net 3/5] net: tun: keep TUN short linear copy hints safe Jamal Hadi Salim
@ 2026-10-22 17:52     ` Eric Dumazet
  1 sibling, 0 replies; 19+ messages in thread
From: Eric Dumazet @ 2026-10-22 17:52 UTC (permalink / raw)
  To: Jamal Hadi Salim
  Cc: netdev, Jiri Pirko, Victor Nogueira, David S . Miller,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Martin Varghese,
	Pravin B Shelar, Vega, stable

Le jeu. 22 oct. 2026 à 11:22, Jamal Hadi Salim <jhs@mojatatu.com> a écrit :
>
> The issue:
> act_mpls POP can leave fewer than ETH_HLEN linear bytes after
> skb_mpls_pop(), either standalone on an Ethernet device or chained after
> act_vlan POP_ETH.  A subsequent eth_type_trans() can then BUG in
> __skb_pull().
>
> The Fix:
> After the pop, when the skb started as MPLS, drop it if the linear head
> is shorter than ETH_HLEN.  Non-MPLS pops and pushes are unaffected.
>
> Conditions to recreate the bug:
> - egress tc filter on lo: action mpls pop (standalone), or
>   action vlan pop_eth action mpls pop (chained).
> - AF_PACKET SOCK_RAW with PACKET_VNET_HDR, hdr_len=28, and a non-linear
>   eth / mpls / inner-eth frame.
> - The pop leaves skb_headlen(skb) < ETH_HLEN; a following
>   eth_type_trans() can BUG in __skb_pull().

skb_mpls_pop() calls skb_ensure_writable(skb, mac_len + MPLS_HLEN),
then memmove()s the mac header and pulls MPLS_HLEN.
So after the pop we still have at least mac_len bytes in the linear part.

If mac_len >= ETH_HLEN, the new check can never trigger.
It only matters when mac_len < ETH_HLEN, ie after POP_ETH
or on an L3 device.

Do you have a standalone repro? If yes, which path ends up with
mac_len < ETH_HLEN on an Ethernet device?


>
> Fixes: 040b5cfbcefa ("Fixed updating of ethertype in function skb_mpls_pop")

This commit only added the @ethernet parameter to fix the ethertype update.
The pop leaving a short linear part dates back to act_mpls introduction:

Fixes: 2a2ea50870ba ("net: sched: add mpls manipulation actions to TC")

> Reported-by: Vega <vega@nebusec.ai>
> Link: https://lore.kernel.org/r/40fe2d7dfce13411bfbe9271c0f7c54fb7e88e3b.1782548651.git.bronzed_45_vested@icloud.com/
> Cc: stable@vger.kernel.org
> Suggested-by: Jakub Kicinski <kuba@kernel.org>
> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> ---
>  net/sched/act_mpls.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/net/sched/act_mpls.c b/net/sched/act_mpls.c
> index 4ea8b2e08c3a..4d375033400b 100644
> --- a/net/sched/act_mpls.c
> +++ b/net/sched/act_mpls.c
> @@ -57,6 +57,7 @@ TC_INDIRECT_SCOPE int tcf_mpls_act(struct sk_buff *skb,
>         struct tcf_mpls *m = to_mpls(a);
>         struct tcf_mpls_params *p;
>         __be32 new_lse;
> +       bool was_mpls;
>         int mac_len;
>
>         tcf_lastuse_update(&m->tcf_tm);
> @@ -76,9 +77,12 @@ TC_INDIRECT_SCOPE int tcf_mpls_act(struct sk_buff *skb,
>
>         switch (p->tcfm_action) {
>         case TCA_MPLS_ACT_POP:
> +               was_mpls = eth_p_mpls(skb->protocol);
>                 if (skb_mpls_pop(skb, p->tcfm_proto, mac_len,
>                                  skb->dev && skb->dev->type == ARPHRD_ETHER))
>                         goto drop;
> +               if (was_mpls && unlikely(skb_headlen(skb) < ETH_HLEN))
> +                       goto drop;

Same remark as Willem's on patch 1: please pull instead of dropping.

skb_mpls_pop() only guarantees the popped label was in the linear part.
On an L3 device (mac_len == 0) with a label stack, the next label and
the following headers can legitimately sit in a frag.
These packets work today, and this patch would silently drop them.

Something like:

        if (mac_len < ETH_HLEN && !pskb_may_pull(skb, ETH_HLEN))
                goto drop;

This would also remove the need for @was_mpls: if the packet
was not MPLS, skb_mpls_pop() did not change anything, and pulling
only drops packets shorter than ETH_HLEN.

Thanks.

>                 break;
>         case TCA_MPLS_ACT_PUSH:
>                 new_lse = tcf_mpls_get_lse(NULL, p, !eth_p_mpls(skb_protocol(skb, true)));
> --
> 2.43.0
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net 1/5] net/sched: act_vlan: reject short linear Ethernet headers after POP_ETH
  2026-10-22 16:01     ` Jamal Hadi Salim
@ 2026-10-22 17:57       ` Eric Dumazet
  0 siblings, 0 replies; 19+ messages in thread
From: Eric Dumazet @ 2026-10-22 17:57 UTC (permalink / raw)
  To: Jamal Hadi Salim
  Cc: Willem de Bruijn, netdev, Jiri Pirko, Andrew Lunn,
	David S . Miller, Guillaume Nault, Simon Horman, Paolo Abeni,
	Jakub Kicinski, Victor Nogueira, Vega, Ren Wei, Herbert Xu,
	Jason Wang, stable

Le jeu. 22 oct. 2026 à 18:01, Jamal Hadi Salim <jhs@mojatatu.com> a écrit :
>
> On Thu, Oct 22, 2026 at 11:21 AM Willem de Bruijn
> <willemdebruijn.kernel@gmail.com> wrote:
> >
> > Jamal Hadi Salim wrote:
> > > The issue:
> > > act_vlan POP_ETH can leave a linear area shorter than ETH_HLEN; a
> > > subsequent eth_type_trans() may then BUG in __skb_pull() when the frame
> > > is redirected to an Ethernet device.
> > >
> > > The Fix:
> > > Drop the packet at the producer boundary when skb_headlen() is shorter
> > > than ETH_HLEN after skb_eth_pop().
> > >
> > > Conditions to recreate the bug:
> > > - egress tc filter on lo: action vlan pop_eth.
> > > - AF_PACKET SOCK_RAW with PACKET_VNET_HDR, hdr_len=28, and a non-linear
> > >   eth / inner-eth frame.
> > > - The pop leaves skb_headlen(skb) < ETH_HLEN; a following
> > >   eth_type_trans() can BUG in __skb_pull().
> > >
> > > Fixes: 19fbcb36a39e ("net/sched: act_vlan: Add {POP,PUSH}_ETH actions")
> > > Reported-by: Vega <vega@nebusec.ai>
> > > Link: https://lore.kernel.org/r/40fe2d7dfce13411bfbe9271c0f7c54fb7e88e3b.1782548651.git.bronzed_45_vested@icloud.com/
> > > Cc: stable@vger.kernel.org
> > > Suggested-by: Jakub Kicinski <kuba@kernel.org>
> > > Reviewed-by: Victor Nogueira <victor@mojatatu.com>
> > > Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> > > ---
> > >  net/sched/act_vlan.c | 2 ++
> > >  1 file changed, 2 insertions(+)
> > >
> > > diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
> > > index 6a375fdc63dd..ddf03b08bfe8 100644
> > > --- a/net/sched/act_vlan.c
> > > +++ b/net/sched/act_vlan.c
> > > @@ -79,6 +79,8 @@ TC_INDIRECT_SCOPE int tcf_vlan_act(struct sk_buff *skb,
> > >               err = skb_eth_pop(skb);
> > >               if (err)
> > >                       goto drop;
> > > +             if (unlikely(skb_headlen(skb) < ETH_HLEN))
> > > +                     goto drop;
> >
> > Could it try to pull the header and only drop if the packet is too short?
> >
>
> What would be the benefit?

Not dropping legitimate packets :)

skb_eth_pop() only guarantees the 14 bytes it removes were in the
linear part. Nothing guarantees anything after them, and many skbs
have exactly ETH_HLEN bytes in their linear part.

For instance, drivers using napi_gro_frags() (mlx4, sfc, gve, be2net,
cxgb4, ionic, ...) when GRO is disabled, or for protocols without a GRO
handler: napi_frags_skb() only pulls the Ethernet header.

After POP_ETH, skb_headlen(skb) is 0 for these packets.
They work today (for example POP_ETH then redirect to bareudp),
and this patch would silently drop them.

        err = skb_eth_pop(skb);
        if (err)
                goto drop;
        if (!pskb_may_pull(skb, ETH_HLEN))
                goto drop;

fixes the crash, and only drops packets shorter than ETH_HLEN after the
pop, which are not valid L3 packets anyway.

> Note: the OVS patches pull because they must restore
> MAC_PROTO_ETHERNET and already return an action error, i see a good
> reason there.

The same reasoning applies here: the producer makes the packet
valid for the consumer, it should not punish valid packets.

Thanks.


> > >       case TCA_VLAN_ACT_PUSH_ETH:
> > >               err = skb_eth_push(skb, p->tcfv_push_dst, p->tcfv_push_src);
> > > --
> > > 2.43.0
> > >
> >
> >

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net 3/5] net: tun: keep TUN short linear copy hints safe
  2026-10-22 16:17         ` Jamal Hadi Salim
@ 2026-10-22 18:00           ` Eric Dumazet
  2026-10-22 20:18             ` Jamal Hadi Salim
  0 siblings, 1 reply; 19+ messages in thread
From: Eric Dumazet @ 2026-10-22 18:00 UTC (permalink / raw)
  To: Jamal Hadi Salim
  Cc: Willem de Bruijn, netdev, Jason Wang, Andrew Lunn,
	David S . Miller, Jakub Kicinski, Paolo Abeni, Rusty Russell,
	Max Krasnyansky, Jiri Pirko, Victor Nogueira, stable

Le jeu. 22 oct. 2026 à 18:17, Jamal Hadi Salim <jhs@mojatatu.com> a écrit :
>
> On Thu, Oct 22, 2026 at 11:22 AM Willem de Bruijn
> <willemdebruijn.kernel@gmail.com> wrote:
> >
> > Jamal Hadi Salim wrote:
> > > The issue:
> > > A TUN skb can be redirected by tc mirred to an Ethernet xmit path, which
> > > calls eth_type_trans() and needs a full Ethernet header in the linear
> > > area.  tun_get_user() currently validates len and the GSO header length
> > > only for IFF_TAP, so an IFF_TUN | IFF_VNET_HDR packet can set hdr_len to
> > > 1..13 and leave fewer than ETH_HLEN linear bytes.  The redirected packet
> > > then BUGs in eth_type_trans().
> >
> > TUN mode does not imply Ethernet. Indeed, TUN implies an L3 packet?
>
> I have a feeling i am missing something: True, TUN is L3  but we are
> not adding or parsing eth headers to TUN.
>
> The patch only bounds the linear copy hint and receive headroom so a
> TUN skb redirected by tc to an some ethernet xmit path satisfies
> eth_type_trans()'s precondition in the patchset. IOW, with current
> code does it matter if TUN is l3? The other side will assume the
> payload to be ethernet..

I agree with Willem: TUN is not the producer here, mirred is.

TUN builds a valid L3 skb (mac_len == 0). mirred then sends it to a
device expecting a link layer header, and the IP header is parsed
as an Ethernet one. With this patch we no longer crash, but we still
transmit garbage.

Also, rejecting len < ETH_HLEN in IFF_TUN mode changes the uAPI for
a constraint that has nothing to do with TUN itself.

> If the redirect itself should be rejected for TUN, that is a different
> fix; earlier ask from Eric is to fix the producer not for example the
> driver (like loopback).
> The "reject redirect from TUN" could probably be done but i dont see a
> cheap way of doing it.

It does not need to be TUN specific, and bpf_redirect() already does it.
__bpf_redirect_common() refuses to send a packet without a link layer
header to a device expecting one, since 3a0af8fd61f9 ("bpf: BPF for
lightweight tunnel infrastructure"):

        /* Verify that a link layer header is carried */
        if (unlikely(skb->mac_header >= skb->network_header || skb->len == 0)) {
                kfree_skb(skb);
                return -ERANGE;
        }

mirred could do the same in tcf_mirred_to_dev(), after the
push/pull adjustment. Something like (untested):

        if (!expects_nh &&
            (unlikely(skb_network_offset(skb_to_send) < dev->min_header_len) ||
             !pskb_may_pull(skb_to_send, dev->min_header_len)))
                /* drop, freeing skb_to_send if it was cloned */

This is one compare in the fast path, covers TUN and any other L3
source (including a vlan pop_eth / mpls pop chain followed by mirred),
and keeps the legit case working (vlan push_eth, then mirred to an
Ethernet device).

Then this tun patch is not needed, unless there is another path
from an IFF_TUN device to eth_type_trans() that I missed.

Thanks.

>
> Thoughts?
>



> cheers,
> jamal
> > >
> > > The Fix:
> > > Reject packets shorter than ETH_HLEN in both modes.  For IFF_TUN, where
> > > hdr_len is only an allocation/copy hint when GSO and checksum offload are
> > > off, raise a short nonzero hdr_len to ETH_HLEN instead of rejecting the
> > > write.  Keep the TAP rejection and its NET_IP_ALIGN adjustment unchanged.
> > > This preserves valid no-offload TUN writes with hints below ETH_HLEN while
> > > guaranteeing at least ETH_HLEN linear bytes for the redirected consumer.
> > >
> > > The maximum receive headroom advertised through tun_set_headroom() must
> > > reserve the same linear minimum.  A large upper-device needed_headroom
> > > (for example an L2 netkit port behind a VLAN in an OVS datapath) otherwise
> > > caps good_linear below ETH_HLEN and defeats the clamp.  Reserve ETH_HLEN
> > > for TUN; the TAP branch already reserves ETH_HLEN + NET_IP_ALIGN.
> > >
> > > Conditions to recreate the bug (repro available):
> > > - create a TUN device with IFF_TUN | IFF_VNET_HDR | IFF_NO_PI;
> > > - attach ingress mirred egress redirect dev lo;
> > > - write a virtio_net_hdr with hdr_len=1 and an 8192-byte payload.
> > > Unfixed kernel will panic in eth_type_trans via loopback_xmit.
> > > In a fixed kernel the write is accepted with hdr_len clamped to ETH_HLEN and the
> > > packet is forwarded without a BUG.
> > > - no-offload acceptance: a separate check writes a 28-byte IPv4/UDP-shaped
> > >   packet with hdr_len 0, 1, 13, 14 and 20; all writes are accepted.
> > > - high headroom: create an L2 netkit pair with headroom 4096, put a VLAN
> > >   over it, and add both the VLAN and the TUN to one OVS datapath so the
> > >   TUN receive headroom is raised to 4100.  The same hdr_len=1 jumbo must
> > >   keep at least ETH_HLEN linear bytes; without the setter reservation it
> > >   still BUGs.
> > >
> > > Fixes: f42157cb568c ("tun: fallback if skb_alloc() fails on big packets")
> > > Cc: stable@vger.kernel.org
> > > Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> > > ---
> > >  drivers/net/tun.c | 7 ++++++-
> > >  1 file changed, 6 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> > > index 242899f7fd07..1e235c2f0aee 100644
> > > --- a/drivers/net/tun.c
> > > +++ b/drivers/net/tun.c
> > > @@ -1193,7 +1193,7 @@ static void tun_set_headroom(struct net_device *dev, int new_hr)
> > >       if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP)
> > >               max_headroom -= ETH_HLEN + NET_IP_ALIGN;
> > >       else
> > > -             max_headroom -= 1;
> > > +             max_headroom -= ETH_HLEN;
> > >
> > >       tun->align = clamp_t(int, new_hr, NET_SKB_PAD, max_headroom);
> > >  }
> > > @@ -1830,6 +1830,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
> > >               align += NET_IP_ALIGN;
> > >               if (unlikely(len < ETH_HLEN || (hdr_len && hdr_len < ETH_HLEN)))
> > >                       return -EINVAL;
> > > +     } else {
> > > +             if (unlikely(len < ETH_HLEN))
> > > +                     return -EINVAL;
> > > +             if (hdr_len)
> > > +                     hdr_len = max_t(int, hdr_len, ETH_HLEN);
> > >       }
> > >
> > >       good_linear = SKB_MAX_HEAD(align);
> > > --
> > > 2.43.0
> > >
> >
> >

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH net 3/5] net: tun: keep TUN short linear copy hints safe
  2026-10-22 18:00           ` Eric Dumazet
@ 2026-10-22 20:18             ` Jamal Hadi Salim
  0 siblings, 0 replies; 19+ messages in thread
From: Jamal Hadi Salim @ 2026-10-22 20:18 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Willem de Bruijn, netdev, Jason Wang, Andrew Lunn,
	David S . Miller, Jakub Kicinski, Paolo Abeni, Rusty Russell,
	Max Krasnyansky, Jiri Pirko, Victor Nogueira, stable

On Thu, Oct 22, 2026 at 2:00 PM Eric Dumazet <edumazet@kernel.org> wrote:
>
> Le jeu. 22 oct. 2026 à 18:17, Jamal Hadi Salim <jhs@mojatatu.com> a écrit :
> >
> > On Thu, Oct 22, 2026 at 11:22 AM Willem de Bruijn
> > <willemdebruijn.kernel@gmail.com> wrote:
> > >
> > > Jamal Hadi Salim wrote:
> > > > The issue:
> > > > A TUN skb can be redirected by tc mirred to an Ethernet xmit path, which
> > > > calls eth_type_trans() and needs a full Ethernet header in the linear
> > > > area.  tun_get_user() currently validates len and the GSO header length
> > > > only for IFF_TAP, so an IFF_TUN | IFF_VNET_HDR packet can set hdr_len to
> > > > 1..13 and leave fewer than ETH_HLEN linear bytes.  The redirected packet
> > > > then BUGs in eth_type_trans().
> > >
> > > TUN mode does not imply Ethernet. Indeed, TUN implies an L3 packet?
> >
> > I have a feeling i am missing something: True, TUN is L3  but we are
> > not adding or parsing eth headers to TUN.
> >
> > The patch only bounds the linear copy hint and receive headroom so a
> > TUN skb redirected by tc to an some ethernet xmit path satisfies
> > eth_type_trans()'s precondition in the patchset. IOW, with current
> > code does it matter if TUN is l3? The other side will assume the
> > payload to be ethernet..
>
> I agree with Willem: TUN is not the producer here, mirred is.
>
> TUN builds a valid L3 skb (mac_len == 0). mirred then sends it to a
> device expecting a link layer header, and the IP header is parsed
> as an Ethernet one. With this patch we no longer crash, but we still
> transmit garbage.
>
> Also, rejecting len < ETH_HLEN in IFF_TUN mode changes the uAPI for
> a constraint that has nothing to do with TUN itself.
>
> > If the redirect itself should be rejected for TUN, that is a different
> > fix; earlier ask from Eric is to fix the producer not for example the
> > driver (like loopback).
> > The "reject redirect from TUN" could probably be done but i dont see a
> > cheap way of doing it.
>
> It does not need to be TUN specific, and bpf_redirect() already does it.
> __bpf_redirect_common() refuses to send a packet without a link layer
> header to a device expecting one, since 3a0af8fd61f9 ("bpf: BPF for
> lightweight tunnel infrastructure"):
>
>         /* Verify that a link layer header is carried */
>         if (unlikely(skb->mac_header >= skb->network_header || skb->len == 0)) {
>                 kfree_skb(skb);
>                 return -ERANGE;
>         }
>
> mirred could do the same in tcf_mirred_to_dev(), after the
> push/pull adjustment. Something like (untested):
>
>         if (!expects_nh &&
>             (unlikely(skb_network_offset(skb_to_send) < dev->min_header_len) ||
>              !pskb_may_pull(skb_to_send, dev->min_header_len)))
>                 /* drop, freeing skb_to_send if it was cloned */
>
> This is one compare in the fast path, covers TUN and any other L3
> source (including a vlan pop_eth / mpls pop chain followed by mirred),
> and keeps the legit case working (vlan push_eth, then mirred to an
> Ethernet device).
>
> Then this tun patch is not needed, unless there is another path
> from an IFF_TUN device to eth_type_trans() that I missed.
>

Ok, i will look at this with the same reproducer script.
Also good answer on the skb pull.

Overall i wll resend this series with a new update, substituting this
with a mirred patch. I also have since found IFE old report from
sashiko fits as an additional patch.

pw-bot: cr

cheers,
jamal
> Thanks.
>
> >
> > Thoughts?
> >
>
>
>
> > cheers,
> > jamal
> > > >
> > > > The Fix:
> > > > Reject packets shorter than ETH_HLEN in both modes.  For IFF_TUN, where
> > > > hdr_len is only an allocation/copy hint when GSO and checksum offload are
> > > > off, raise a short nonzero hdr_len to ETH_HLEN instead of rejecting the
> > > > write.  Keep the TAP rejection and its NET_IP_ALIGN adjustment unchanged.
> > > > This preserves valid no-offload TUN writes with hints below ETH_HLEN while
> > > > guaranteeing at least ETH_HLEN linear bytes for the redirected consumer.
> > > >
> > > > The maximum receive headroom advertised through tun_set_headroom() must
> > > > reserve the same linear minimum.  A large upper-device needed_headroom
> > > > (for example an L2 netkit port behind a VLAN in an OVS datapath) otherwise
> > > > caps good_linear below ETH_HLEN and defeats the clamp.  Reserve ETH_HLEN
> > > > for TUN; the TAP branch already reserves ETH_HLEN + NET_IP_ALIGN.
> > > >
> > > > Conditions to recreate the bug (repro available):
> > > > - create a TUN device with IFF_TUN | IFF_VNET_HDR | IFF_NO_PI;
> > > > - attach ingress mirred egress redirect dev lo;
> > > > - write a virtio_net_hdr with hdr_len=1 and an 8192-byte payload.
> > > > Unfixed kernel will panic in eth_type_trans via loopback_xmit.
> > > > In a fixed kernel the write is accepted with hdr_len clamped to ETH_HLEN and the
> > > > packet is forwarded without a BUG.
> > > > - no-offload acceptance: a separate check writes a 28-byte IPv4/UDP-shaped
> > > >   packet with hdr_len 0, 1, 13, 14 and 20; all writes are accepted.
> > > > - high headroom: create an L2 netkit pair with headroom 4096, put a VLAN
> > > >   over it, and add both the VLAN and the TUN to one OVS datapath so the
> > > >   TUN receive headroom is raised to 4100.  The same hdr_len=1 jumbo must
> > > >   keep at least ETH_HLEN linear bytes; without the setter reservation it
> > > >   still BUGs.
> > > >
> > > > Fixes: f42157cb568c ("tun: fallback if skb_alloc() fails on big packets")
> > > > Cc: stable@vger.kernel.org
> > > > Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> > > > ---
> > > >  drivers/net/tun.c | 7 ++++++-
> > > >  1 file changed, 6 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> > > > index 242899f7fd07..1e235c2f0aee 100644
> > > > --- a/drivers/net/tun.c
> > > > +++ b/drivers/net/tun.c
> > > > @@ -1193,7 +1193,7 @@ static void tun_set_headroom(struct net_device *dev, int new_hr)
> > > >       if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP)
> > > >               max_headroom -= ETH_HLEN + NET_IP_ALIGN;
> > > >       else
> > > > -             max_headroom -= 1;
> > > > +             max_headroom -= ETH_HLEN;
> > > >
> > > >       tun->align = clamp_t(int, new_hr, NET_SKB_PAD, max_headroom);
> > > >  }
> > > > @@ -1830,6 +1830,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
> > > >               align += NET_IP_ALIGN;
> > > >               if (unlikely(len < ETH_HLEN || (hdr_len && hdr_len < ETH_HLEN)))
> > > >                       return -EINVAL;
> > > > +     } else {
> > > > +             if (unlikely(len < ETH_HLEN))
> > > > +                     return -EINVAL;
> > > > +             if (hdr_len)
> > > > +                     hdr_len = max_t(int, hdr_len, ETH_HLEN);
> > > >       }
> > > >
> > > >       good_linear = SKB_MAX_HEAD(align);
> > > > --
> > > > 2.43.0
> > > >
> > >
> > >

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2026-10-22 20:18 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-22  9:22 [PATCH net 0/5] net: reject short linear Ethernet headers from tc actions, tun and OVS Jamal Hadi Salim
2026-10-22  9:22 ` [PATCH net 1/5] net/sched: act_vlan: reject short linear Ethernet headers after POP_ETH Jamal Hadi Salim
2026-10-22  9:22   ` [PATCH net 2/5] net/sched: act_mpls: reject short linear Ethernet headers after pop Jamal Hadi Salim
2026-10-22  9:22     ` [PATCH net 3/5] net: tun: keep TUN short linear copy hints safe Jamal Hadi Salim
2026-10-22  9:22       ` [PATCH net 4/5] net: openvswitch: ensure a linear inner Ethernet header on TEB pop Jamal Hadi Salim
2026-10-22  9:22         ` [PATCH net 5/5] net: openvswitch: ensure a linear inner Ethernet header on NSH pop Jamal Hadi Salim
2026-10-22  9:54           ` Jiri Benc
2026-10-22 12:42           ` Ilya Maximets
2026-10-22 17:47             ` Eric Dumazet
2026-10-22 12:41         ` [PATCH net 4/5] net: openvswitch: ensure a linear inner Ethernet header on TEB pop Ilya Maximets
2026-10-22 17:47           ` Eric Dumazet
2026-10-22 15:22       ` [PATCH net 3/5] net: tun: keep TUN short linear copy hints safe Willem de Bruijn
2026-10-22 16:17         ` Jamal Hadi Salim
2026-10-22 18:00           ` Eric Dumazet
2026-10-22 20:18             ` Jamal Hadi Salim
2026-10-22 17:52     ` [PATCH net 2/5] net/sched: act_mpls: reject short linear Ethernet headers after pop Eric Dumazet
2026-10-22 15:21   ` [PATCH net 1/5] net/sched: act_vlan: reject short linear Ethernet headers after POP_ETH Willem de Bruijn
2026-10-22 16:01     ` Jamal Hadi Salim
2026-10-22 17:57       ` Eric Dumazet

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox