All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.