From 77bf30377cb863783399080df4d99bb95495102a Mon Sep 17 00:00:00 2001 From: Kp Date: Sat, 28 Jun 2008 00:28:25 -0500 Subject: [PATCH] Fix reference counting for key exchange handling. When a key exchange times out, the SKE can be freed before the user responds. Switch the SKE callbacks to obtain their own reference to the object to prevent this. --- lib/silcske/silcske.c | 23 ++++++++--------------- lib/silcske/silcske_i.h | 2 -- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/lib/silcske/silcske.c b/lib/silcske/silcske.c index bac8a5c4..00d39322 100644 --- a/lib/silcske/silcske.c +++ b/lib/silcske/silcske.c @@ -957,7 +957,7 @@ static SilcBool silc_ske_packet_send(SilcSKE ske, static void silc_ske_completion(SilcSKE ske) { /* Call the completion callback */ - if (!ske->freed && !ske->aborted && ske->callbacks->completed) { + if (!ske->aborted && ske->callbacks->completed) { if (ske->status != SILC_SKE_STATUS_OK) ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL, ske->callbacks->context); @@ -973,8 +973,6 @@ static void silc_ske_finished(SilcFSM fsm, void *fsm_context, void *destructor_context) { SilcSKE ske = fsm_context; - ske->running = FALSE; - if (ske->freed) silc_ske_free(ske); } @@ -1036,13 +1034,10 @@ SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule, void silc_ske_free(SilcSKE ske) { - SILC_LOG_DEBUG(("Freeing Key Exchange object")); - if (!ske) return; - if (ske->running) { - ske->freed = TRUE; + SILC_LOG_DEBUG(("Freeing Key Exchange object %p: aborted=%u refcount=%hu", ske, ske->aborted, ske->refcnt)); if (ske->aborted) { /* If already aborted, destroy the session immediately */ @@ -1054,8 +1049,6 @@ void silc_ske_free(SilcSKE ske) silc_fsm_next(&ske->fsm, silc_ske_st_initiator_failure); silc_fsm_continue_sync(&ske->fsm); } - return; - } ske->refcnt--; if (ske->refcnt > 0) @@ -1102,7 +1095,7 @@ void silc_ske_free(SilcSKE ske) silc_free(ske->hash); silc_free(ske->callbacks); - memset(ske, 'F', sizeof(*ske)); + memset(ske, 0xdd, sizeof(*ske)); silc_free(ske); } @@ -1805,7 +1798,7 @@ SilcAsyncOperation silc_ske_initiator(SilcSKE ske, SilcSKEParams params, SilcSKEStartPayload start_payload) { - SILC_LOG_DEBUG(("Start SKE as initiator")); + SILC_LOG_DEBUG(("Start SKE %p as initiator; stream=%p; params=%p; start_payload=%p", ske, stream, params, start_payload)); if (!ske || !stream || !params || !params->version) return NULL; @@ -1831,7 +1824,7 @@ SilcAsyncOperation silc_ske_initiator(SilcSKE ske, ske->timeout = params->timeout_secs ? params->timeout_secs : 30; ske->start_payload = start_payload; ske->version = params->version; - ske->running = TRUE; + ++ ske->refcnt; /* Link to packet stream to get key exchange packets */ ske->stream = stream; @@ -2418,7 +2411,7 @@ SilcAsyncOperation silc_ske_responder(SilcSKE ske, ske->version = params->version; if (!ske->version) return NULL; - ske->running = TRUE; + ++ ske->refcnt; /* Link to packet stream to get key exchange packets */ ske->stream = stream; @@ -2676,8 +2669,8 @@ silc_ske_rekey_initiator(SilcSKE ske, ske->rekey = rekey; ske->responder = FALSE; - ske->running = TRUE; ske->rekeying = TRUE; + ++ ske->refcnt; /* Link to packet stream to get key exchange packets */ ske->stream = stream; @@ -2953,9 +2946,9 @@ silc_ske_rekey_responder(SilcSKE ske, ske->rekey = rekey; ske->responder = TRUE; - ske->running = TRUE; ske->rekeying = TRUE; ske->packet = packet; + ++ ske->refcnt; /* Link to packet stream to get key exchange packets */ ske->stream = stream; diff --git a/lib/silcske/silcske_i.h b/lib/silcske/silcske_i.h index 05132455..e716f58d 100644 --- a/lib/silcske/silcske_i.h +++ b/lib/silcske/silcske_i.h @@ -91,9 +91,7 @@ struct SilcSKEStruct { SilcUInt16 refcnt; /* Reference counter */ unsigned int aborted : 1; /* Set when SKE aborted */ - unsigned int freed : 1; /* Set when freed during session */ unsigned int responder : 1; /* Set when we are responder side */ - unsigned int running : 1; /* Set when SKE is running */ unsigned int rekeying : 1; /* Set when rekeying */ }; -- 2.24.0