zrhoffman / rpms / 389-ds-base

Forked from rpms/389-ds-base 3 years ago
Clone

Blame SOURCES/0061-Ticket-49356-mapping-tree-crash-can-occur-during-tot.patch

61f723
From b0954a5df7841330732a5ab532c528a68cf380cf Mon Sep 17 00:00:00 2001
61f723
From: William Brown <firstyear@redhat.com>
61f723
Date: Fri, 18 Aug 2017 13:00:46 +1000
61f723
Subject: [PATCH] Ticket 49356 - mapping tree crash can occur during tot init
61f723
61f723
Bug Description:  Two faults were found in the handling of the mapping
61f723
tree of 389 directory server. The first fault was that the tree-free
61f723
check was not performed atomically and may cause an incorrect operations
61f723
error to be returned. The second was that during a total init the referral
61f723
would not lock the be, but the pw_verify code assumed a be was locked.
61f723
This caused a segfault.
61f723
61f723
Fix Description:  Fix the freed check to use atomics. Fix the pw_verify
61f723
to assert be is NULL (which is correct, there is no backend).
61f723
61f723
https://pagure.io/389-ds-base/issue/49356
61f723
61f723
Author: wibrown
61f723
61f723
Review by: mreynolds (THanks!)
61f723
---
61f723
 .../mapping_tree/referral_during_tot_init.py       |  57 ++++++++
61f723
 ldap/servers/slapd/fedse.c                         |  10 ++
61f723
 ldap/servers/slapd/main.c                          |  10 --
61f723
 ldap/servers/slapd/mapping_tree.c                  | 150 +++++++++++----------
61f723
 ldap/servers/slapd/pw_verify.c                     |   8 +-
61f723
 5 files changed, 150 insertions(+), 85 deletions(-)
61f723
 create mode 100644 dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py
61f723
61f723
diff --git a/dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py b/dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py
61f723
new file mode 100644
61f723
index 0000000..e5aee7d
61f723
--- /dev/null
61f723
+++ b/dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py
61f723
@@ -0,0 +1,57 @@
61f723
+# --- BEGIN COPYRIGHT BLOCK ---
61f723
+# Copyright (C) 2017 Red Hat, Inc.
61f723
+# All rights reserved.
61f723
+#
61f723
+# License: GPL (version 3 or any later version).
61f723
+# See LICENSE for details.
61f723
+# --- END COPYRIGHT BLOCK ---
61f723
+#
61f723
+import ldap
61f723
+import pytest
61f723
+from lib389.topologies import topology_m2
61f723
+from lib389._constants import (DEFAULT_SUFFIX, HOST_MASTER_2, PORT_MASTER_2, TASK_WAIT)
61f723
+
61f723
+from lib389.idm.user import (TEST_USER_PROPERTIES, UserAccounts)
61f723
+
61f723
+def test_referral_during_tot(topology_m2):
61f723
+
61f723
+    master1 = topology_m2.ms["master1"]
61f723
+    master2 = topology_m2.ms["master2"]
61f723
+
61f723
+    # Create a bunch of entries on master1
61f723
+    ldif_dir = master1.get_ldif_dir()
61f723
+    import_ldif = ldif_dir + '/ref_during_tot_import.ldif'
61f723
+    master1.buildLDIF(10000, import_ldif)
61f723
+
61f723
+    master1.stop()
61f723
+    try:
61f723
+        master1.ldif2db(bename=None, excludeSuffixes=None, encrypt=False, suffixes=[DEFAULT_SUFFIX], import_file=import_ldif)
61f723
+    except:
61f723
+        pass
61f723
+    # master1.tasks.importLDIF(suffix=DEFAULT_SUFFIX, input_file=import_ldif, args={TASK_WAIT: True})
61f723
+    master1.start()
61f723
+    users = UserAccounts(master1, DEFAULT_SUFFIX, rdn='ou=Accounting')
61f723
+
61f723
+    u = users.create(properties=TEST_USER_PROPERTIES)
61f723
+    u.set('userPassword', 'password')
61f723
+
61f723
+    binddn = u.dn
61f723
+    bindpw = 'password'
61f723
+
61f723
+    # Now export them to master2
61f723
+    master1.agreement.init(DEFAULT_SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
61f723
+
61f723
+    # While that's happening try to bind as a user to master 2
61f723
+    # This should trigger the referral code.
61f723
+    for i in range(0, 100):
61f723
+        conn = ldap.initialize(master2.toLDAPURL())
61f723
+        conn.set_option(ldap.OPT_REFERRALS, False)
61f723
+        try:
61f723
+            conn.simple_bind_s(binddn, bindpw)
61f723
+            conn.unbind_s()
61f723
+        except ldap.REFERRAL:
61f723
+            pass
61f723
+
61f723
+    # Done.
61f723
+
61f723
+
61f723
diff --git a/ldap/servers/slapd/fedse.c b/ldap/servers/slapd/fedse.c
61f723
index 13a3c74..c2a862b 100644
61f723
--- a/ldap/servers/slapd/fedse.c
61f723
+++ b/ldap/servers/slapd/fedse.c
61f723
@@ -1853,6 +1853,16 @@ setup_internal_backends(char *configdir)
61f723
 		be_addsuffix(be,&monitor);
61f723
 		be_addsuffix(be,&config);
61f723
 
61f723
+        /*
61f723
+         * Now that the be's are in place, we can
61f723
+         * setup the mapping tree.
61f723
+         */
61f723
+
61f723
+        if (mapping_tree_init()) {
61f723
+            slapi_log_err(SLAPI_LOG_EMERG, "setup_internal_backends", "Failed to init mapping tree\n");
61f723
+            exit(1);
61f723
+        }
61f723
+
61f723
 		add_internal_entries();
61f723
 
61f723
 		add_easter_egg_entry();
61f723
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
61f723
index 552d54d..1d9afce 100644
61f723
--- a/ldap/servers/slapd/main.c
61f723
+++ b/ldap/servers/slapd/main.c
61f723
@@ -1034,16 +1034,6 @@ main( int argc, char **argv)
61f723
 
61f723
 		ps_init_psearch_system();   /* must come before plugin_startall() */
61f723
 
61f723
-		/* Initailize the mapping tree */
61f723
-
61f723
-		if (mapping_tree_init())
61f723
-		{
61f723
-			slapi_log_err(SLAPI_LOG_EMERG, "main", "Failed to init mapping tree\n");
61f723
-			return_value = 1;
61f723
-			goto cleanup;
61f723
-		}
61f723
-
61f723
-
61f723
 		/* initialize UniqueID generator - must be done once backends are started
61f723
 		   and event queue is initialized but before plugins are started */
61f723
 		/* Note: This DN is no need to be normalized. */
61f723
diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c
61f723
index 1b8d2d9..dfb6584 100644
61f723
--- a/ldap/servers/slapd/mapping_tree.c
61f723
+++ b/ldap/servers/slapd/mapping_tree.c
61f723
@@ -88,13 +88,13 @@ struct mt_node
61f723
  *      release backend lock 
61f723
  *
61f723
  */
61f723
-static Slapi_RWLock    *myLock;    /* global lock on the mapping tree structures */
61f723
+static Slapi_RWLock *myLock = NULL; /* global lock on the mapping tree structures */
61f723
 
61f723
 
61f723
 static mapping_tree_node *mapping_tree_root = NULL;
61f723
-static int mapping_tree_inited = 0;
61f723
-static int mapping_tree_freed = 0;
61f723
-static int extension_type = -1;    /* type returned from the factory */
61f723
+static int32_t mapping_tree_inited = 0;
61f723
+static int32_t mapping_tree_freed = 0;
61f723
+static int extension_type = -1; /* type returned from the factory */
61f723
 
61f723
 /* The different states a mapping tree node can be in. */
61f723
 #define    MTN_DISABLED                 0    /* The server acts like the node isn't there. */
61f723
@@ -1659,22 +1659,24 @@ add_internal_mapping_tree_node(const char *subtree, Slapi_Backend *be, mapping_t
61f723
 {
61f723
     Slapi_DN *dn;
61f723
     mapping_tree_node *node;
61f723
-    backend ** be_list = (backend **) slapi_ch_malloc(sizeof(backend *));
61f723
+    backend **be_list = (backend **)slapi_ch_malloc(sizeof(backend *));
61f723
+    int *be_states = (int *)slapi_ch_malloc(sizeof(int));
61f723
 
61f723
     be_list[0] = be;
61f723
+    be_states[0] = SLAPI_BE_STATE_ON;
61f723
 
61f723
     dn = slapi_sdn_new_dn_byval(subtree);
61f723
-    node= mapping_tree_node_new(
61f723
-            dn,
61f723
-            be_list,
61f723
-            NULL, /* backend_name */
61f723
-            NULL,
61f723
-            1,    /* number of backends at this node */
61f723
-            1,    /* size of backend list structure */
61f723
-            NULL, /* referral */
61f723
-            parent,
61f723
-            MTN_BACKEND,
61f723
-            1, /* The config  node is a private node.
61f723
+    node = mapping_tree_node_new(
61f723
+        dn,
61f723
+        be_list,
61f723
+        NULL, /* backend_name */
61f723
+        be_states, /* be state */
61f723
+        1,    /* number of backends at this node */
61f723
+        1,    /* size of backend list structure */
61f723
+        NULL, /* referral */
61f723
+        parent,
61f723
+        MTN_BACKEND,
61f723
+        1,                    /* The config  node is a private node.
61f723
                 *  People can't see or change it. */
61f723
             NULL, NULL, NULL, 0); /* no distribution */
61f723
     return node;
61f723
@@ -1722,17 +1724,20 @@ mapping_tree_init()
61f723
     
61f723
     /* we call this function from a single thread, so it should be ok */
61f723
 
61f723
-    if(mapping_tree_freed){
61f723
-    /* shutdown has been detected */
61f723
-      return 0;
61f723
-    }
61f723
-
61f723
-    if (mapping_tree_inited)
61f723
+    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
61f723
+        /* shutdown has been detected */
61f723
         return 0;
61f723
+    }
61f723
 
61f723
-    /* ONREPL - I have moved this up because otherwise we can endup calling this 
61f723
+    /* ONREPL - I have moved this up because otherwise we can endup calling this
61f723
      * function recursively */
61f723
+    if (myLock != NULL) {
61f723
+        return 0;
61f723
+    }
61f723
+    myLock = slapi_new_rwlock();
61f723
+    slapi_rwlock_wrlock(myLock);
61f723
 
61f723
+    /* Should be fenced by the rwlock. */
61f723
     mapping_tree_inited = 1;
61f723
 
61f723
     slapi_register_supported_control(MTN_CONTROL_USE_ONE_BACKEND_OID,
61f723
@@ -1740,10 +1745,8 @@ mapping_tree_init()
61f723
     slapi_register_supported_control(MTN_CONTROL_USE_ONE_BACKEND_EXT_OID,
61f723
                      SLAPI_OPERATION_SEARCH);
61f723
 
61f723
-    myLock = slapi_new_rwlock();
61f723
-
61f723
-    be= slapi_be_select_by_instance_name(DSE_BACKEND);
61f723
-    mapping_tree_root= add_internal_mapping_tree_node("", be, NULL);
61f723
+    be = slapi_be_select_by_instance_name(DSE_BACKEND);
61f723
+    mapping_tree_root = add_internal_mapping_tree_node("", be, NULL);
61f723
 
61f723
     /* We also need to add the config and schema backends to the mapping tree.
61f723
      * They are special in that users will not know about it's node in the 
61f723
@@ -1757,17 +1760,23 @@ mapping_tree_init()
61f723
     node= add_internal_mapping_tree_node("cn=schema", be, mapping_tree_root);
61f723
     mapping_tree_node_add_child(mapping_tree_root, node);
61f723
 
61f723
-    /* 
61f723
+    slapi_rwlock_unlock(myLock);
61f723
+
61f723
+    /*
61f723
      * Now we need to look under cn=mapping tree, cn=config to find the rest
61f723
      * of the mapping tree entries.
61f723
      * Builds the mapping tree from entries in the DIT.  This function just
61f723
      * calls mapping_tree_node_get_children with the special case for the
61f723
      * root node.
61f723
      */
61f723
-    if (mapping_tree_node_get_children(mapping_tree_root, 1))
61f723
+
61f723
+    if (mapping_tree_node_get_children(mapping_tree_root, 1)) {
61f723
         return -1;
61f723
+    }
61f723
 
61f723
+    slapi_rwlock_wrlock(myLock);
61f723
     mtn_create_extension(mapping_tree_root);
61f723
+    slapi_rwlock_unlock(myLock);
61f723
 
61f723
     /* setup the dse callback functions for the ldbm instance config entry */
61f723
     {
61f723
@@ -1840,8 +1849,8 @@ mapping_tree_free ()
61f723
      */ 
61f723
     slapi_unregister_backend_state_change_all();
61f723
     /* recursively free tree nodes */
61f723
-    mtn_free_node (&mapping_tree_root);
61f723
-    mapping_tree_freed = 1;
61f723
+    mtn_free_node(&mapping_tree_root);
61f723
+    __atomic_store_4(&mapping_tree_freed, 1, __ATOMIC_RELAXED);
61f723
 }
61f723
 
61f723
 /* This function returns the first node to parse when a search is done 
61f723
@@ -2083,14 +2092,12 @@ int slapi_dn_write_needs_referral(Slapi_DN *target_sdn, Slapi_Entry **referral)
61f723
     mapping_tree_node *target_node = NULL;
61f723
     int ret = 0;
61f723
 
61f723
-    if(mapping_tree_freed){
61f723
+    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
61f723
         /* shutdown detected */
61f723
         goto done;
61f723
     }
61f723
 
61f723
-    if(!mapping_tree_inited) {
61f723
-        mapping_tree_init();
61f723
-    }
61f723
+    PR_ASSERT(mapping_tree_inited == 1);
61f723
 
61f723
     if (target_sdn) {
61f723
         mtn_lock();
61f723
@@ -2157,8 +2164,8 @@ int slapi_mapping_tree_select(Slapi_PBlock *pb, Slapi_Backend **be, Slapi_Entry
61f723
     int fixup = 0;
61f723
     
61f723
 
61f723
-    if(mapping_tree_freed){
61f723
-        /* shutdown detected */ 
61f723
+    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
61f723
+        /* shutdown detected */
61f723
         return LDAP_OPERATIONS_ERROR;
61f723
     }
61f723
 
61f723
@@ -2175,9 +2182,7 @@ int slapi_mapping_tree_select(Slapi_PBlock *pb, Slapi_Backend **be, Slapi_Entry
61f723
     target_sdn = operation_get_target_spec (op);
61f723
     fixup = operation_is_flag_set(op, OP_FLAG_TOMBSTONE_FIXUP);
61f723
 
61f723
-    if(!mapping_tree_inited) {
61f723
-        mapping_tree_init();
61f723
-    } 
61f723
+    PR_ASSERT(mapping_tree_inited == 1);
61f723
 
61f723
     be[0] = NULL;
61f723
     if (referral) {
61f723
@@ -2188,8 +2193,9 @@ int slapi_mapping_tree_select(Slapi_PBlock *pb, Slapi_Backend **be, Slapi_Entry
61f723
 
61f723
     /* Get the mapping tree node that is the best match for the target dn. */
61f723
     target_node = slapi_get_mapping_tree_node_by_dn(target_sdn);
61f723
-    if (target_node == NULL)
61f723
+    if (target_node == NULL) {
61f723
         target_node = mapping_tree_root;
61f723
+    }
61f723
 
61f723
     /* The processing of the base scope root DSE search and all other LDAP operations on "" 
61f723
      *  will be transferred to the internal DSE backend 
61f723
@@ -2266,8 +2272,8 @@ int slapi_mapping_tree_select_all(Slapi_PBlock *pb, Slapi_Backend **be_list,
61f723
     Slapi_DN *sdn = NULL;
61f723
     int flag_partial_result = 0;
61f723
     int op_type;
61f723
-    
61f723
-    if(mapping_tree_freed){
61f723
+
61f723
+    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
61f723
         return LDAP_OPERATIONS_ERROR;
61f723
     }
61f723
 
61f723
@@ -2287,9 +2293,7 @@ int slapi_mapping_tree_select_all(Slapi_PBlock *pb, Slapi_Backend **be_list,
61f723
     slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &op_type);
61f723
     slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &scope);
61f723
 
61f723
-    if(!mapping_tree_inited){
61f723
-        mapping_tree_init();
61f723
-    } 
61f723
+    PR_ASSERT(mapping_tree_inited == 1);
61f723
 
61f723
     mtn_lock();
61f723
 
61f723
@@ -2448,8 +2452,8 @@ int slapi_mapping_tree_select_and_check(Slapi_PBlock *pb,char *newdn, Slapi_Back
61f723
     Slapi_Operation *op;
61f723
     int ret;
61f723
     int need_unlock = 0;
61f723
-    
61f723
-    if(mapping_tree_freed){
61f723
+
61f723
+    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
61f723
         return LDAP_OPERATIONS_ERROR;
61f723
      }
61f723
 
61f723
@@ -2635,7 +2639,7 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
61f723
     int flag_stop = 0;
61f723
     struct slapi_componentid *cid = NULL;
61f723
 
61f723
-    if(mapping_tree_freed){
61f723
+    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
61f723
         /* shut down detected */
61f723
         return LDAP_OPERATIONS_ERROR; 
61f723
     }
61f723
@@ -2719,21 +2723,22 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
61f723
                     } else {
61f723
                         /* This MTN has not been linked to its backend
61f723
                          * instance yet. */
61f723
-                        target_node->mtn_be[*index] =
61f723
-                            slapi_be_select_by_instance_name(
61f723
-                                target_node->mtn_backend_names[*index]);
61f723
-                        *be = target_node->mtn_be[*index];
61f723
-                        if(*be==NULL) {
61f723
-                            slapi_log_err(SLAPI_LOG_BACKLDBM, "mtn_get_be",
61f723
-                                "Warning: Mapping tree node entry for %s "
61f723
-                                "point to an unknown backend : %s\n",
61f723
-                                slapi_sdn_get_dn(target_node->mtn_subtree),
61f723
-                                target_node->mtn_backend_names[*index]);
61f723
-                            /* Well there's still not backend instance for
61f723
-                             * this MTN, so let's have the default backend
61f723
-                             * deal with this.
61f723
-                             */
61f723
-                            *be = defbackend_get_backend();
61f723
+                        /* WARNING: internal memory dse backends don't provide NAMES */
61f723
+                        if (target_node->mtn_backend_names != NULL) {
61f723
+                            target_node->mtn_be[*index] = slapi_be_select_by_instance_name(target_node->mtn_backend_names[*index]);
61f723
+                            *be = target_node->mtn_be[*index];
61f723
+                            if (*be == NULL) {
61f723
+                                slapi_log_err(SLAPI_LOG_BACKLDBM, "mtn_get_be",
61f723
+                                              "Warning: Mapping tree node entry for %s "
61f723
+                                              "point to an unknown backend : %s\n",
61f723
+                                              slapi_sdn_get_dn(target_node->mtn_subtree),
61f723
+                                              target_node->mtn_backend_names[*index]);
61f723
+                                /* Well there's still not backend instance for
61f723
+                                 * this MTN, so let's have the default backend
61f723
+                                 * deal with this.
61f723
+                                 */
61f723
+                                *be = defbackend_get_backend();
61f723
+                            }
61f723
                         }
61f723
                     }
61f723
                 }
61f723
@@ -2745,10 +2750,11 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
61f723
             result = LDAP_OPERATIONS_ERROR;
61f723
                     *be = defbackend_get_backend();
61f723
                 }
61f723
-                if (flag_stop)
61f723
+                if (flag_stop) {
61f723
                     *index = SLAPI_BE_NO_BACKEND;
61f723
-                else
61f723
+                } else {
61f723
                     (*index)++;
61f723
+                }
61f723
             }
61f723
         }        
61f723
     } else {
61f723
@@ -2822,7 +2828,7 @@ static mapping_tree_node *best_matching_child(mapping_tree_node *parent,
61f723
     mapping_tree_node *highest_match_node = NULL;
61f723
     mapping_tree_node *current;
61f723
 
61f723
-    if(mapping_tree_freed){
61f723
+    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
61f723
         /* shutdown detected */
61f723
         return NULL;
61f723
     }
61f723
@@ -2849,7 +2855,7 @@ mtn_get_mapping_tree_node_by_entry(mapping_tree_node* node, const Slapi_DN *dn)
61f723
 {
61f723
     mapping_tree_node *found_node = NULL;
61f723
 
61f723
-    if(mapping_tree_freed){
61f723
+    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
61f723
         /* shutdown detected */
61f723
         return NULL;
61f723
     }
61f723
@@ -2895,7 +2901,7 @@ slapi_get_mapping_tree_node_by_dn(const Slapi_DN *dn)
61f723
     mapping_tree_node *current_best_match = mapping_tree_root;
61f723
     mapping_tree_node *next_best_match = mapping_tree_root;
61f723
 
61f723
-    if(mapping_tree_freed){
61f723
+    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
61f723
         /* shutdown detected */
61f723
         return NULL;
61f723
     }
61f723
@@ -2929,7 +2935,7 @@ get_mapping_tree_node_by_name(mapping_tree_node * node, char * be_name)
61f723
     int i;
61f723
     mapping_tree_node *found_node = NULL;
61f723
 
61f723
-    if(mapping_tree_freed){
61f723
+    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
61f723
         /* shutdown detected */
61f723
         return NULL;
61f723
     }
61f723
@@ -2980,7 +2986,7 @@ slapi_get_mapping_tree_node_configdn (const Slapi_DN *root)
61f723
 {
61f723
     char *dn = NULL;
61f723
 
61f723
-    if(mapping_tree_freed){
61f723
+    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
61f723
         /* shutdown detected */
61f723
         return NULL;
61f723
     }
61f723
@@ -3007,7 +3013,7 @@ slapi_get_mapping_tree_node_configsdn (const Slapi_DN *root)
61f723
     char *dn = NULL;
61f723
     Slapi_DN *sdn = NULL;
61f723
 
61f723
-    if(mapping_tree_freed){
61f723
+    if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
61f723
         /* shutdown detected */
61f723
         return NULL;
61f723
     }
61f723
diff --git a/ldap/servers/slapd/pw_verify.c b/ldap/servers/slapd/pw_verify.c
61f723
index cb182ed..1f0c18a 100644
61f723
--- a/ldap/servers/slapd/pw_verify.c
61f723
+++ b/ldap/servers/slapd/pw_verify.c
61f723
@@ -58,12 +58,14 @@ pw_verify_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
61f723
     int rc = SLAPI_BIND_SUCCESS;
61f723
     Slapi_Backend *be = NULL;
61f723
 
61f723
-    if (slapi_mapping_tree_select(pb, &be, referral, NULL, 0) != LDAP_SUCCESS) {
61f723
+    int mt_result = slapi_mapping_tree_select(pb, &be, referral, NULL, 0);
61f723
+    if (mt_result != LDAP_SUCCESS) {
61f723
         return SLAPI_BIND_NO_BACKEND;
61f723
     }
61f723
 
61f723
     if (*referral) {
61f723
-        slapi_be_Unlock(be);
61f723
+        /* If we have a referral, this is NULL */
61f723
+        PR_ASSERT(be == NULL);
61f723
         return SLAPI_BIND_REFERRAL;
61f723
     }
61f723
 
61f723
@@ -128,7 +130,7 @@ pw_validate_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
61f723
     }
61f723
 
61f723
     if (*referral) {
61f723
-        slapi_be_Unlock(be);
61f723
+        PR_ASSERT(be == NULL);
61f723
         return SLAPI_BIND_REFERRAL;
61f723
     }
61f723
 
61f723
-- 
61f723
2.9.4
61f723