From 3d48a475054911856b736ca2720b82f529dd68cf Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Wed, 1 Oct 2014 14:20:27 -0700 Subject: [PATCH] Bug 1147659 - cyrus-sasl client library (client.c) is not thread safe Description: client_dispose (lib/clinet.c) which closes a connection of a sasl client frees mech_list if the head of the list differs from the head of the global cmechlist->mech_list. But there was a possibility that the list appears in the middle of the global mech list. By freeing the mech, it crashed a multi-threaded sasl client. This patch checks each mech if it is in the global mech list or not. Only if it is not, the mech is freed. --- lib/client.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/lib/client.c b/lib/client.c index 31fe346..3f76483 100644 --- a/lib/client.c +++ b/lib/client.c @@ -324,6 +324,26 @@ int sasl_client_init(const sasl_callback_t *callbacks) return ret; } +/* + * If mech is in cmechlist->mech_list, return 1 + * Otherwise, return 0 + */ +static int mech_is_in_cmechlist(cmechanism_t *mech) +{ + cmechanism_t *m = cmechlist->mech_list; + if (NULL == mech) { + return 0; + } + + while (m && mech) { + if (m == mech) { + return 1; + } + m = m->next; + } + return 0; +} + static void client_dispose(sasl_conn_t *pconn) { sasl_client_conn_t *c_conn=(sasl_client_conn_t *) pconn; @@ -352,6 +372,13 @@ static void client_dispose(sasl_conn_t *pconn) while (m) { prevm = m; m = m->next; + if (mech_is_in_cmechlist(prevm)) { + /* + * If prevm exists in the global mech_list cmechlist->mech_list, + * we should not free it as well as the rest of the list. + */ + break; + } sasl_FREE(prevm); } } -- 1.9.3