From 51caf177a8b720a9631690d761bdb05c634e0f9e Mon Sep 17 00:00:00 2001
From: Quanah Gibson-Mount <quanah@openldap.org>
Date: Thu, 24 Mar 2011 01:53:21 +0000
Subject: [PATCH] ITS#6846

---
 CHANGES                        |  1 +
 servers/slapd/back-meta/bind.c | 34 +++++++++++++++++++++++-----------
 2 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/CHANGES b/CHANGES
index 8910b4d2f3..e36100401d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,7 @@ OpenLDAP 2.4 Change Log
 OpenLDAP 2.4.25 Engineering
 	Fixed slapd add objectclasses in order (ITS#6837)
 	Fixed slapd-ldap chain cn=config support (ITS#6837)
+	Fixed slapd-meta deadlock (ITS#6846)
 	Build Environment
 		Fixed libldap/lberl/util if/else usage (ITS#6832)
 		Fixed Windows odbc32 detection (ITS#6125)
diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c
index 24272b2aca..f9374ae27e 100644
--- a/servers/slapd/back-meta/bind.c
+++ b/servers/slapd/back-meta/bind.c
@@ -42,7 +42,8 @@ meta_back_proxy_authz_bind(
 	int			candidate,
 	Operation		*op,
 	SlapReply		*rs,
-	ldap_back_send_t	sendok );
+	ldap_back_send_t	sendok,
+	int			dolock );
 
 static int
 meta_back_single_bind(
@@ -178,7 +179,7 @@ meta_back_bind( Operation *op, SlapReply *rs )
 			}
 
 			
-			(void)meta_back_proxy_authz_bind( mc, i, op, rs, LDAP_BACK_DONTSEND );
+			(void)meta_back_proxy_authz_bind( mc, i, op, rs, LDAP_BACK_DONTSEND, 1 );
 			lerr = rs->sr_err;
 
 		} else {
@@ -305,7 +306,8 @@ meta_back_bind_op_result(
 	metaconn_t		*mc,
 	int			candidate,
 	int			msgid,
-	ldap_back_send_t	sendok )
+	ldap_back_send_t	sendok,
+	int			dolock )
 {
 	metainfo_t		*mi = ( metainfo_t * )op->o_bd->be_private;
 	metatarget_t		*mt = mi->mi_targets[ candidate ];
@@ -384,7 +386,9 @@ retry:;
 			/* don't let anyone else use this handler,
 			 * because there's a pending bind that will not
 			 * be acknowledged */
-			ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+			if ( dolock) {
+				ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+			}
 			assert( LDAP_BACK_CONN_BINDING( msc ) );
 
 #ifdef DEBUG_205
@@ -393,7 +397,9 @@ retry:;
 #endif /* DEBUG_205 */
 
 			meta_clear_one_candidate( op, mc, candidate );
-			ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+			if ( dolock ) {
+				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
+			}
 
 			rs->sr_err = timeout_err;
 			rs->sr_text = timeout_text;
@@ -516,7 +522,7 @@ meta_back_single_bind(
 
 	mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
 
-	meta_back_bind_op_result( op, rs, mc, candidate, msgid, LDAP_BACK_DONTSEND );
+	meta_back_bind_op_result( op, rs, mc, candidate, msgid, LDAP_BACK_DONTSEND, 1 );
 	if ( rs->sr_err != LDAP_SUCCESS ) {
 		goto return_results;
 	}
@@ -527,7 +533,7 @@ meta_back_single_bind(
 	 * bind with the configured identity assertion */
 	/* NOTE: use with care */
 	if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
-		meta_back_proxy_authz_bind( mc, candidate, op, rs, LDAP_BACK_SENDERR );
+		meta_back_proxy_authz_bind( mc, candidate, op, rs, LDAP_BACK_SENDERR, 1 );
 		if ( !LDAP_BACK_CONN_ISBOUND( msc ) ) {
 			goto return_results;
 		}
@@ -596,7 +602,7 @@ meta_back_single_dobind(
 			( LDAP_BACK_CONN_ISPRIV( mc ) && dn_match( &msc->msc_bound_ndn, &mt->mt_idassert_authcDN ) ) ||
 			( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
 	{
-		(void)meta_back_proxy_authz_bind( mc, candidate, op, rs, sendok );
+		(void)meta_back_proxy_authz_bind( mc, candidate, op, rs, sendok, dolock );
 
 	} else {
 		char *binddn = "";
@@ -622,7 +628,7 @@ meta_back_single_dobind(
 			ldap_pvt_thread_yield();
 		}
 
-		rs->sr_err = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok );
+		rs->sr_err = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok, dolock );
 
 		/* if bind succeeded, but anonymous, clear msc_bound_ndn */
 		if ( rs->sr_err != LDAP_SUCCESS || binddn[0] == '\0' ) {
@@ -1548,7 +1554,13 @@ done:;
 }
 
 static int
-meta_back_proxy_authz_bind( metaconn_t *mc, int candidate, Operation *op, SlapReply *rs, ldap_back_send_t sendok )
+meta_back_proxy_authz_bind(
+	metaconn_t *mc,
+	int candidate,
+	Operation *op,
+	SlapReply *rs,
+	ldap_back_send_t sendok,
+	int dolock )
 {
 	metainfo_t		*mi = (metainfo_t *)op->o_bd->be_private;
 	metatarget_t		*mt = mi->mi_targets[ candidate ];
@@ -1574,7 +1586,7 @@ meta_back_proxy_authz_bind( metaconn_t *mc, int candidate, Operation *op, SlapRe
 				}
 				ldap_pvt_thread_yield();
 			}
-			rc = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok );
+			rc = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok, dolock );
 			if ( rc == LDAP_SUCCESS ) {
 				/* set rebind stuff in case of successful proxyAuthz bind,
 				 * so that referral chasing is attempted using the right
-- 
GitLab