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.
117 lines
3.8 KiB
117 lines
3.8 KiB
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) |
|
{
|
|
|