Download raw body.
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
iked(8): prevent ikev2_ike_sa_delete() from being called twice on `ikectl reset sa`