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 <fw@strlen.de>
Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
---
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);
--
2.43.0