]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfrm: state: silence sparse warnings during netns exit
authorSabrina Dubroca <sd@queasysnail.net>
Mon, 9 Mar 2026 10:32:39 +0000 (11:32 +0100)
committerSteffen Klassert <steffen.klassert@secunet.com>
Thu, 12 Mar 2026 06:15:38 +0000 (07:15 +0100)
Silence sparse warnings in xfrm_state_fini:
net/xfrm/xfrm_state.c:3327:9: warning: incorrect type in argument 1 (different address spaces)
net/xfrm/xfrm_state.c:3327:9:    expected struct hlist_head const *h
net/xfrm/xfrm_state.c:3327:9:    got struct hlist_head [noderef] __rcu *state_byseq

Add xfrm_state_deref_netexit() to wrap those calls. The netns is going
away, we don't have to worry about the state_by* pointers being
changed behind our backs.

Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
net/xfrm/xfrm_state.c

index f28cbe249c05fa93fc0665bf9a7cd9cb766c4eb1..1748d374abcab38949d0b9958fce0bbcc3c7e054 100644 (file)
@@ -3316,6 +3316,8 @@ out_bydst:
        return -ENOMEM;
 }
 
+#define xfrm_state_deref_netexit(table) \
+       rcu_dereference_protected((table), true /* netns is going away */)
 void xfrm_state_fini(struct net *net)
 {
        unsigned int sz;
@@ -3328,17 +3330,17 @@ void xfrm_state_fini(struct net *net)
        WARN_ON(!list_empty(&net->xfrm.state_all));
 
        for (i = 0; i <= net->xfrm.state_hmask; i++) {
-               WARN_ON(!hlist_empty(net->xfrm.state_byseq + i));
-               WARN_ON(!hlist_empty(net->xfrm.state_byspi + i));
-               WARN_ON(!hlist_empty(net->xfrm.state_bysrc + i));
-               WARN_ON(!hlist_empty(net->xfrm.state_bydst + i));
+               WARN_ON(!hlist_empty(xfrm_state_deref_netexit(net->xfrm.state_byseq) + i));
+               WARN_ON(!hlist_empty(xfrm_state_deref_netexit(net->xfrm.state_byspi) + i));
+               WARN_ON(!hlist_empty(xfrm_state_deref_netexit(net->xfrm.state_bysrc) + i));
+               WARN_ON(!hlist_empty(xfrm_state_deref_netexit(net->xfrm.state_bydst) + i));
        }
 
        sz = (net->xfrm.state_hmask + 1) * sizeof(struct hlist_head);
-       xfrm_hash_free(net->xfrm.state_byseq, sz);
-       xfrm_hash_free(net->xfrm.state_byspi, sz);
-       xfrm_hash_free(net->xfrm.state_bysrc, sz);
-       xfrm_hash_free(net->xfrm.state_bydst, sz);
+       xfrm_hash_free(xfrm_state_deref_netexit(net->xfrm.state_byseq), sz);
+       xfrm_hash_free(xfrm_state_deref_netexit(net->xfrm.state_byspi), sz);
+       xfrm_hash_free(xfrm_state_deref_netexit(net->xfrm.state_bysrc), sz);
+       xfrm_hash_free(xfrm_state_deref_netexit(net->xfrm.state_bydst), sz);
        free_percpu(net->xfrm.state_cache_input);
 }