Blame SOURCES/autofs-5.0.7-fix-crash-due-to-thread-unsafe-use-of-libldap.patch

304803
autofs-5.0.7 - fix crash due to thread unsafe use of libldap
304803
304803
From: Leonardo Chiquitto <leonardo.lists@gmail.com>
304803
304803
Add locking around LDAP initialization calls
304803
304803
To prevent corruption inside SSL and LDAP libraries, it's necessary to
304803
serialize all calls to functions that initialize LDAP contexts.
304803
304803
How to reproduce the problem:
304803
304803
- Setup an LDAP server with SSL/TLS support enabled
304803
- Configure AutoFS to fetch the maps from LDAP
304803
- Make sure the OpenLDAP client library is configured to use SSL
304803
  connections and "usetls" is set to yes in autofs_ldap_auth.conf.
304803
304803
In one directory handled by AutoFS (an indirect mount point), trigger in
304803
parallel some dozens of invalid mounts (ie, try to access keys that do not
304803
exist in the AutoFS map). Repeat until it crashes.
304803
304803
Here it always crashes in less than 20 minutes, normally inside OpenSSL.
304803
Core dump inspection shows that internal SSL structures are corrupted,
304803
with function pointers pointing to random addresses.
304803
304803
Trying to find similar reports on the web, I found this email from an
304803
OpenLDAP developer (partial quote, emphasis mine) [1]:
304803
304803
"As far as I know, libldap is thread safe in the sense that multiple
304803
threads can use separate LDAP* handles without running into concurrency
304803
issues; *except for library initialization*, all accesses to common data
304803
(i.e. global variables) is read-only."
304803
304803
[1]http://www.openldap.org/cgi-bin/wilma_hiliter/openldap-software/200606/msg00252.html
304803
304803
AutoFS implements no locking around LDAP initialization libraries and
304803
it's quite common to see multiple threads executing ldap_initialize()
304803
or ldap_start_tls_s() at the same time.
304803
---
304803
 CHANGELOG             |    1 +
304803
 modules/lookup_ldap.c |   35 ++++++++++++++++++++++++++++++++++-
304803
 2 files changed, 35 insertions(+), 1 deletion(-)
304803
304803
--- autofs-5.0.7.orig/CHANGELOG
304803
+++ autofs-5.0.7/CHANGELOG
304803
@@ -105,6 +105,7 @@
304803
 - fix incorrect append options description in README.v5-release.
304803
 - fix mistake in assignment.
304803
 - use open(2) instead of access(2) to trigger dependent mounts.
304803
+- fix crash due to thread unsafe use of libldap.
304803
 
304803
 25/07/2012 autofs-5.0.7
304803
 =======================
304803
--- autofs-5.0.7.orig/modules/lookup_ldap.c
304803
+++ autofs-5.0.7/modules/lookup_ldap.c
304803
@@ -52,6 +52,12 @@ static struct ldap_schema common_schema[
304803
 };
304803
 static unsigned int common_schema_count = sizeof(common_schema)/sizeof(struct ldap_schema);
304803
 
304803
+/*
304803
+ * Initialization of LDAP and OpenSSL must be always serialized to
304803
+ * avoid corruption of context structures inside these libraries.
304803
+ */
304803
+pthread_mutex_t ldapinit_mutex = PTHREAD_MUTEX_INITIALIZER;
304803
+
304803
 struct ldap_search_params {
304803
 	struct autofs_point *ap;
304803
 	LDAP *ldap;
304803
@@ -138,6 +144,22 @@ int ldap_parse_page_control(LDAP *ldap,
304803
 }
304803
 #endif /* HAVE_LDAP_PARSE_PAGE_CONTROL */
304803
 
304803
+static void ldapinit_mutex_lock(void)
304803
+{
304803
+	int status = pthread_mutex_lock(&ldapinit_mutex);
304803
+	if (status)
304803
+		fatal(status);
304803
+	return;
304803
+}
304803
+
304803
+static void ldapinit_mutex_unlock(void)
304803
+{
304803
+	int status = pthread_mutex_unlock(&ldapinit_mutex);
304803
+	if (status)
304803
+		fatal(status);
304803
+	return;
304803
+}
304803
+
304803
 static void uris_mutex_lock(struct lookup_context *ctxt)
304803
 {
304803
 	int status = pthread_mutex_lock(&ctxt->uris_mutex);
304803
@@ -198,7 +220,7 @@ int unbind_ldap_connection(unsigned logo
304803
 	return rv;
304803
 }
304803
 
304803
-LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt)
304803
+LDAP *__init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt)
304803
 {
304803
 	LDAP *ldap = NULL;
304803
 	struct timeval timeout     = { ctxt->timeout, 0 };
304803
@@ -276,6 +298,17 @@ LDAP *init_ldap_connection(unsigned logo
304803
 
304803
 	return ldap;
304803
 }
304803
+
304803
+LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt)
304803
+{
304803
+	LDAP *ldap;
304803
+
304803
+	ldapinit_mutex_lock();
304803
+	ldap = __init_ldap_connection(logopt, uri, ctxt);
304803
+	ldapinit_mutex_unlock();
304803
+
304803
+	return ldap;
304803
+}
304803
 
304803
 static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key)
304803
 {