From 3d48a475054911856b736ca2720b82f529dd68cf Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@redhat.com>
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