A concurrent delete can free the migrated state before
xfrm_do_migrate_state() finishes using it.

Fixes: a9d155ea9b44 ("xfrm: add XFRM_MSG_MIGRATE_STATE for single SA migration")
Reported-by: Sashiko <[email protected]>
Signed-off-by: Antony Antony <[email protected]>
---
 net/xfrm/xfrm_user.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 11ec3b14a42f..29cbdc836cfc 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -3468,6 +3468,7 @@ static int xfrm_do_migrate_state(struct sk_buff *skb, 
struct nlmsghdr *nlh,
        __xfrm_state_delete(x);
        spin_unlock_bh(&x->lock);
 
+       xfrm_state_hold(xc);
        err = xfrm_state_migrate_install(x, xc, &m, extack);
        if (err < 0) {
                /*
@@ -3475,6 +3476,7 @@ static int xfrm_do_migrate_state(struct sk_buff *skb, 
struct nlmsghdr *nlh,
                 * free under xfrm_cfg_mutex. Both SAs are gone if it does;
                 * restoring x would risk SN/IV reuse.
                 */
+               xfrm_state_put(xc);
                goto out;
        }
 
@@ -3493,6 +3495,7 @@ static int xfrm_do_migrate_state(struct sk_buff *skb, 
struct nlmsghdr *nlh,
                err = 0;
        }
 
+       xfrm_state_put(xc);
 out:
        xfrm_state_put(x);
        return err;

-- 
2.47.3


Reply via email to