Commit 84a5208d98 for strongswan.org
commit 84a5208d98aa3987ed1cf6b78c7965031b696750
Author: Tobias Brunner <tobias@strongswan.org>
Date: Mon Nov 24 12:24:21 2025 +0100
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
diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c
index c1d692dce4..80c3b21311 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);