| From 71283aaa6c65b3cec84caf1dc78560985737641f Mon Sep 17 00:00:00 2001 |
| From: Weiming Shi <bestswngs@gmail.com> |
| Date: Tue, 18 Aug 2026 23:45:15 +0800 |
| Subject: xdp: fix zero-copy frame layout |
| |
| From: Weiming Shi <bestswngs@gmail.com> |
| |
| commit 71283aaa6c65b3cec84caf1dc78560985737641f upstream. |
| |
| xdp_convert_zc_to_xdp_frame() clones an XSK packet into an order-0 page |
| and advertises PAGE_SIZE as its frame size. It allows the copied frame |
| to occupy the page tail needed by skb_shared_info and records zero |
| headroom even when metadata separates the frame header from packet data. |
| An AF_XDP zero-copy packet redirected through cpumap can therefore make |
| the skb overlap skb_shared_info or place it beyond the allocated page. |
| |
| Limit the copied layout to SKB_WITH_OVERHEAD(PAGE_SIZE) and include the |
| metadata length in frame headroom. Redirect callers already handle a |
| NULL conversion result. |
| |
| BUG: KASAN: slab-out-of-bounds in skb_gro_receive |
| Write of size 4 at addr ffff88800cf37004 by task cpumap/1/map:1/146 |
| Call Trace: |
| skb_gro_receive (net/core/gro.c:174) |
| udp_gro_receive (net/ipv4/udp_offload.c:812) |
| inet_gro_receive (net/ipv4/af_inet.c:1539) |
| dev_gro_receive (net/core/gro.c:515) |
| gro_receive_skb (net/core/gro.c:633) |
| cpu_map_kthread_run (kernel/bpf/cpumap.c:395) |
| kthread (kernel/kthread.c:436) |
| ret_from_fork (arch/x86/kernel/process.c:164) |
| ret_from_fork_asm (arch/x86/entry/entry_64.S:255) |
| Kernel panic - not syncing: KASAN: panic_on_warn set ... |
| |
| Fixes: b0d1beeff2a9 ("xdp: implement convert_to_xdp_frame for MEM_TYPE_ZERO_COPY") |
| Cc: stable@vger.kernel.org |
| Reported-by: Xiang Mei <xmei5@asu.edu> |
| Signed-off-by: Weiming Shi <bestswngs@gmail.com> |
| Link: https://patch.msgid.link/20260818154516.793517-1-bestswngs@gmail.com |
| Signed-off-by: Jakub Kicinski <kuba@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/core/xdp.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/net/core/xdp.c |
| +++ b/net/core/xdp.c |
| @@ -549,7 +549,7 @@ struct xdp_frame *xdp_convert_zc_to_xdp_ |
| xdp->data - xdp->data_meta; |
| totsize = xdp->data_end - xdp->data + metasize; |
| |
| - if (sizeof(*xdpf) + totsize > PAGE_SIZE) |
| + if (sizeof(*xdpf) + totsize > SKB_WITH_OVERHEAD(PAGE_SIZE)) |
| return NULL; |
| |
| page = dev_alloc_page(); |
| @@ -566,7 +566,7 @@ struct xdp_frame *xdp_convert_zc_to_xdp_ |
| |
| xdpf->data = addr + metasize; |
| xdpf->len = totsize - metasize; |
| - xdpf->headroom = 0; |
| + xdpf->headroom = metasize; |
| xdpf->metasize = metasize; |
| xdpf->frame_sz = PAGE_SIZE; |
| xdpf->mem.type = MEM_TYPE_PAGE_ORDER0; |