]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
Revert "xfrm: destroy xfrm_state synchronously on net exit path"
authorSabrina Dubroca <sd@queasysnail.net>
Tue, 29 Jul 2025 21:11:53 +0000 (17:11 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 12 Dec 2025 17:37:17 +0000 (18:37 +0100)
[ Upstream commit 2a198bbec6913ae1c90ec963750003c6213668c7 ]

This reverts commit f75a2804da391571563c4b6b29e7797787332673.

With all states (whether user or kern) removed from the hashtables
during deletion, there's no need for synchronous destruction of
states. xfrm6_tunnel states still need to have been destroyed (which
will be the case when its last user is deleted (not destroyed)) so
that xfrm6_tunnel_free_spi removes it from the per-netns hashtable
before the netns is destroyed.

This has the benefit of skipping one synchronize_rcu per state (in
__xfrm_state_destroy(sync=true)) when we exit a netns.

Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/net/xfrm.h
net/ipv6/xfrm6_tunnel.c
net/key/af_key.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c

index d51204041bf7dda223ed13fb705e44853e4bcbd4..b6fff506bf30c2e351fb4e5faac8562dbfa945cf 100644 (file)
@@ -851,7 +851,7 @@ static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
                xfrm_pol_put(pols[i]);
 }
 
-void __xfrm_state_destroy(struct xfrm_state *, bool);
+void __xfrm_state_destroy(struct xfrm_state *);
 
 static inline void __xfrm_state_put(struct xfrm_state *x)
 {
@@ -861,13 +861,7 @@ static inline void __xfrm_state_put(struct xfrm_state *x)
 static inline void xfrm_state_put(struct xfrm_state *x)
 {
        if (refcount_dec_and_test(&x->refcnt))
-               __xfrm_state_destroy(x, false);
-}
-
-static inline void xfrm_state_put_sync(struct xfrm_state *x)
-{
-       if (refcount_dec_and_test(&x->refcnt))
-               __xfrm_state_destroy(x, true);
+               __xfrm_state_destroy(x);
 }
 
 static inline void xfrm_state_hold(struct xfrm_state *x)
@@ -1705,7 +1699,7 @@ struct xfrmk_spdinfo {
 
 struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq, u32 pcpu_num);
 int xfrm_state_delete(struct xfrm_state *x);
-int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync);
+int xfrm_state_flush(struct net *net, u8 proto, bool task_valid);
 int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_valid);
 int xfrm_dev_policy_flush(struct net *net, struct net_device *dev,
                          bool task_valid);
index 7fd8bc08e6eb1a8df31c54d7614b62dd22acff3f..5120a763da0d95d6eb1f4a839b05bd60f9584c8f 100644 (file)
@@ -334,7 +334,7 @@ static void __net_exit xfrm6_tunnel_net_exit(struct net *net)
        struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net);
        unsigned int i;
 
-       xfrm_state_flush(net, 0, false, true);
+       xfrm_state_flush(net, IPSEC_PROTO_ANY, false);
        xfrm_flush_gc();
 
        for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++)
index c56bb4f451e6deaac7b6f2b1fcba4a3e51cf15c2..9dea2b26e506937bd99a57476774c6366d1b8596 100644 (file)
@@ -1766,7 +1766,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, const struct sadb_m
        if (proto == 0)
                return -EINVAL;
 
-       err = xfrm_state_flush(net, proto, true, false);
+       err = xfrm_state_flush(net, proto, true);
        err2 = unicast_flush_resp(sk, hdr);
        if (err || err2) {
                if (err == -ESRCH) /* empty table - go quietly */
index e4500d481e26b12e219f877b1e73159af9b9cd12..9cd747cfcc34c6cb7dab26e337711508aec06a1f 100644 (file)
@@ -531,7 +531,7 @@ void xfrm_state_free(struct xfrm_state *x)
 }
 EXPORT_SYMBOL(xfrm_state_free);
 
-static void ___xfrm_state_destroy(struct xfrm_state *x)
+static void xfrm_state_gc_destroy(struct xfrm_state *x)
 {
        hrtimer_cancel(&x->mtimer);
        del_timer_sync(&x->rtimer);
@@ -569,7 +569,7 @@ static void xfrm_state_gc_task(struct work_struct *work)
        synchronize_rcu();
 
        hlist_for_each_entry_safe(x, tmp, &gc_list, gclist)
-               ___xfrm_state_destroy(x);
+               xfrm_state_gc_destroy(x);
 }
 
 static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
@@ -732,19 +732,14 @@ void xfrm_dev_state_free(struct xfrm_state *x)
 }
 #endif
 
-void __xfrm_state_destroy(struct xfrm_state *x, bool sync)
+void __xfrm_state_destroy(struct xfrm_state *x)
 {
        WARN_ON(x->km.state != XFRM_STATE_DEAD);
 
-       if (sync) {
-               synchronize_rcu();
-               ___xfrm_state_destroy(x);
-       } else {
-               spin_lock_bh(&xfrm_state_gc_lock);
-               hlist_add_head(&x->gclist, &xfrm_state_gc_list);
-               spin_unlock_bh(&xfrm_state_gc_lock);
-               schedule_work(&xfrm_state_gc_work);
-       }
+       spin_lock_bh(&xfrm_state_gc_lock);
+       hlist_add_head(&x->gclist, &xfrm_state_gc_list);
+       spin_unlock_bh(&xfrm_state_gc_lock);
+       schedule_work(&xfrm_state_gc_work);
 }
 EXPORT_SYMBOL(__xfrm_state_destroy);
 
@@ -859,7 +854,7 @@ xfrm_dev_state_flush_secctx_check(struct net *net, struct net_device *dev, bool
 }
 #endif
 
-int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync)
+int xfrm_state_flush(struct net *net, u8 proto, bool task_valid)
 {
        int i, err = 0, cnt = 0;
 
@@ -3218,7 +3213,7 @@ void xfrm_state_fini(struct net *net)
        unsigned int sz;
 
        flush_work(&net->xfrm.state_hash_work);
-       xfrm_state_flush(net, 0, false, true);
+       xfrm_state_flush(net, IPSEC_PROTO_ANY, false);
        flush_work(&xfrm_state_gc_work);
 
        WARN_ON(!list_empty(&net->xfrm.state_all));
index 3d0fdeebaf3c8fa87628e3dba0bda4c793d62900..1a4d2fac08594fa2531fbc9540233d8a15e2a63d 100644 (file)
@@ -2571,7 +2571,7 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
        struct xfrm_usersa_flush *p = nlmsg_data(nlh);
        int err;
 
-       err = xfrm_state_flush(net, p->proto, true, false);
+       err = xfrm_state_flush(net, p->proto, true);
        if (err) {
                if (err == -ESRCH) /* empty table */
                        return 0;