sbonazzo / rpms / cyrus-sasl

Forked from rpms/cyrus-sasl 2 years ago
Clone
Blob Blame History Raw
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