Netdev List
 help / color / mirror / Atom feed
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

      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