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