diff --git a/SOURCES/0001-Issue-5870-ns-slapd-crashes-at-startup-if-a-backend-.patch b/SOURCES/0001-Issue-5870-ns-slapd-crashes-at-startup-if-a-backend-.patch new file mode 100644 index 0000000..bef5e99 --- /dev/null +++ b/SOURCES/0001-Issue-5870-ns-slapd-crashes-at-startup-if-a-backend-.patch @@ -0,0 +1,84 @@ +From c98a1f0d4ad35778204440a8a5fc497d476621a9 Mon Sep 17 00:00:00 2001 +From: tbordaz +Date: Wed, 2 Aug 2023 14:44:42 +0200 +Subject: [PATCH] Issue 5870 - ns-slapd crashes at startup if a backend has no + suffix (#5871) + +Bug description: + With $5598, the server checks at startup if it exists + some referrals entries in the various backends/suffixes. + If a backend has no defined suffix (not clear how it + occurs except crafting dse.ldif) the checking + triggers a sigsev + +Fix description: + Check it exists a suffix before using it +--- + .../tests/suites/ds_logs/ds_logs_test.py | 29 +++++++++++++++++++ + ldap/servers/slapd/backend.c | 3 +- + 2 files changed, 31 insertions(+), 1 deletion(-) + +diff --git a/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py b/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py +index 1a51ca548..812936c62 100644 +--- a/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py ++++ b/dirsrvtests/tests/suites/ds_logs/ds_logs_test.py +@@ -11,6 +11,8 @@ import os + import time + import logging + import pytest ++import shutil ++from lib389.rootdse import RootDSE + import subprocess + from lib389.referral import Referrals, Referral + from lib389.backend import Backend +@@ -1398,6 +1400,33 @@ def test_referral_subsuffix(topology_st, request): + + request.addfinalizer(fin) + ++def test_missing_backend_suffix(topology_st, request): ++ """Test that the server does not crash if a backend has no suffix ++ ++ :id: 427c9780-4875-4a94-a3e4-afa11be7d1a9 ++ :setup: Standalone instance ++ :steps: ++ 1. Stop the instance ++ 2. remove 'nsslapd-suffix' from the backend (userRoot) ++ 3. start the instance ++ 4. Check it started successfully with SRCH on rootDSE ++ :expectedresults: ++ all steps succeeds ++ """ ++ topology_st.standalone.stop() ++ dse_ldif = topology_st.standalone.confdir + '/dse.ldif' ++ shutil.copy(dse_ldif, dse_ldif + '.correct') ++ os.system('sed -e "/nsslapd-suffix/d" %s > %s' % (dse_ldif + '.correct', dse_ldif)) ++ topology_st.standalone.start() ++ rdse = RootDSE(topology_st.standalone) ++ ++ def fin(): ++ log.info('Restore dse.ldif') ++ topology_st.standalone.stop() ++ shutil.copy(dse_ldif + '.correct', dse_ldif) ++ ++ request.addfinalizer(fin) ++ + if __name__ == '__main__': + # Run isolated + # -s for DEBUG mode +diff --git a/ldap/servers/slapd/backend.c b/ldap/servers/slapd/backend.c +index ea8ccb88d..498f683b1 100644 +--- a/ldap/servers/slapd/backend.c ++++ b/ldap/servers/slapd/backend.c +@@ -222,7 +222,8 @@ slapi_exist_referral(Slapi_Backend *be) + suffix = slapi_sdn_get_dn(slapi_be_getsuffix(be, 0)); + + /* ignore special backends */ +- if ((strcmp(suffix, "cn=schema") == 0) || ++ if ((suffix == NULL) || ++ (strcmp(suffix, "cn=schema") == 0) || + (strcmp(suffix, "cn=config") == 0)) { + return 0; /* it does not mean anything having a referral in those backends */ + } +-- +2.41.0 + diff --git a/SOURCES/0001-Issue-5984-Crash-when-paged-result-search-are-abando.patch b/SOURCES/0001-Issue-5984-Crash-when-paged-result-search-are-abando.patch new file mode 100644 index 0000000..f5737eb --- /dev/null +++ b/SOURCES/0001-Issue-5984-Crash-when-paged-result-search-are-abando.patch @@ -0,0 +1,389 @@ +From 1fefae50842b6bcdd631b59d91688388e90e0a5c Mon Sep 17 00:00:00 2001 +From: progier389 +Date: Fri, 17 Nov 2023 14:41:51 +0100 +Subject: [PATCH 1/2] Issue 5984 - Crash when paged result search are abandoned + (#5985) + +* Issue 5984 - Crash when paged result search are abandoned + +Problem: + Fix #4551 has changed the lock that protects the paged result data + within a connection. But the abandon operation attempts to free + the paged search result with the connection lock. + This leads to race condition and double free causing an heap + corruption and a SIGSEGV. + + Solution: + - Get a copy of the operation data that needs to be logged. + - Unlock the connection mutex (to avoid deadlock risk) + - Free the paged result while holding the paged result lock. + +Issue: 5984 + +Reviewed by: @tbordaz (Thanks!) + +(cherry picked from commit 06bd0862956672eb76276cab5c1dd906fe5a7eec) +--- + .../paged_results/paged_results_test.py | 110 ++++++++++++++++-- + ldap/servers/slapd/abandon.c | 23 ++-- + ldap/servers/slapd/opshared.c | 4 +- + ldap/servers/slapd/pagedresults.c | 8 +- + ldap/servers/slapd/proto-slap.h | 2 +- + src/lib389/lib389/__init__.py | 27 ++++- + 6 files changed, 152 insertions(+), 22 deletions(-) + +diff --git a/dirsrvtests/tests/suites/paged_results/paged_results_test.py b/dirsrvtests/tests/suites/paged_results/paged_results_test.py +index 893d28a07..2fc418d3f 100644 +--- a/dirsrvtests/tests/suites/paged_results/paged_results_test.py ++++ b/dirsrvtests/tests/suites/paged_results/paged_results_test.py +@@ -7,7 +7,7 @@ + # --- END COPYRIGHT BLOCK --- + # + import socket +-from random import sample ++from random import sample, randrange + + import pytest + from ldap.controls import SimplePagedResultsControl, GetEffectiveRightsControl +@@ -17,8 +21,10 @@ from lib389.topologies import topology_st + from lib389._constants import DN_LDBM, DN_DM, DEFAULT_SUFFIX, BACKEND_NAME, PASSWORD + + from lib389._controls import SSSRequestControl +- +-from lib389.idm.user import UserAccounts ++from lib389.idm.user import UserAccount, UserAccounts ++from lib389.cli_base import FakeArgs ++from lib389.config import LDBMConfig ++from lib389.dbgen import dbgen_users + from lib389.idm.organization import Organization + from lib389.idm.organizationalunit import OrganizationalUnit + from lib389.backend import Backends +@@ -46,11 +52,56 @@ NEW_BACKEND_1 = 'parent_base' + NEW_BACKEND_2 = 'child_base' + + OLD_HOSTNAME = socket.gethostname() +-socket.sethostname('localhost') ++if os.getuid() == 0: ++ socket.sethostname('localhost') + HOSTNAME = socket.gethostname() + IP_ADDRESS = socket.gethostbyname(HOSTNAME) + OLD_IP_ADDRESS = socket.gethostbyname(OLD_HOSTNAME) + ++ ++@pytest.fixture(scope="module") ++def create_40k_users(topology_st, request): ++ inst = topology_st.standalone ++ ++ # Prepare return value ++ retval = FakeArgs() ++ retval.inst = inst ++ retval.bename = '40k' ++ retval.suffix = f'o={retval.bename}' ++ retval.ldif_file = f'{inst.get_ldif_dir()}/{retval.bename}.ldif' ++ ++ # Create new backend ++ bes = Backends(inst) ++ be_1 = bes.create(properties={ ++ 'cn': retval.bename, ++ 'nsslapd-suffix': retval.suffix, ++ }) ++ ++ # Set paged search lookthrough limit ++ ldbmconfig = LDBMConfig(inst) ++ ldbmconfig.replace('nsslapd-pagedlookthroughlimit', b'100000') ++ ++ # Create ldif and import it. ++ dbgen_users(inst, 40000, retval.ldif_file, retval.suffix) ++ # tasks = Tasks(inst) ++ # args = {TASK_WAIT: True} ++ # tasks.importLDIF(retval.suffix, None, retval.ldif_file, args) ++ inst.stop() ++ assert inst.ldif2db(retval.bename, None, None, None, retval.ldif_file, None) ++ inst.start() ++ ++ # And set an aci allowing anonymous read ++ log.info('Adding ACI to allow our test user to search') ++ ACI_TARGET = '(targetattr != "userPassword || aci")' ++ ACI_ALLOW = '(version 3.0; acl "Enable anonymous access";allow (read, search, compare)' ++ ACI_SUBJECT = '(userdn = "ldap:///anyone");)' ++ ACI_BODY = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT ++ o_1 = Organization(inst, retval.suffix) ++ o_1.set('aci', ACI_BODY) ++ ++ return retval ++ ++ + @pytest.fixture(scope="module") + def create_user(topology_st, request): + """User for binding operation""" +@@ -75,8 +126,10 @@ def create_user(topology_st, request): + + def fin(): + log.info('Deleting user simplepaged_test') +- user.delete() +- socket.sethostname(OLD_HOSTNAME) ++ if not DEBUGGING: ++ user.delete() ++ if os.getuid() == 0: ++ socket.sethostname(OLD_HOSTNAME) + + request.addfinalizer(fin) + +@@ -179,7 +232,7 @@ def change_conf_attr(topology_st, suffix, attr_name, attr_value): + return attr_value_bck + + +-def paged_search(conn, suffix, controls, search_flt, searchreq_attrlist): ++def paged_search(conn, suffix, controls, search_flt, searchreq_attrlist, abandon_rate=0): + """Search at the DEFAULT_SUFFIX with ldap.SCOPE_SUBTREE + using Simple Paged Control(should the first item in the + list controls. +@@ -199,9 +252,16 @@ def paged_search(conn, suffix, controls, search_flt, searchreq_attrlist): + req_pr_ctrl.size, + str(controls))) + msgid = conn.search_ext(suffix, ldap.SCOPE_SUBTREE, search_flt, searchreq_attrlist, serverctrls=controls) ++ log.info('Getting page %d' % (pages,)) + while True: +- log.info('Getting page %d' % (pages,)) +- rtype, rdata, rmsgid, rctrls = conn.result3(msgid) ++ try: ++ rtype, rdata, rmsgid, rctrls = conn.result3(msgid, timeout=0.001) ++ except ldap.TIMEOUT: ++ if pages > 0 and abandon_rate>0 and randrange(100)c_mutex)); + for (o = pb_conn->c_ops; o != NULL; o = o->o_next) { +- if (o->o_msgid == id && o != pb_op) ++ if (o->o_msgid == id && o != pb_op) { ++ slapi_operation_time_elapsed(o, &o_copy.hr_time_end); ++ o_copy.nentries = o->o_results.r.r_search.nentries; ++ o_copy.opid = o->o_opid; + break; ++ } + } + + if (o != NULL) { +@@ -130,7 +140,8 @@ do_abandon(Slapi_PBlock *pb) + slapi_log_err(SLAPI_LOG_TRACE, "do_abandon", "op not found\n"); + } + +- if (0 == pagedresults_free_one_msgid_nolock(pb_conn, id)) { ++ pthread_mutex_unlock(&(pb_conn->c_mutex)); ++ if (0 == pagedresults_free_one_msgid(pb_conn, id, pageresult_lock_get_addr(pb_conn))) { + slapi_log_access(LDAP_DEBUG_STATS, "conn=%" PRIu64 + " op=%d ABANDON targetop=Simple Paged Results msgid=%d\n", + pb_conn->c_connid, pb_op->o_opid, id); +@@ -143,15 +154,11 @@ do_abandon(Slapi_PBlock *pb) + " targetop=SUPPRESSED-BY-PLUGIN msgid=%d\n", + pb_conn->c_connid, pb_op->o_opid, id); + } else { +- struct timespec o_hr_time_end; +- slapi_operation_time_elapsed(o, &o_hr_time_end); + slapi_log_access(LDAP_DEBUG_STATS, "conn=%" PRIu64 " op=%d ABANDON" + " targetop=%d msgid=%d nentries=%d etime=%" PRId64 ".%010" PRId64 "\n", +- pb_conn->c_connid, pb_op->o_opid, o->o_opid, id, +- o->o_results.r.r_search.nentries, (int64_t)o_hr_time_end.tv_sec, (int64_t)o_hr_time_end.tv_nsec); ++ pb_conn->c_connid, pb_op->o_opid, o_copy.opid, id, ++ o_copy.nentries, (int64_t)o_copy.hr_time_end.tv_sec, (int64_t)o_copy.hr_time_end.tv_nsec); + } +- +- pthread_mutex_unlock(&(pb_conn->c_mutex)); + /* + * Wake up the persistent searches, so they + * can notice if they've been abandoned. +diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c +index 897b9566e..7ab4117cd 100644 +--- a/ldap/servers/slapd/opshared.c ++++ b/ldap/servers/slapd/opshared.c +@@ -922,9 +922,7 @@ op_shared_search(Slapi_PBlock *pb, int send_result) + next_be = NULL; /* to break the loop */ + if (operation->o_status & SLAPI_OP_STATUS_ABANDONED) { + /* It turned out this search was abandoned. */ +- pthread_mutex_lock(pagedresults_mutex); +- pagedresults_free_one_msgid_nolock(pb_conn, operation->o_msgid); +- pthread_mutex_unlock(pagedresults_mutex); ++ pagedresults_free_one_msgid(pb_conn, operation->o_msgid, pagedresults_mutex); + /* paged-results-request was abandoned; making an empty cookie. */ + pagedresults_set_response_control(pb, 0, estimate, -1, pr_idx); + send_ldap_result(pb, 0, NULL, "Simple Paged Results Search abandoned", 0, NULL); +diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c +index 01fe3370f..db87e486e 100644 +--- a/ldap/servers/slapd/pagedresults.c ++++ b/ldap/servers/slapd/pagedresults.c +@@ -34,6 +34,10 @@ pageresult_lock_cleanup() + slapi_ch_free((void**)&lock_hash); + } + ++/* Beware to the lock order with c_mutex: ++ * c_mutex is sometime locked while holding pageresult_lock ++ * ==> Do not lock pageresult_lock when holing c_mutex ++ */ + pthread_mutex_t * + pageresult_lock_get_addr(Connection *conn) + { +@@ -350,7 +354,7 @@ pagedresults_free_one(Connection *conn, Operation *op, int index) + * Used for abandoning - pageresult_lock_get_addr(conn) is already locked in do_abandone. + */ + int +-pagedresults_free_one_msgid_nolock(Connection *conn, ber_int_t msgid) ++pagedresults_free_one_msgid(Connection *conn, ber_int_t msgid, pthread_mutex_t *mutex) + { + int rc = -1; + int i; +@@ -361,6 +365,7 @@ pagedresults_free_one_msgid_nolock(Connection *conn, ber_int_t msgid) + } else { + slapi_log_err(SLAPI_LOG_TRACE, + "pagedresults_free_one_msgid_nolock", "=> msgid=%d\n", msgid); ++ pthread_mutex_lock(mutex); + for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) { + if (conn->c_pagedresults.prl_list[i].pr_msgid == msgid) { + PagedResults *prp = conn->c_pagedresults.prl_list + i; +@@ -375,6 +380,7 @@ pagedresults_free_one_msgid_nolock(Connection *conn, ber_int_t msgid) + break; + } + } ++ pthread_mutex_unlock(mutex); + slapi_log_err(SLAPI_LOG_TRACE, + "pagedresults_free_one_msgid_nolock", "<= %d\n", rc); + } +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index bb1f8aea2..76b2e3af2 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -1587,7 +1587,7 @@ int pagedresults_is_timedout_nolock(Connection *conn); + int pagedresults_reset_timedout_nolock(Connection *conn); + int pagedresults_in_use_nolock(Connection *conn); + int pagedresults_free_one(Connection *conn, Operation *op, int index); +-int pagedresults_free_one_msgid_nolock(Connection *conn, ber_int_t msgid); ++int pagedresults_free_one_msgid(Connection *conn, ber_int_t msgid, pthread_mutex_t *mutex); + int op_is_pagedresults(Operation *op); + int pagedresults_cleanup_all(Connection *conn, int needlock); + void op_set_pagedresults(Operation *op); +diff --git a/src/lib389/lib389/__init__.py b/src/lib389/lib389/__init__.py +index b8ca7685f..81e41c58b 100644 +--- a/src/lib389/lib389/__init__.py ++++ b/src/lib389/lib389/__init__.py +@@ -1040,6 +1040,24 @@ class DirSrv(SimpleLDAPObject, object): + + self.state = DIRSRV_STATE_OFFLINE + ++ def dump_errorlog(self): ++ ''' ++ Its logs all errors messages within the error log that occured ++ after the last startup. ++ ''' ++ if os.path.isfile(self.errlog): ++ lines = [] ++ with open(self.errlog, 'r') as file: ++ for line in file: ++ if "starting up" in line: ++ lines = [] ++ for key in ( 'DEBUG', 'INFO', 'NOTICE', 'WARN' ): ++ if key in line: ++ lines.append(line) ++ break ++ for line in lines: ++ self.log.error(line) ++ + def start(self, timeout=120, post_open=True): + ''' + It starts an instance and rebind it. Its final state after rebind +@@ -1063,7 +1081,13 @@ class DirSrv(SimpleLDAPObject, object): + if self.with_systemd(): + self.log.debug("systemd status -> True") + # Do systemd things here ... +- subprocess.check_output(["systemctl", "start", "dirsrv@%s" % self.serverid], stderr=subprocess.STDOUT) ++ try: ++ subprocess.check_output(["systemctl", "start", "dirsrv@%s" % self.serverid], stderr=subprocess.STDOUT) ++ except subprocess.CalledProcessError as e: ++ self.dump_errorlog() ++ self.log.error('Failed to start dirsrv@%s: "%s"' % (self.serverid, e.output.decode())) ++ self.log.error(e) ++ raise ValueError('Failed to start DS') + else: + self.log.debug("systemd status -> False") + # Start the process. +@@ -1087,6 +1111,7 @@ class DirSrv(SimpleLDAPObject, object): + self.log.debug("DEBUG: starting with %s" % cmd) + output = subprocess.check_output(*cmd, env=env, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: ++ self.dump_errorlog() + self.log.error('Failed to start ns-slapd: "%s"' % e.output.decode()) + self.log.error(e) + raise ValueError('Failed to start DS') +-- +2.41.0 + diff --git a/SOURCES/0002-Issue-5984-Crash-when-paged-result-search-are-abando.patch b/SOURCES/0002-Issue-5984-Crash-when-paged-result-search-are-abando.patch new file mode 100644 index 0000000..7cbb6d3 --- /dev/null +++ b/SOURCES/0002-Issue-5984-Crash-when-paged-result-search-are-abando.patch @@ -0,0 +1,89 @@ +From df7dd8320424f7ab616c9ad8086a6874ff8bf859 Mon Sep 17 00:00:00 2001 +From: progier389 +Date: Tue, 21 Nov 2023 11:57:44 +0100 +Subject: [PATCH 2/2] Issue 5984 - Crash when paged result search are abandoned + - fix2 (#5987) + +Chasing several rabbits at the same time is a bad idea ! +and I mixed branches and unwillingly pushed one commit for #5980 in #5984 +just before the PR #5985 merge ! -:( +Hopefully it does not break anything but just logs some useless crap if instance fails to starts. +Anyway This commit reverts the change about __init.py +and also do a minor code cleanup (removed a trailing space) in abandon.c + +Issue #5984 + +Reviewed by: @tbordaz Thanks ! +--- + ldap/servers/slapd/abandon.c | 2 +- + src/lib389/lib389/__init__.py | 27 +-------------------------- + 2 files changed, 2 insertions(+), 27 deletions(-) + +diff --git a/ldap/servers/slapd/abandon.c b/ldap/servers/slapd/abandon.c +index 964d28836..2dd1ee320 100644 +--- a/ldap/servers/slapd/abandon.c ++++ b/ldap/servers/slapd/abandon.c +@@ -43,7 +43,7 @@ do_abandon(Slapi_PBlock *pb) + struct timespec hr_time_end; + int nentries; + int opid; +- } o_copy; ++ } o_copy; + + slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op); + slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn); +diff --git a/src/lib389/lib389/__init__.py b/src/lib389/lib389/__init__.py +index 6a941dbe7..7590ec442 100644 +--- a/src/lib389/lib389/__init__.py ++++ b/src/lib389/lib389/__init__.py +@@ -1048,24 +1048,6 @@ class DirSrv(SimpleLDAPObject, object): + + self.state = DIRSRV_STATE_OFFLINE + +- def dump_errorlog(self): +- ''' +- Its logs all errors messages within the error log that occured +- after the last startup. +- ''' +- if os.path.isfile(self.errlog): +- lines = [] +- with open(self.errlog, 'r') as file: +- for line in file: +- if "starting up" in line: +- lines = [] +- for key in ( 'DEBUG', 'INFO', 'NOTICE', 'WARN' ): +- if key in line: +- lines.append(line) +- break +- for line in lines: +- self.log.error(line) +- + def start(self, timeout=120, post_open=True): + ''' + It starts an instance and rebind it. Its final state after rebind +@@ -1089,13 +1071,7 @@ class DirSrv(SimpleLDAPObject, object): + if self.with_systemd(): + self.log.debug("systemd status -> True") + # Do systemd things here ... +- try: +- subprocess.check_output(["systemctl", "start", "dirsrv@%s" % self.serverid], stderr=subprocess.STDOUT) +- except subprocess.CalledProcessError as e: +- self.dump_errorlog() +- self.log.error('Failed to start dirsrv@%s: "%s"' % (self.serverid, e.output.decode())) +- self.log.error(e) +- raise ValueError('Failed to start DS') ++ subprocess.check_output(["systemctl", "start", "dirsrv@%s" % self.serverid], stderr=subprocess.STDOUT) + else: + self.log.debug("systemd status -> False") + # Start the process. +@@ -1119,7 +1095,6 @@ class DirSrv(SimpleLDAPObject, object): + self.log.debug("DEBUG: starting with %s" % cmd) + output = subprocess.check_output(*cmd, env=env, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: +- self.dump_errorlog() + self.log.error('Failed to start ns-slapd: "%s"' % e.output.decode()) + self.log.error(e) + raise ValueError('Failed to start DS') +-- +2.41.0 + diff --git a/SPECS/389-ds-base.spec b/SPECS/389-ds-base.spec index 9219395..26b2b0b 100644 --- a/SPECS/389-ds-base.spec +++ b/SPECS/389-ds-base.spec @@ -48,7 +48,7 @@ ExcludeArch: i686 Summary: 389 Directory Server (base) Name: 389-ds-base Version: 1.4.3.37 -Release: %{?relprefix}1%{?prerel}%{?dist} +Release: %{?relprefix}2%{?prerel}%{?dist} License: GPLv3+ and (ASL 2.0 or MIT) URL: https://www.port389.org Group: System Environment/Daemons @@ -296,6 +296,10 @@ Source4: vendor-%{version}-1.tar.gz Source5: Cargo-%{version}-1.lock %endif +Patch01: 0001-Issue-5870-ns-slapd-crashes-at-startup-if-a-backend-.patch +Patch02: 0001-Issue-5984-Crash-when-paged-result-search-are-abando.patch +Patch03: 0002-Issue-5984-Crash-when-paged-result-search-are-abando.patch + %description 389 Directory Server is an LDAPv3 compliant server. The base package includes the LDAP server and command line utilities for server administration. @@ -916,11 +920,16 @@ exit 0 %doc README.md %changelog -* Fri Dec 08 2023 MSVSphere Packaging Team - 1.4.3.37-1 +* Fri Dec 08 2023 MSVSphere Packaging Team - 1.4.3.37-2 - Rebuilt for MSVSphere 8.8 +* Sun Dec 03 2023 James Chapman - 1.4.3.37-2 +- Bump version to 1.4.3.37-2 +- Resolves: RHEL-12710 bdb_start - Detected Disorderly Shutdown directory server is not starting +- Resolves: RHEL-16822 ns-slapd crash in slapi_attr_basetype + * Wed Aug 16 2023 Mark Reynolds - 1.4.3.37-1 -- Bump versionto 1.4.3.37-1 +- Bump version to 1.4.3.37-1 - Resolves: rhbz#2224505 - Paged search impacts performance - Resolves: rhbz#2220890 - healthcheck tool needs to be updates for new default password storage scheme - Resolves: rhbz#2218235 - python3-lib389: Python tarfile extraction needs change to avoid a warning