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 --- 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