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

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