Re: [PATCH net] net: iptunnel: fix stale transport header during tunnel decapsulation

Eric Dumazet <[email protected]>
Newsgroups org.kernel.vger.netdev
Message-ID <CANn89iLCrzmOfUVwa0yeROpkZxWmVsAkbH7=SBA3XuVxkmTfKA@mail.gmail.com>
On Thu, Aug 13, 2026 at 5:30 AM Dong Chenchen <[email protected]> wrote:
>
> Syzbot reported a crash in qdisc_pkt_len_segs_init() caused by a stale
> transport_header offset after tunnel decapsulation.
>
> BUG: unable to handle page fault for address: ffffed102091a42e
> Oops: Oops: 0000 [#1] SMP KASAN NOPTI
> CPU: 0 UID: 0 PID: 340 Comm: qdisc_uaf_repro Not tainted 7.2.0-rc4-00061-g248951ddc14d #256 PREEMPT(full)
> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
> RIP: 0010:__asan_load2
> <IRQ>
> qdisc_pkt_len_segs_init (net/core/dev.c:4145)
> __dev_queue_xmit (net/core/dev.c:4787)
> br_dev_queue_push_xmit (net/bridge/br_forward.c:53)
> br_handle_frame_finish (net/bridge/br_input.c:229)
> br_handle_frame (net/bridge/br_input.c:315)
> __netif_receive_skb_core.constprop.0 (net/core/dev.c:6099)
> __netif_receive_skb_list_core (net/core/dev.c:6287)
> netif_receive_skb_list_internal (net/core/dev.c:6445)
> napi_complete_done (net/core/dev.c:6813)
> gro_cell_poll (net/core/gro_cells.c:74)
> __napi_poll (net/core/dev.c:7735)
> net_rx_action (net/core/dev.c:7798 net/core/dev.c:7955)
> handle_softirqs (kernel/softirq.c:622)
> do_softirq (kernel/softirq.c:523  kernel/softirq.c:510 )
> __local_bh_enable_ip (kernel/softirq.c:450)
> tun_get_user (drivers/net/tun.c:1986 (discriminator 1))
> tun_chr_write_iter (drivers/net/tun.c:2032)
>
> The crash requires four conditions to line up:
>
> 1. The incoming packet is encapsulated and carries GSO metadata.  The outer
>    transport header offset is stored in skb->transport_header while the
>    packet is still in the outer tunnel context.
> 2. The tunnel receiver strips the outer headers.  skb->data is advanced to
>    the inner frame, but skb->transport_header is left pointing to the
>    now-removed outer L4 header, so it becomes a negative offset relative to
>    the new data.
> 3. The inner frame is not delivered to the local IP stack.  Instead, it
>    is forwarded at L2 by a bridge or HSR, so ip_rcv_core() never runs and
>    the transport header is not reset to the inner L4 offset.
> 4. The forwarding path calls __dev_queue_xmit(), which enters
>    qdisc_pkt_len_segs_init().  That function computes the GSO header length
>    from skb_transport_offset(skb).  Because the offset is negative, the
>    unsigned cast overflows and pskb_may_pull(skb, hdr_len +
>    sizeof(struct tcphdr)) reads past the end of the skb, triggering a
>    KASAN fault or page fault.
>
> Fix this by clearing skb->transport_header to the ~0U sentinel at the
> tunnel decapsulation boundary, after each tunnel receive function has
> finished all processing that needs the outer L4 header and before the skb
> is handed to GRO or the stack. The IP/GRO receive paths then set the
> transport header correctly when they parse the inner packet.
>
> Fixes: 7fb4c1967011 ("net: pull headers in qdisc_pkt_len_segs_init()")

This Fixes: tag seems pretty random to me. Issue was present long
before that commit.
Next time, please be precise with the `Fixes:` tag; it's not decoration.

Also, calling skb_unset_transport_header(skb) directly from
gro_cells_receive() would make more sense and
your patch would be less intrusive.

pw-bot: cr
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.