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