Re: [PATCH net v3 1/2] net: fix skb length accounting after generic XDP frag adjustment
[email protected] Wed, 05 Aug 2026 05:41:08 +0000
| Newsgroups | org.kernel.vger.bpf |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: Pre-existing issues: - [High] Preexisting bug: bpf_xdp_adjust_tail for generic XDP incorrectly frees system_page_pool fragment pages using the driver's RX queue memory model. - [High] The exact length accounting vulnerability fixed in `bpf_prog_run_generic_xdp` remains unpatched in the native XDP receive path for veth devices (`veth_xdp_rcv_skb`). -- --- Patch [1]: [PATCH net v3 1/2] net: fix skb length accounting after generic XDP frag adjustment --- commit e03da2f78f026fb5c5139f386cdfe9ac7e62b48f Author: Sun Jian <[email protected]> Subject: net: fix skb length accounting after generic XDP frag adjustment Generic XDP exposes non-linear skb fragments through an xdp_buff. If an XDP program adjusts the fragment area, bpf_prog_run_generic_xdp() copies xdp_frags_size back to skb->data_len but leaves skb->len containing the old fragment contribution. This patch subtracts the old data_len before replacing it and adds the new data_len afterwards, keeping skb->len and skb->data_len synchronized. Link: https://lore.kernel.org/bpf/al9T9Eto%2FhRIzP5W@boxer/ > diff --git a/net/core/dev.c b/net/core/dev.c > index 5933c5dab09ee..5c37cf6c4aa10 100644 > --- a/net/core/dev.c > +++ b/net/core/dev.c > @@ -5517,12 +5517,16 @@ u32 bpf_prog_run_generic_xdp(struct sk_buff *skb, struct xdp_buff *xdp, > } > > /* XDP frag metadata (e.g. nr_frags) are updated in eBPF helpers [Severity: High] This is a pre-existing issue, but since this code path relates to fragment shrinking via bpf_xdp_adjust_tail(), does it incorrectly free system_page_pool fragment pages using the driver's RX queue memory model? In generic XDP, skb fragments are reallocated using system_page_pool: net/core/dev.c:netif_skb_check_for_xdp() { ... err = skb_cow_data_for_xdp(this_cpu_read(system_page_pool.pool), pskb, prog); ... } However, bpf_prog_run_generic_xdp() initializes the xdp_buff with the device driver's rxqueue: net/core/dev.c:bpf_prog_run_generic_xdp() { ... xdp_init_buff(xdp, frame_sz, &rxqueue->xdp_rxq); ... } When an XDP program shrinks fragments, bpf_xdp_shrink_data() retrieves the driver's mem_type and passes it to __xdp_return(): net/core/filter.c:bpf_xdp_shrink_data() { ... enum xdp_mem_type mem_type = xdp->rxq->mem.type; ... if (release) { __xdp_return(netmem, mem_type, false, zc_frag); ... } If mem_type is MEM_TYPE_PAGE_SHARED, __xdp_return() routes to page_frag_free(), bypassing the required page_pool_put_full_netmem() hooks for system_page_pool pages. Can this leak DMA mappings and corrupt page structures when these pages reach the buddy allocator? > - * (e.g. bpf_xdp_adjust_tail), we need to update data_len here. > + * (e.g. bpf_xdp_adjust_tail). Remove the old fragment contribution > + * from skb->len before updating data_len, then add the new one back. > */ > - if (xdp_buff_has_frags(xdp)) > + skb->len -= skb->data_len; > + if (xdp_buff_has_frags(xdp)) { > skb->data_len = skb_shinfo(skb)->xdp_frags_size; > - else > + skb->len += skb->data_len; [Severity: High] This isn't a bug introduced by this patch, but does the exact length accounting vulnerability fixed here remain unpatched in the native XDP receive path for veth devices? Looking at veth_xdp_rcv_skb() in drivers/net/veth.c: drivers/net/veth.c:veth_xdp_rcv_skb() { ... off = xdp->data_end - orig_data_end; if (off != 0) __skb_put(skb, off); /* positive on grow, negative on shrink */ /* XDP frag metadata (e.g. nr_frags) are updated in eBPF helpers * (e.g. bpf_xdp_adjust_tail), we need to update data_len here. */ if (xdp_buff_has_frags(xdp)) skb->data_len = skb_shinfo(skb)->xdp_frags_size; else skb->data_len = 0; ... } If an XDP program shrinks an skb's fragment area, skb->data_len is updated but skb->len is not adjusted, which would artificially inflate skb_headlen() and potentially leak adjacent kernel memory to userspace. Additionally, if the fragments are completely dropped, xdp->data_end shrinks, resulting in a negative off passed to __skb_put(). Since skb->data_len is still non-zero during the __skb_put() call, would SKB_LINEAR_ASSERT() trigger a BUG_ON and cause a kernel panic? > + } else { > skb->data_len = 0; > + } > > /* check if XDP changed eth hdr such SKB needs update */ > eth = (struct ethhdr *)xdp->data; -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=1