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