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

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