From d7470cba6dfaac917710ef77192a94d57cb69f00 Mon Sep 17 00:00:00 2001 From: Jakub Sitnicki Date: Mon, 31 Aug 2026 08:27:38 +0200 Subject: [PATCH 1/2] net: Make skb_ext_put_sp() idempotent The sec_path extension can be released either when it is deleted from an skb or when the last skb holding the extension block is freed. Make skb_ext_put_sp() safe to call from both paths by returning when sec_path->len is zero and clearing it after dropping the XFRM state references. This will let __skb_ext_put() release the sec_path without checking whether the extension is present first, which is needed if we want to reuse skb_ext chunks area after skb scrubbing. Signed-off-by: Jakub Sitnicki Link: https://patch.msgid.link/20260831-skb-ext-prep-work-v1-1-ecc2a8542fd9@cloudflare.com Signed-off-by: Jakub Kicinski --- net/core/skbuff.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 966af3beed94..aa8b42c74f42 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -7236,8 +7236,12 @@ static void skb_ext_put_sp(struct sec_path *sp) { unsigned int i; + if (!sp->len) + return; + for (i = 0; i < sp->len; i++) xfrm_state_put(sp->xvec[i]); + sp->len = 0; } #endif @@ -7260,10 +7264,8 @@ void __skb_ext_del(struct sk_buff *skb, enum skb_ext_id id) #ifdef CONFIG_XFRM } else if (id == SKB_EXT_SEC_PATH && refcount_read(&ext->refcnt) == 1) { - struct sec_path *sp = skb_ext_get_ptr(ext, SKB_EXT_SEC_PATH); - skb_ext_put_sp(sp); - sp->len = 0; + skb_ext_put_sp(skb_ext_get_ptr(ext, SKB_EXT_SEC_PATH)); #endif } } From dbe45b209edf9b43ec56a1e6858c055c1eb332c3 Mon Sep 17 00:00:00 2001 From: Jakub Sitnicki Date: Mon, 31 Aug 2026 08:27:39 +0200 Subject: [PATCH 2/2] net: Make skb_ext_put_mctp() idempotent The MCTP flow extension can be released either when it is deleted from an skb or when the last skb holding the extension block is freed. Handle the release in __skb_ext_del(), which is currently missing, and make skb_ext_put_mctp() safe to call from both paths. This will let __skb_ext_put() release the MCTP key without checking whether the extension is present first, which is needed if we want to reuse skb_ext chunks area after skb scrubbing. Suggested-by: Florian Westphal Signed-off-by: Jakub Sitnicki Acked-by: Jeremy Kerr Link: https://patch.msgid.link/20260831-skb-ext-prep-work-v1-2-ecc2a8542fd9@cloudflare.com Signed-off-by: Jakub Kicinski --- net/core/skbuff.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index aa8b42c74f42..ab195b99c853 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -7248,8 +7248,11 @@ static void skb_ext_put_sp(struct sec_path *sp) #ifdef CONFIG_MCTP_FLOWS static void skb_ext_put_mctp(struct mctp_flow *flow) { - if (flow->key) - mctp_key_unref(flow->key); + if (!flow->key) + return; + + mctp_key_unref(flow->key); + flow->key = NULL; } #endif @@ -7261,13 +7264,20 @@ void __skb_ext_del(struct sk_buff *skb, enum skb_ext_id id) if (skb->active_extensions == 0) { skb->extensions = NULL; __skb_ext_put(ext); -#ifdef CONFIG_XFRM - } else if (id == SKB_EXT_SEC_PATH && - refcount_read(&ext->refcnt) == 1) { + return; + } + if (refcount_read(&ext->refcnt) > 1) + return; + +#ifdef CONFIG_XFRM + if (id == SKB_EXT_SEC_PATH) skb_ext_put_sp(skb_ext_get_ptr(ext, SKB_EXT_SEC_PATH)); #endif - } +#ifdef CONFIG_MCTP_FLOWS + if (id == SKB_EXT_MCTP) + skb_ext_put_mctp(skb_ext_get_ptr(ext, SKB_EXT_MCTP)); +#endif } EXPORT_SYMBOL(__skb_ext_del);