Index | Thread | Search

From:
Wataru Ashihara <wsh@iij.ad.jp>
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

Download raw body.

Thread
  • Wataru Ashihara:

    iked(8): prevent ikev2_ike_sa_delete() from being called twice on `ikectl reset sa`

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