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 <jakub@cloudflare.com>
---
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
}
}
--
2.43.0