From: Wyatt Feng <wf.kernel.dev@gmail.com>
To: Jakub Kicinski <kuba@kernel.org>
Cc: Nebula Security <vega@nebusec.ai>, Ren Wei <enjou1224z@gmail.com>,
netdev@vger.kernel.org, andrew+netdev@lunn.ch,
davem@davemloft.net, edumazet@google.com, pabeni@redhat.com
Subject: Re: [PATCH net v3] net: loopback: ensure Ethernet header is linear before eth_type_trans
Date: Mon, 10 Aug 2026 02:05:16 -0700 [thread overview]
Message-ID: <anmHJxrbKazL6_N8@mail.google.com> (raw)
In-Reply-To: <20260804174508.20c0e505@kernel.org>
This is Wyatt Feng, replying from a new address dedicated to kernel
development, as my previous iCloud Hide My Email address does not
support multiple recipients.
On Tue, Aug 04, 2026 at 05:45:08PM -0800, Jakub Kicinski wrote:
> Shouldn't TCA_VLAN_ACT_POP_ETH make sure another header is accessible
> then? Are there other ways for something to strip L2 before the frame
> reaches the driver?
Making TCA_VLAN_ACT_POP_ETH verify that a full inner Ethernet header is
accessible would prevent the original act_vlan path. However, that alone
would not protect loopback_xmit(), because other paths can leave the skb
without an Ethernet header before it reaches the driver.
I found another path that can strip L2 before the skb reaches the driver:
the IFE decode action. On egress, tcf_ife_decode() calls ife_decode(),
which pulls the outer Ethernet header and the IFE metadata header. It then
calls eth_type_trans(), which consumes the inner Ethernet header. If the
action returns TC_ACT_PIPE, the skb continues to the driver without an
Ethernet header at skb->data.
The reproducer below attaches IFE decode to the loopback egress path and
sends a large, non-linear IFE frame through an AF_PACKET socket. After IFE
decode returns, loopback_xmit() calls eth_type_trans() again and hits the
skb assertion. This path does not use TCA_VLAN_ACT_POP_ETH.
The IFE action is not present in the panic stack because it has already
returned before the driver xmit function is invoked.
Therefore, I think the check in loopback_xmit() is still needed as a
defensive check at the common consumer.
I reproduced this on:
7.2.0-rc6-00240-gdd057113a
The test can be run in a disposable VM as follows. CONFIG_NET_ACT_IFE,
CONFIG_NET_CLS_MATCHALL and CONFIG_NET_SCH_INGRESS are required.
gcc -O2 -Wall -Wextra -o ife_reproducer ife_reproducer.c
unshare -Urn sh
ip link set lo up
tc qdisc add dev lo clsact
tc filter add dev lo egress protocol 0xed3e pref 1 matchall \
action ife decode pipe
./ife_reproducer lo
ife_reproducer.c:
#include <arpa/inet.h>
#include <errno.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <netpacket/packet.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#ifndef ETH_P_IFE
#define ETH_P_IFE 0xED3E
#endif
#define IFE_META_HDR_LEN 2
#define PAYLOAD_LEN 8192
static void set_eth_header(unsigned char *data, const unsigned char *dst,
const unsigned char *src, uint16_t proto)
{
uint16_t be_proto = htons(proto);
memcpy(data, dst, ETH_ALEN);
memcpy(data + ETH_ALEN, src, ETH_ALEN);
memcpy(data + 2 * ETH_ALEN, &be_proto, sizeof(be_proto));
}
int main(int argc, char **argv)
{
static const unsigned char outer_dst[ETH_ALEN] =
{ 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
static const unsigned char outer_src[ETH_ALEN] =
{ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
static const unsigned char inner_dst[ETH_ALEN] =
{ 0x02, 0x00, 0x00, 0x00, 0x00, 0x01 };
static const unsigned char inner_src[ETH_ALEN] =
{ 0x02, 0x00, 0x00, 0x00, 0x00, 0x02 };
const char *ifname = argc > 1 ? argv[1] : "lo";
const size_t inner_off = ETH_HLEN + IFE_META_HDR_LEN;
const size_t len = inner_off + ETH_HLEN + PAYLOAD_LEN;
struct sockaddr_ll sll = { 0 };
uint16_t meta_len;
unsigned char *frame;
ssize_t sent;
int fd = -1;
int ret = 1;
frame = malloc(len);
if (!frame) {
perror("malloc");
return 1;
}
memset(frame, 'A', len);
set_eth_header(frame, outer_dst, outer_src, ETH_P_IFE);
/* IFE metalen includes the two-byte IFE metadata header itself. */
meta_len = htons(IFE_META_HDR_LEN);
memcpy(frame + ETH_HLEN, &meta_len, sizeof(meta_len));
set_eth_header(frame + inner_off, inner_dst, inner_src, ETH_P_IP);
fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IFE));
if (fd < 0) {
perror("socket");
goto out;
}
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(ETH_P_IFE);
sll.sll_ifindex = if_nametoindex(ifname);
if (!sll.sll_ifindex) {
fprintf(stderr, "unknown interface: %s\n", ifname);
goto out;
}
if (bind(fd, (struct sockaddr *)&sll, sizeof(sll)) < 0) {
perror("bind");
goto out;
}
sent = send(fd, frame, len, 0);
if (sent < 0) {
perror("send");
goto out;
}
if ((size_t)sent != len) {
fprintf(stderr, "short send: %zd of %zu bytes\n", sent, len);
goto out;
}
printf("sent %zu-byte IFE frame on %s\n", len, ifname);
ret = 0;
out:
if (fd >= 0)
close(fd);
free(frame);
return ret;
}
The resulting panic was:
[ 300.362037][ T9401] kernel BUG at include/linux/skbuff.h:2847!
[ 300.362790][ T9401] Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
[ 300.364887][ T9401] Hardware name: Red Hat KVM, BIOS 1.16.0-4.module+el8.9.0+1408+7b966129 04/01/2014
[ 300.365955][ T9401] RIP: 0010:eth_type_trans (include/linux/skbuff.h:2847 include/linux/skbuff.h:2854 i
[ 300.366668][ T9401] Code: 56 33 f8 44 89 73 70 be 0e 00 00 00 48 c7 c7 80 94 19 8d e8 e4 d8 0f f8 31 d2
Code starting with the faulting instruction
===========================================
0: 56 push %rsi
1: 33 f8 xor %eax,%edi
3: 44 89 73 70 mov %r14d,0x70(%rbx)
7: be 0e 00 00 00 mov $0xe,%esi
c: 48 c7 c7 80 94 19 8d mov $0xffffffff8d199480,%rdi
13: e8 e4 d8 0f f8 callq 0xfffffffff80fd8fc
18: 31 d2 xor %edx,%edx
[ 300.368865][ T9401] RSP: 0018:ffa000000746f5d8 EFLAGS: 00010246
[ 300.369584][ T9401] RAX: 0000000000000000 RBX: ff110000388fa200 RCX: ffffffff89651ff5
[ 300.370504][ T9401] RDX: 0000000000000200 RSI: ff11000025560040 RDI: 0000000000000002
[ 300.371424][ T9401] RBP: 0000000000000020 R08: 0000000000000130 R09: 0000000000000000
[ 300.372342][ T9401] R10: ffe21c000d3248e9 R11: ff1100006992474b R12: ff110000220c1000
[ 300.373263][ T9401] R13: ff110000390b96e0 R14: 0000000000002000 R15: 0000000000000020
[ 300.374183][ T9401] FS: 00007f7566a8b540(0000) GS:ff110000d5379000(0000) knlGS:0000000000000000
[ 300.375217][ T9401] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 300.375987][ T9401] CR2: 0000000025b75000 CR3: 0000000038ea3000 CR4: 0000000000751ef0
[ 300.376902][ T9401] PKRU: 55555554
[ 300.377327][ T^[[118;1:3u9401] Call Trace:
[ 300.377725][ T9401] <TASK>
[ 300.378091][ T9401] loopback_xmit (include/linux/skbuff.h:3393 drivers/net/loopback.c:86)
[ 300.378672][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.379379][ T9401] dev_hard_start_xmit (include/linux/netdevice.h:5397 include/linux/netdevice.h:5406
[ 300.380026][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.380724][ T9401] __dev_queue_xmit (net/core/dev.c:4878)
[ 300.381370][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.382058][ T9401] ? __lock_acquire (kernel/locking/lockdep.c:3820 kernel/locking/lockdep.c:3876 kern
[ 300.382678][ T9401] ? __pfx___dev_queue_xmit (include/linux/netdevice.h:4035)
[ 300.383351][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.384042][ T9401] ? find_held_lock (kernel/locking/lockdep.c:5350)
[ 300.384643][ T9401] ? __might_fault (mm/memory.c:7292 mm/memory.c:7286)
[ 300.385260][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.385958][ T9401] ? __might_fault (mm/memory.c:7292 mm/memory.c:7286)
[ 300.386563][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.387254][ T9401] ? write_comp_data (kernel/kcov.c:246)
[ 300.387875][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.388562][ T9401] ? __sanitizer_cov_trace_pc (kernel/kcov.c:217)
[ 300.389260][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.389952][ T9401] ? _copy_from_iter (include/linux/iov_iter.h:299 include/linux/iov_iter.h:330 lib/i
[ 300.390597][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.391286][ T9401] ? __sanitizer_cov_trace_pc (kernel/kcov.c:217)
[ 300.391979][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.392665][ T9401] ? _copy_from_iter (include/linux/iov_iter.h:299 include/linux/iov_iter.h:330 lib/i
[ 300.393308][ T9401] ? __pfx__copy_from_iter (include/linux/iov_iter.h:157)
[ 300.393978][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.394665][ T9401] ? __sanitizer_cov_trace_pc (kernel/kcov.c:217)
[ 300.395364][ T9401] ? __pfx__copy_from_iter (include/linux/iov_iter.h:157)
[ 300.396031][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.396722][ T9401] ? write_comp_data (kernel/kcov.c:246)
[ 300.397331][ T9401] ? __sanitizer_cov_trace_pc (kernel/kcov.c:217)
[ 300.398026][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.398711][ T9401] ? packet_parse_headers.isra.71 (include/linux/skbuff.h:3194 net/packet/af_packet.c
[ 300.399475][ T9401] ? __pfx_packet_parse_headers.isra.71 (net/packet/af_packet.c:1550)
[ 300.400267][ T9401] packet_xmit (include/linux/netdevice.h:3448 net/packet/af_packet.c:276 net/packet/
[ 300.400848][ T9401] ? write_comp_data (kernel/kcov.c:246)
[ 300.401460][ T9401] packet_sendmsg (net/packet/af_packet.c:3104 net/packet/af_packet.c:3136)
[ 300.402106][ T9401] ? __pfx_avc_has_perm (security/selinux/avc.c:529)
[ 300.402755][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.403440][ T9401] ? __sanitizer_cov_trace_pc (kernel/kcov.c:217)
[ 300.404137][ T9401] ? __pfx_packet_sendmsg (net/packet/af_packet.c:2502)
[ 300.404798][ T9401] ? __pfx_sock_has_perm (security/selinux/include/objsec.h:232)
[ 300.405419][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.406110][ T9401] ? write_comp_data (kernel/kcov.c:246)
[ 300.406723][ T9401] ? __entry_text_end (??:?)
[ 300.407390][ T9401] ? __sanitizer_cov_trace_pc (kernel/kcov.c:217)
[ 300.408083][ T9401] ? tomoyo_find_next_domain (security/tomoyo/domain.c:838 (discriminator 1))
[ 300.408789][ T9401] ? __pfx_tomoyo_socket_sendmsg_permission (security/tomoyo/network.c:604)
[ 300.409615][ T9401] ? release_sock (include/linux/spinlock.h:348 net/core/sock.c:3856)
[ 300.410218][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.410908][ T9401] ? write_comp_data (kernel/kcov.c:246)
[ 300.411517][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.412209][ T9401] ? selinux_socket_sendmsg (include/net/sock.h:2962 security/selinux/hooks.c:5284)
[ 300.412898][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.413585][ T9401] ? write_comp_data (kernel/kcov.c:246)
[ 300.414196][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.414891][ T9401] ? __sanitizer_cov_trace_pc (kernel/kcov.c:217)
[ 300.415583][ T9401] ? __pfx_packet_sendmsg (net/packet/af_packet.c:2502)
[ 300.416244][ T9401] __sock_sendmsg (net/socket.c:775 net/socket.c:790)
[ 300.416828][ T9401] __sys_sendto (net/socket.c:2252)
[ 300.417406][ T9401] ? __pfx___sys_sendto (net/socket.c:2206)
[ 300.418076][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.418776][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.419463][ T9401] ? __sys_bind (include/linux/file.h:62)
[ 300.420032][ T9401] ? __pfx___sys_bind (net/socket.c:1920)
[ 300.420640][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.421336][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.422026][ T9401] ? __sanitizer_cov_trace_pc (kernel/kcov.c:217)
[ 300.422728][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.423413][ T9401] ? fput_close_sync (fs/file_table.c:618)
[ 300.424038][ T9401] ? __pfx_fput_close_sync (fs/file_table.c:479)
[ 300.424685][ T9401] ? dnotify_flush (fs/notify/dnotify/dnotify.c:161)
[ 300.425279][ T9401] __x64_sys_sendto (net/socket.c:2259 net/socket.c:2255 net/socket.c:2255)
[ 300.425887][ T9401] ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:234)
[ 300.426574][ T9401] ? lockdep_hardirqs_on (kernel/locking/lockdep.c:4472)
[ 300.427253][ T9401] do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94)
[ 300.427820][ T9401] ? exc_page_fault (arch/x86/mm/fault.c:1539)
[ 300.428434][ T9401] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
[ 300.429147][ T9401] RIP: 0033:0x7f75669b2eec
[ 300.429693][ T9401] Code: 89 02 48 c7 c0 ff ff ff ff eb b8 0f 1f 00 41 89 ca 64 8b 04 25 18 00 00 00 85
Code starting with the faulting instruction
===========================================
0: 89 02 mov %eax,(%rdx)
2: 48 c7 c0 ff ff ff ff mov $0xffffffffffffffff,%rax
9: eb b8 jmp 0xffffffffffffffc3
b: 0f 1f 00 nopl (%rax)
e: 41 89 ca mov %ecx,%r10d
11: 64 8b 04 25 18 00 00 mov %fs:0x18,%eax
18: 00
19: 85 .byte 0x85
[ 300.431895][ T9401] RSP: 002b:00007ffe9d0f1428 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
[ 300.432873][ T9401] RAX: ffffffffffffffda RBX: 0000000025b742a0 RCX: 00007f75669b2eec
[ 300.433795][ T9401] RDX: 000000000000201e RSI: 0000000025b742a0 RDI: 0000000000000003
[ 300.434710][ T9401] RBP: 0000000000000003 R08: 0000000000000000 R09: 0000000000000000
[ 300.435634][ T9401] R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffe9d0f1f15
[ 300.436553][ T9401] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[ 300.437494][ T9401] </TASK>
[ 300.437865][ T9401] Modules linked in:
[ 300.438455][ T9401] ---[ end trace 0000000000000000 ]---
[ 300.439102][ T9401] RIP: 0010:eth_type_trans (include/linux/skbuff.h:2847 include/linux/skbuff.h:2854 i
[ 300.439791][ T9401] Code: 56 33 f8 44 89 73 70 be 0e 00 00 00 48 c7 c7 80 94 19 8d e8 e4 d8 0f f8 31 d2
All code
========
0: 56 push %rsi
1: 33 f8 xor %eax,%edi
3: 44 89 73 70 mov %r14d,0x70(%rbx)
7: be 0e 00 00 00 mov $0xe,%esi
c: 48 c7 c7 80 94 19 8d mov $0xffffffff8d199480,%rdi
13: e8 e4 d8 0f f8 callq 0xfffffffff80fd8fc
18: 31 d2 xor %edx,%edx
1a: 48 89 de mov %rbx,%rsi
1d: 48 c7 c7 c0 94 19 8d mov $0xffffffff8d1994c0,%rdi
24: e8 43 b3 d5 ff callq 0xffffffffffd5b36c
29: 90 nop
2a:* 0f 0b ud2 <-- trapping instruction
2c: bd 00 01 00 00 mov $0x100,%ebp
31: e9 1e ff ff ff jmpq 0xffffffffffffff54
36: 48 8b 7c 24 20 mov 0x20(%rsp),%rdi
3b: e8 3c d4 a8 f8 callq 0xfffffffff8a8d47c
Code starting with the faulting instruction
===========================================
0: 0f 0b ud2
2: bd 00 01 00 00 mov $0x100,%ebp
7: e9 1e ff ff ff jmpq 0xffffffffffffff2a
c: 48 8b 7c 24 20 mov 0x20(%rsp),%rdi
11: e8 3c d4 a8 f8 callq 0xfffffffff8a8d452
[ 300.442007][ T9401] RSP: 0018:ffa000000746f5d8 EFLAGS: 00010246
[ 300.442738][ T9401] RAX: 0000000000000000 RBX: ff110000388fa200 RCX: ffffffff89651ff5
[ 300.443658][ T9401] RDX: 0000000000000200 RSI: ff11000025560040 RDI: 0000000000000002
[ 300.444599][ T9401] RBP: 0000000000000020 R08: 0000000000000130 R09: 0000000000000000
[ 300.445521][ T9401] R10: ffe21c000d3248e9 R11: ff1100006992474b R12: ff110000220c1000
[ 300.446460][ T9401] R13: ff110000390b96e0 R14: 0000000000002000 R15: 0000000000000020
[ 300.447413][ T9401] FS: 00007f7566a8b540(0000) GS:ff110000d5379000(0000) knlGS:0000000000000000
[ 300.448711][ T9401] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 300.449508][ T9401] CR2: 0000000025b75000 CR3: 0000000038ea3000 CR4: 0000000000751ef0
[ 300.450443][ T9401] PKRU: 55555554
[ 300.450878][ T9401] Kernel panic - not syncing: Fatal exception in interrupt
prev parent reply other threads:[~2026-08-10 9:05 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-28 15:04 [PATCH net v3] net: loopback: ensure Ethernet header is linear before eth_type_trans Ren Wei
2026-08-01 0:50 ` Jakub Kicinski
2026-08-05 0:08 ` Nebula Security
2026-08-05 0:45 ` Jakub Kicinski
2026-08-10 9:05 ` Wyatt Feng [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=anmHJxrbKazL6_N8@mail.google.com \
--to=wf.kernel.dev@gmail.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=enjou1224z@gmail.com \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=vega@nebusec.ai \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox