From: Jason Xing <kernelxing@tencent.com> mainline inclusion from mainline-v7.1-rc3 commit 3dec153ae484e3b2ddac841156e197ba54c8df94 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/17327 CVE: CVE-2026-74559 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- Once xsk_skb_init_misc() has been called on an skb, its destructor is set to xsk_destruct_skb(), which submits the descriptor address(es) to the completion queue and advances the CQ producer. If such an skb is subsequently freed via kfree_skb() along an error path - before the skb has ever been handed to the driver - the destructor still runs and submits a bogus, half-initialized address to the CQ. Postpone the init phase when we believe the allocation of first frag is successfully completed. Before this init, skb can be safely freed by kfree_skb(). Closes: https://lore.kernel.org/all/20260419045822.843BFC2BCAF@smtp.kernel.org/ Fixes: c30d084960cf ("xsk: avoid overwriting skb fields for multi-buffer traffic") Acked-by: Stanislav Fomichev <sdf@fomichev.me> Signed-off-by: Jason Xing <kernelxing@tencent.com> Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com> Link: https://patch.msgid.link/20260502200722.53960-6-kerneljasonxing@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Conflicts: net/xdp/xsk.c [Commit 48eb03dd2630 not merged.] Signed-off-by: Zhang Changzhong <zhangchangzhong@huawei.com> --- net/xdp/xsk.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index 2625265..9288215 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c @@ -665,8 +665,6 @@ static struct sk_buff *xsk_build_skb_zerocopy(struct xdp_sock *xs, return ERR_PTR(err); skb_reserve(skb, hr); - - xsk_skb_init_misc(skb, xs, desc->addr); } else { struct xsk_addrs *xsk_addr; @@ -757,8 +755,6 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, kfree_skb(skb); goto free_err; } - - xsk_skb_init_misc(skb, xs, desc->addr); } else { int nr_frags = skb_shinfo(skb)->nr_frags; struct xsk_addrs *xsk_addr; @@ -802,6 +798,8 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, } } + if (!xs->skb) + xsk_skb_init_misc(skb, xs, desc->addr); xsk_inc_num_desc(skb); return skb; -- 2.9.5