From: sashiko-bot@kernel.org
To: "Björn Töpel" <bjorn@kernel.org>, bpf@vger.kernel.org
Subject: Re: [PATCH net-next v1 03/11] xdp: Copy buffers with restricted lifetime
Date: Wed, 11 Nov 2026 10:22:43 +0000 [thread overview]
Message-ID: <sashiko-outbox-208786@kernel.org> (raw)
In-Reply-To: <20261110102039.1002605-4-bjorn@kernel.org>
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] xdp: missing xdp_data_meta_unsupported() check in
xdp_build_skb_from_zc()
- [High] xdp: skb_shared_info overwrite in xdp_build_skb_from_zc() via
aligned memcpy
It also noticed 2 related pre-existing issues this patch does not
introduce:
- [Critical] bpf: double free and memory leak in xdp_do_redirect() [1]
- [Critical] xdp: double-free in xdp_return_buff() [2]
--
commit b80d3a81c03c102ec5d4e46044e260ec432b9137
Author: Björn Töpel <bjorn@kernel.org>
xdp: Copy buffers with restricted lifetime
This commit adds the MP_CAP_RETAIN memory provider capability and copies XDP
buffers from providers without MP_CAP_RETAIN when building an skb, converting
to an xdp_frame, or redirecting outside XSKMAP.
> diff --git a/net/core/filter.c b/net/core/filter.c
> index 80380f89adf90..f93839b493b25 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -4774,12 +4774,28 @@ int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp,
> {
> struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
> enum bpf_map_type map_type = ri->map_type;
> + struct xdp_frame *xdpf;
> + int err;
>
> if (map_type == BPF_MAP_TYPE_XSKMAP)
> return __xdp_do_redirect_xsk(ri, dev, xdp, xdp_prog);
>
> - return __xdp_do_redirect_frame(ri, dev, xdp_convert_buff_to_frame(xdp),
> - xdp_prog);
> + if (likely(!xdp_buff_needs_copy(xdp)))
> + return __xdp_do_redirect_frame(ri, dev,
> + xdp_convert_buff_to_frame(xdp),
> + xdp_prog);
> +
> + /* Release the source only after the target took the copy. */
> + xdpf = xdp_copy_buff_to_frame(xdp);
> + err = __xdp_do_redirect_frame(ri, dev, xdpf, xdp_prog);
[Severity: Critical]
This problem wasn't introduced by this patch, but can redirecting a
MEM_TYPE_XSK_BUFF_POOL buffer still double free xdp and leak xdpf [1]
when __xdp_do_redirect_frame() fails?
For MEM_TYPE_XSK_BUFF_POOL buffers, xdp_buff_needs_copy(xdp) is false, so
xdp_do_redirect() takes the xdp_convert_buff_to_frame() ->
xdp_convert_zc_to_xdp_frame() path, which frees xdp via xsk_buff_free() before
__xdp_do_redirect_frame() runs. If __xdp_do_redirect_frame() returns an
error, the allocated xdpf is leaked and the caller frees xdp a second time on
its error path.
> diff --git a/net/core/xdp.c b/net/core/xdp.c
> index 1d679e8fd6493..0cf46d492d91b 100644
> --- a/net/core/xdp.c
> +++ b/net/core/xdp.c
> @@ -559,10 +561,41 @@ void xdp_return_buff(struct xdp_buff *xdp)
> xdp->rxq->mem.type, true, xdp);
>
> out:
> - __xdp_return(virt_to_netmem(xdp->data), xdp->rxq->mem.type, true, xdp);
> + __xdp_return(xdp_buff_head_netmem(xdp), xdp->rxq->mem.type, true, xdp);
> }
[Severity: Critical]
This problem wasn't introduced by this patch, but does xdp_return_buff() call
xsk_buff_free(xdp) once per fragment [2] on multi-fragment
MEM_TYPE_XSK_BUFF_POOL buffers?
When xdp->rxq->mem.type is MEM_TYPE_XSK_BUFF_POOL, __xdp_return() ignores the
netmem argument and calls xsk_buff_free(xdp), which frees the head buffer and
all attached fragments at once. Looping over sinfo->nr_frags before the final
__xdp_return() frees the same xdp_buff 1 + nr_frags times, corrupting the XSK
buffer pool.
[ ... ]
> @@ -638,6 +689,9 @@ struct sk_buff *xdp_build_skb_from_buff(const struct xdp_buff *xdp)
> u32 nr_frags = 0;
> int metalen;
>
> + if (unlikely(xdp_buff_needs_copy(xdp)))
> + return xdp_build_skb_from_zc(xdp);
[Severity: High]
Does delegating to xdp_build_skb_from_zc() drop the first byte of the packet
when xdp_data_meta_unsupported(xdp) is true?
When a driver passes meta_valid == false to xdp_prepare_buff(), or calls
xdp_set_data_meta_invalid(), xdp->data_meta is set to xdp->data + 1. Unlike
xdp_copy_buff_to_frame(), xdp_build_skb_from_zc() does not check
xdp_data_meta_unsupported(xdp):
net/core/xdp.c:xdp_build_skb_from_zc() {
const struct xdp_rxq_info *rxq = xdp->rxq;
u32 len = xdp->data_end - xdp->data_meta;
...
skb_reserve(skb, xdp->data_meta - xdp->data_hard_start);
memcpy(__skb_put(skb, len), xdp->data_meta, LARGEST_ALIGN(len));
metalen = xdp->data - xdp->data_meta;
if (metalen > 0) {
skb_metadata_set(skb, metalen);
__skb_pull(skb, metalen);
}
}
With xdp->data_meta == xdp->data + 1, this copies from xdp->data + 1, sets
skb->len one byte short, and skips __skb_pull() because metalen is -1,
corrupting the packet header on XDP_PASS.
[ ... ]
> @@ -781,7 +835,7 @@ struct sk_buff *xdp_build_skb_from_zc(struct xdp_buff *xdp)
> goto out;
> }
>
> - xsk_buff_free(xdp);
> + xdp_release_copied(xdp);
[Severity: High]
Can the LARGEST_ALIGN(len) memcpy in xdp_build_skb_from_zc() overwrite
skb_shinfo(skb) when copying a buffer that reaches xdp_data_hard_end(xdp)?
In xdp_build_skb_from_zc(), napi_build_skb(data, truesize) initializes
skb_shinfo(skb) at data + truesize - SKB_DATA_ALIGN(sizeof(struct
skb_shared_info)), and then:
skb_reserve(skb, xdp->data_meta - xdp->data_hard_start);
memcpy(__skb_put(skb, len), xdp->data_meta, LARGEST_ALIGN(len));
When truesize equals xdp->frame_sz, skb->end is at the same offset from data
as xdp_data_hard_end(xdp) is from xdp->data_hard_start. If an XDP program
adjusts xdp->data or xdp->data_meta to an offset that is not 16-byte aligned
and the head buffer is full up to xdp_data_hard_end(xdp), LARGEST_ALIGN(len)
extends up to 15 bytes past skb->end and overwrites skb_shinfo(skb) (including
nr_frags and frag_list) with bytes from xdp->data_end.
[1] https://sashiko.dev/#/bug/linux-c51b4a6d-8f07-471a-858e-04053743c6d2
[2] https://sashiko.dev/#/bug/linux-ad1513d6-3423-4560-95ce-a92871813ba4
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261110102039.1002605-1-bjorn@kernel.org?part=3
next prev parent reply other threads:[~2026-11-11 10:22 UTC|newest]
Thread overview: 62+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 10:20 [PATCH net-next v1 00/11] xsk: Zero copy through page-pool memory providers Björn Töpel
2026-11-10 10:20 ` [PATCH net-next v1 01/11] net: Get skb fragment addresses through netmem Björn Töpel
2026-11-12 8:32 ` saeed bishara
2026-11-12 13:57 ` Björn Töpel
2026-11-10 10:20 ` [PATCH net-next v1 02/11] net: Add memory provider capabilities Björn Töpel
2026-11-10 22:19 ` Stanislav Fomichev
2026-11-11 12:41 ` Björn Töpel
2026-11-11 23:01 ` Stanislav Fomichev
2026-11-12 14:01 ` Björn Töpel
2026-11-13 0:21 ` Stanislav Fomichev
2026-11-11 10:22 ` sashiko-bot
2026-11-11 22:41 ` netdev-bot+sashiko
2026-11-10 10:20 ` [PATCH net-next v1 03/11] xdp: Copy buffers with restricted lifetime Björn Töpel
2026-11-10 22:32 ` Stanislav Fomichev
2026-11-11 13:27 ` Björn Töpel
2026-11-11 23:05 ` Stanislav Fomichev
2026-11-11 10:22 ` sashiko-bot [this message]
2026-11-11 22:41 ` netdev-bot+sashiko
2026-11-10 10:20 ` [PATCH net-next v1 04/11] xsk: Allocate UMEM chunks through page_pool Björn Töpel
2026-11-10 15:08 ` Magnus Karlsson
2026-11-11 13:51 ` Björn Töpel
2026-11-10 23:02 ` Stanislav Fomichev
2026-11-11 13:59 ` Björn Töpel
2026-11-11 23:09 ` Stanislav Fomichev
2026-11-11 22:41 ` netdev-bot+sashiko
2026-11-10 10:20 ` [PATCH net-next v1 05/11] xsk: Install UMEM page pool providers in the core Björn Töpel
2026-11-10 23:50 ` Stanislav Fomichev
2026-11-11 14:01 ` Björn Töpel
2026-11-11 8:59 ` Magnus Karlsson
2026-11-11 19:26 ` Björn Töpel
2026-11-12 8:08 ` Magnus Karlsson
2026-11-11 10:22 ` sashiko-bot
2026-11-11 22:41 ` netdev-bot+sashiko
2026-11-12 11:53 ` Maciej Fijalkowski
2026-11-12 14:48 ` Björn Töpel
2026-11-12 15:43 ` Maciej Fijalkowski
2026-11-12 19:51 ` Björn Töpel
2026-11-10 10:20 ` [PATCH net-next v1 06/11] page_pool: Coordinate refill with memory providers Björn Töpel
2026-11-10 23:51 ` Stanislav Fomichev
2026-11-11 19:37 ` Björn Töpel
2026-11-11 23:13 ` Stanislav Fomichev
2026-11-12 14:53 ` Björn Töpel
2026-11-11 10:22 ` sashiko-bot
2026-11-11 22:41 ` netdev-bot+sashiko
2026-11-10 10:20 ` [PATCH net-next v1 07/11] xsk: Deliver provider chunks without copying Björn Töpel
2026-11-11 22:41 ` netdev-bot+sashiko
2026-11-11 23:20 ` Stanislav Fomichev
2026-11-12 15:10 ` Björn Töpel
2026-11-12 12:17 ` Maciej Fijalkowski
2026-11-12 19:57 ` Björn Töpel
2026-11-10 10:20 ` [PATCH net-next v1 08/11] eth: fbnic: Support XDP redirect Björn Töpel
2026-11-11 10:22 ` sashiko-bot
2026-11-10 10:20 ` [PATCH net-next v1 09/11] eth: fbnic: Use netmem for RX headers and XDP_TX Björn Töpel
2026-11-10 10:20 ` [PATCH net-next v1 10/11] eth: fbnic: Support RX buffers it cannot split Björn Töpel
2026-11-11 10:22 ` sashiko-bot
2026-11-11 21:45 ` Dimitri Daskalakis
2026-11-11 22:41 ` netdev-bot+sashiko
2026-11-10 10:20 ` [PATCH net-next v1 11/11] eth: fbnic: Support AF_XDP page pool zero copy Björn Töpel
2026-11-11 10:22 ` sashiko-bot
2026-11-11 22:41 ` netdev-bot+sashiko
2026-11-12 11:37 ` Maciej Fijalkowski
2026-11-12 20:03 ` Björn Töpel
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=sashiko-outbox-208786@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bjorn@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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.