From: Wataru Ashihara Subject: iked(8): prevent ikev2_ike_sa_delete() from being called twice on `ikectl reset sa` To: tech@openbsd.org, tobhe@openbsd.org Date: Thu, 11 Sep 2025 11:49:41 +0900 iked(8): prevent ikev2_ike_sa_delete() from being called twice on `ikectl reset sa` Partially reverts the changes in config.c,v 1.67: https://github.com/openbsd/src/commit/9c3d68f7d63149dc76143c6a45a704ad8b90a026 The above commit changed the behavior so that the same `sa` was passed to ikev2_ike_sa_delete(): // when env->sc_sas has only one sa and `ikectl reset sa` is executed: sa = RB_MIN(iked_sas, &env->sc_sas); ikev2_ike_sa_delete(env, sa); // sends Delete sa = RB_MIN(iked_sas, &env->sc_sas); // points to the same sa again ikev2_ike_sa_delete(env, sa); // fail because sa->sa_state:IKEV2_STATE_CLOSED != IKEV2_STATE_ESTABLISHED RB_REMOVE(iked_sas, &env->sc_sas, sa); sa = RB_MIN(iked_sas, &env->sc_sas); // NULL, finish the for loop diff --git a/sbin/iked/config.c b/sbin/iked/config.c index def970e05a0..befd57466cd 100644 --- a/sbin/iked/config.c +++ b/sbin/iked/config.c @@ -566,7 +566,7 @@ int config_doreset(struct iked *env, unsigned int mode) { struct iked_policy *pol, *poltmp; - struct iked_sa *sa; + struct iked_sa *sa, *nextsa; struct iked_user *usr; if (mode == RESET_ALL || mode == RESET_POLICY) { @@ -578,7 +578,9 @@ config_doreset(struct iked *env, unsigned int mode) if (mode == RESET_ALL || mode == RESET_SA) { log_debug("%s: flushing SAs", __func__); - while ((sa = RB_MIN(iked_sas, &env->sc_sas))) { + for (sa = RB_MIN(iked_sas, &env->sc_sas); + sa != NULL; sa = nextsa) { + nextsa = RB_NEXT(iked_sas, &env->sc_sas, sa); /* for RESET_SA we try send a DELETE */ if (mode == RESET_ALL || ikev2_ike_sa_delete(env, sa) != 0) { -- Wataru Ashihara