From 84a5208d98aa3987ed1cf6b78c7965031b696750 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 24 Nov 2025 12:24:21 +0100 Subject: [PATCH] child-rekey: Prevent crash if peer rekeys a Child SA twice before sending a delete Some (Windows) peers have been seen to initiate a second rekeying for the same Child SA. Presumably, this happens if a rekey request from us for the same old Child SA arrives while it waits for the response to its first rekey request. Once we receive the delete for the old SA, we conclude the rekeying with the second replacement. However, the first replacement remained linked to the old SA. So this change prevents a crash once the peer sends a delete for that first replacement (which it seems to do after about 5 minutes). References strongswan/strongswan#2944 Closes strongswan/strongswan#2945 --- src/libcharon/sa/ikev2/tasks/child_rekey.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c index c1d692dce..80c3b2131 100644 --- a/src/libcharon/sa/ikev2/tasks/child_rekey.c +++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c @@ -400,7 +400,7 @@ METHOD(task_t, build_r, status_t, { notify_payload_t *notify; child_cfg_t *config; - child_sa_t *child_sa; + child_sa_t *child_sa, *old_replacement; child_sa_state_t state = CHILD_INSTALLED; uint32_t reqid; bool followup_sent = FALSE; @@ -470,6 +470,13 @@ METHOD(task_t, build_r, status_t, if (child_sa && child_sa->get_state(child_sa) == CHILD_INSTALLED) { this->child_sa->set_state(this->child_sa, CHILD_REKEYED); + /* we've seen peers sending multiple rekey requests (probably a bug in + * their collision handling), so make sure we unlink any previous SA */ + old_replacement = this->child_sa->get_rekey_sa(this->child_sa); + if (old_replacement) + { + old_replacement->set_rekey_sa(old_replacement, NULL); + } /* link the SAs to handle possible collisions */ this->child_sa->set_rekey_sa(this->child_sa, child_sa); child_sa->set_rekey_sa(child_sa, this->child_sa);