ldap/servers/slapd/ldaputil.c | 36 ++++++++++++++++++++++++
ldap/servers/slapd/tools/ldclt/ldapfct.c | 25 ++++++++++++++++
ldap/servers/slapd/tools/rsearch/addthread.c | 26 +++++++++++++++++
ldap/servers/slapd/tools/rsearch/searchthread.c | 32 +++++++++++++++++++++
4 files changed, 119 insertions(+)
New commits:
commit 23c088919f66de014ee7f9aad407468e51451405
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Tue Apr 24 20:09:38 2012 -0600
Ticket #348 - crash in ldap_initialize with multiple threads
https://fedorahosted.org/389/ticket/348
Resolves: Ticket #348
Bug Description: crash in ldap_initialize with multiple threads
Reviewed by: mreynolds (Thanks!)
Branch: master
Fix Description: Protect calls to ldap_initialize() with a mutex to prevent
multiple threads from calling it at the same time.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index 545c703..80ab8cb 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -99,6 +99,24 @@
#if !defined(USE_OPENLDAP)
#include <ldap_ssl.h>
#include <ldappr.h>
+#else
+/* need mutex around ldap_initialize - see
https://fedorahosted.org/389/ticket/348 */
+static PRCallOnceType ol_init_callOnce = {0,0};
+static PRLock *ol_init_lock = NULL;
+
+static PRStatus
+internal_ol_init_init(void)
+{
+ PR_ASSERT(NULL == ol_init_lock);
+ if ((ol_init_lock = PR_NewLock()) == NULL) {
+ PRErrorCode errorCode = PR_GetError();
+ slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init",
"PR_NewLock failed %d:%s\n",
+ errorCode, slapd_pr_strerror(errorCode));
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
#endif
/* the server depends on the old, deprecated ldap_explode behavior which openldap
@@ -737,7 +755,16 @@ slapi_ldap_init_ext(
#if defined(USE_OPENLDAP)
if (ldapurl) {
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
+ "Could not perform internal ol_init init\n");
+ rc = -1;
+ goto done;
+ }
+
+ PR_Lock(ol_init_lock);
rc = ldap_initialize(&ld, ldapurl);
+ PR_Unlock(ol_init_lock);
if (rc) {
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
"Could not initialize LDAP connection to [%s]: %d:%s\n",
@@ -751,7 +778,16 @@ slapi_ldap_init_ext(
} else { /* host port */
makeurl = convert_to_openldap_uri(hostname, port, (secure == 1 ? "ldaps" :
"ldap"));
}
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
+ "Could not perform internal ol_init init\n");
+ rc = -1;
+ goto done;
+ }
+
+ PR_Lock(ol_init_lock);
rc = ldap_initialize(&ld, makeurl);
+ PR_Unlock(ol_init_lock);
if (rc) {
slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
"Could not initialize LDAP connection to [%s]: %d:%s\n",
diff --git a/ldap/servers/slapd/tools/ldclt/ldapfct.c
b/ldap/servers/slapd/tools/ldclt/ldapfct.c
index 0e8a2fb..3f74fd0 100644
--- a/ldap/servers/slapd/tools/ldclt/ldapfct.c
+++ b/ldap/servers/slapd/tools/ldclt/ldapfct.c
@@ -708,6 +708,23 @@ done:
return rc;
}
+
+/* need mutex around ldap_initialize - see
https://fedorahosted.org/389/ticket/348 */
+static PRCallOnceType ol_init_callOnce = {0,0};
+static PRLock *ol_init_lock = NULL;
+
+static PRStatus
+internal_ol_init_init(void)
+{
+ PR_ASSERT(NULL == ol_init_lock);
+ if ((ol_init_lock = PR_NewLock()) == NULL) {
+ PRErrorCode errorCode = PR_GetError();
+ printf("internal_ol_init_init PR_NewLock failed %d\n", errorCode);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
#endif /* USE_OPENLDAP */
/* mctx is a global */
@@ -735,12 +752,20 @@ connectToLDAP(thread_context *tttctx, const char *bufBindDN, const
char *bufPass
ldapurl = PR_smprintf("ldap%s://%s:%d/",
(mode & SSL) ? "s" : "",
mctx.hostname, mctx.port);
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ printf("Could not perform internal ol_init init\n");
+ goto done;
+ }
+
+ PR_Lock(ol_init_lock);
if ((ret = ldap_initialize(&ld, ldapurl))) {
+ PR_Unlock(ol_init_lock);
printf ("ldclt[%d]: T%03d: Cannot ldap_initialize (%s), errno=%d
ldaperror=%d:%s\n",
mctx.pid, thrdNum, ldapurl, errno, ret, my_ldap_err2string(ret));
fflush (stdout);
goto done;
}
+ PR_Unlock(ol_init_lock);
PR_smprintf_free(ldapurl);
ldapurl = NULL;
if (mode & SSL) {
diff --git a/ldap/servers/slapd/tools/rsearch/addthread.c
b/ldap/servers/slapd/tools/rsearch/addthread.c
index f01ba18..a3e5568 100644
--- a/ldap/servers/slapd/tools/rsearch/addthread.c
+++ b/ldap/servers/slapd/tools/rsearch/addthread.c
@@ -176,6 +176,25 @@ static void at_disconnect(AddThread *at)
}
#endif
+#if defined(USE_OPENLDAP)
+/* need mutex around ldap_initialize - see
https://fedorahosted.org/389/ticket/348 */
+static PRCallOnceType ol_init_callOnce = {0,0};
+static PRLock *ol_init_lock = NULL;
+
+static PRStatus
+internal_ol_init_init(void)
+{
+ PR_ASSERT(NULL == ol_init_lock);
+ if ((ol_init_lock = PR_NewLock()) == NULL) {
+ PRErrorCode errorCode = PR_GetError();
+ fprintf(stderr, "internal_ol_init_init PR_NewLock failed %d\n",
errorCode);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+#endif
+
static void at_bind(AddThread *at)
{
int ret;
@@ -185,7 +204,14 @@ static void at_bind(AddThread *at)
at->ld = NULL;
ldapurl = PR_smprintf("ldap://%s:%d", hostname, port);
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ fprintf(stderr, "Could not perform internal ol_init init\n");
+ return;
+ }
+
+ PR_Lock(ol_init_lock);
ret = ldap_initialize(&at->ld, ldapurl);
+ PR_Unlock(ol_init_lock);
PR_smprintf_free(ldapurl);
ldapurl = NULL;
if (ret) {
diff --git a/ldap/servers/slapd/tools/rsearch/searchthread.c
b/ldap/servers/slapd/tools/rsearch/searchthread.c
index 9e2b0d6..8a74d58 100644
--- a/ldap/servers/slapd/tools/rsearch/searchthread.c
+++ b/ldap/servers/slapd/tools/rsearch/searchthread.c
@@ -180,6 +180,24 @@ static int st_bind_core(SearchThread *st, LDAP **ld, char *dn, char
*pw)
return 1;
}
+#if defined(USE_OPENLDAP)
+/* need mutex around ldap_initialize - see
https://fedorahosted.org/389/ticket/348 */
+static PRCallOnceType ol_init_callOnce = {0,0};
+static PRLock *ol_init_lock = NULL;
+
+static PRStatus
+internal_ol_init_init(void)
+{
+ PR_ASSERT(NULL == ol_init_lock);
+ if ((ol_init_lock = PR_NewLock()) == NULL) {
+ PRErrorCode errorCode = PR_GetError();
+ fprintf(stderr, "internal_ol_init_init PR_NewLock failed %d\n",
errorCode);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+#endif
static int st_bind(SearchThread *st)
{
if (!st->ld) {
@@ -189,7 +207,14 @@ static int st_bind(SearchThread *st)
st->ld = NULL;
ldapurl = PR_smprintf("ldap://%s:%d", hostname, port);
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ fprintf(stderr, "Could not perform internal ol_init init\n");
+ return 0;
+ }
+
+ PR_Lock(ol_init_lock);
ret = ldap_initialize(&st->ld, ldapurl);
+ PR_Unlock(ol_init_lock);
PR_smprintf_free(ldapurl);
ldapurl = NULL;
if (ret) {
@@ -212,7 +237,14 @@ static int st_bind(SearchThread *st)
st->ld2 = NULL;
ldapurl = PR_smprintf("ldap://%s:%d", hostname, port);
+ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) {
+ fprintf(stderr, "Could not perform internal ol_init init\n");
+ return 0;
+ }
+
+ PR_Lock(ol_init_lock);
ret = ldap_initialize(&st->ld2, ldapurl);
+ PR_Unlock(ol_init_lock);
PR_smprintf_free(ldapurl);
ldapurl = NULL;
if (ret) {