From: Petr Wozniak <petr.wozniak@gmail.com> mainline inclusion from mainline-v7.2-rc4 commit 3f4c3919baf0944ad96580467c302bc6c7758b00 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/17032 CVE: CVE-2026-68426 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- skb_gso_segment() leaves the segment list head with ->prev pointing at the last segment, an invariant validate_xmit_skb_list() relies on when it sets its tail pointer (tail = skb->prev). When validate_xmit_xfrm() walks a GSO list and some segments are stolen by async crypto (->xmit() returns -EINPROGRESS), those segments are unlinked from the list but the head ->prev is never updated. If the last segment is the one stolen, the returned head still has ->prev pointing at it, even though it is now owned by the crypto engine and may be freed. validate_xmit_skb_list() later does tail->next = skb, writing through that stale pointer -- a use-after-free. Repoint skb->prev at the last retained segment before returning. Fixes: f53c723902d1 ("net: Add asynchronous callbacks for xfrm on layer 2.") Signed-off-by: Petr Wozniak <petr.wozniak@gmail.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Conflicts: net/xfrm/xfrm_device.c [mainline commit 6860b467f569 ("xfrm: propagate -EINPROGRESS from validate_xmit_xfrm()") is not backport, which lead to conflicts: this is a Class B non-Stable-dep-of prerequisite (pure control-flow change turning NULL return into ERR_PTR(-EINPROGRESS), no dev_hold/refcount/ lock/UAF involvement). Applied forced minimal adaptation per P3: kept target's "return skb;" (5.10 callers already handle NULL via "if (!skb) continue;"), applied only the CVE change "if (skb) skb->prev = pskb;" to repoint the GSO head ->prev at the last retained segment so validate_xmit_skb_list() cannot chain onto a segment stolen by async crypto (use-after-free). Refcount/lifetime analysis: added code takes no reference and acquires no lock; ownership of stolen skbs remains with the crypto engine via the xfrm_dev_resume() path, unchanged] Signed-off-by: Dong Chenchen <dongchenchen2@huawei.com> --- net/xfrm/xfrm_device.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c index 0e7424b8a5fa..062caeb893a5 100644 --- a/net/xfrm/xfrm_device.c +++ b/net/xfrm/xfrm_device.c @@ -215,6 +215,14 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur pskb = skb2; } + /* skb_gso_segment() set skb->prev to the last segment, but async + * crypto may have stolen it above without updating ->prev. Repoint + * it at the last retained segment so validate_xmit_skb_list() does + * not chain onto a segment now owned by the crypto engine. + */ + if (skb) + skb->prev = pskb; + return skb; } EXPORT_SYMBOL_GPL(validate_xmit_xfrm); -- 2.43.0