diff --git a/SOURCES/0024-Ticket-50905-intermittent-SSL-hang-with-rhds.patch b/SOURCES/0024-Ticket-50905-intermittent-SSL-hang-with-rhds.patch new file mode 100644 index 0000000..3af4844 --- /dev/null +++ b/SOURCES/0024-Ticket-50905-intermittent-SSL-hang-with-rhds.patch @@ -0,0 +1,60 @@ +From 14e3bea927c33a97ca8aed937b6edd9ce4557d24 Mon Sep 17 00:00:00 2001 +From: Thierry Bordaz +Date: Fri, 3 Apr 2020 15:23:10 +0200 +Subject: [PATCH] Ticket 50905 - intermittent SSL hang with rhds + +Bug Description: + On a successfull sasl bind, a new IO layer (sasl_io_enable) is registered on top of + the connection. Then sasl bind sends the successful result. Registration is + done while sasl bind thread holds c_mutex but result is sent while the c_mutex + is released. + + If a new operation comes in just after c_mutex was released it is + possible that sasl bind sends the result while the new IO layer is pushed. + IO layers is partially initialized at that time. It can create sigseg or + deadlock or... + +Fix Description: + The fix is to protect the send result from IO layer push. + i.e. move send_ldap_result into c_mutex + +https://pagure.io/389-ds-base/issue/50905 + +Reviewed by: Mark Reynolds (Thanks !!) + +Platforms tested: F29 + +Flag Day: no + +Doc impact: no +--- + ldap/servers/slapd/saslbind.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/ldap/servers/slapd/saslbind.c b/ldap/servers/slapd/saslbind.c +index 0907c623f..ef29acf71 100644 +--- a/ldap/servers/slapd/saslbind.c ++++ b/ldap/servers/slapd/saslbind.c +@@ -1118,12 +1118,16 @@ sasl_check_result: + /* Enable SASL I/O on the connection */ + PR_EnterMonitor(pb_conn->c_mutex); + connection_set_io_layer_cb(pb_conn, sasl_io_enable, NULL, NULL); ++ ++ /* send successful result before sasl_io_enable can be pushed by another incoming op */ ++ send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL); ++ + PR_ExitMonitor(pb_conn->c_mutex); ++ } else { ++ /* send successful result */ ++ send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL); + } + +- /* send successful result */ +- send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL); +- + /* remove the sasl data from the pblock */ + slapi_pblock_set(pb, SLAPI_BIND_RET_SASLCREDS, NULL); + +-- +2.25.4 + diff --git a/SOURCES/0026-Ticket-51068-deadlock-when-updating-the-schema.patch b/SOURCES/0026-Ticket-51068-deadlock-when-updating-the-schema.patch new file mode 100644 index 0000000..2f48907 --- /dev/null +++ b/SOURCES/0026-Ticket-51068-deadlock-when-updating-the-schema.patch @@ -0,0 +1,224 @@ +From 3b589a2bfc33f407cf2c23dc6896566bb8e2acdf Mon Sep 17 00:00:00 2001 +From: Thierry Bordaz +Date: Tue, 5 May 2020 17:44:01 +0200 +Subject: [PATCH] Ticket 51068 - deadlock when updating the schema + +Bug Description: + It exists a 3 threads deadlock scenario. It involves state change plugins when it + calls schema_changed_callback. So the trigger is a change of schema (direct or via + replication). The scenario is + MOD(cn=schema) hold StateChange lock wait for vattr lock + SRCH hold vattr lock wait for DB page + MOD hold DB page wait for StateChange lock + +Fix Description: + Statechange lock protects the list of registered callbacks. + lock is a mutex where actually registration of callback is only done + at startup. Later the list is only lookup. + Making statechange lock a rwlock suppresses the deadlock scenario + as MODs will only acquire in read StateChange lock. + It should also improve performance as at the moment all MODs are serialized + on that lock + In order to prevent writer starvation a new slapi_new_rwlock_prio + create rwlock with priority to writers. + +https://pagure.io/389-ds-base/issue/51068 + +Reviewed by: Mark Reynolds, William Brown + +Platforms tested: 30 + +Flag Day: no + +Doc impact: no +--- + .../servers/plugins/statechange/statechange.c | 24 ++++++++++-------- + ldap/servers/slapd/slapi-plugin.h | 16 ++++++++++++ + ldap/servers/slapd/slapi2nspr.c | 25 +++++++++++++++++++ + ldap/servers/slapd/vattr.c | 2 +- + 4 files changed, 55 insertions(+), 12 deletions(-) + +diff --git a/ldap/servers/plugins/statechange/statechange.c b/ldap/servers/plugins/statechange/statechange.c +index f89b394c6..0a3838b5e 100644 +--- a/ldap/servers/plugins/statechange/statechange.c ++++ b/ldap/servers/plugins/statechange/statechange.c +@@ -40,7 +40,7 @@ static SCNotify *head; /* a place to start in the list */ + #define SCN_PLUGIN_SUBSYSTEM "statechange-plugin" /* used for logging */ + + static void *api[5]; +-static Slapi_Mutex *buffer_lock = 0; ++static Slapi_RWLock *buffer_lock = 0; + static PRUint64 g_plugin_started = 0; + + /* +@@ -140,7 +140,7 @@ statechange_start(Slapi_PBlock *pb __attribute__((unused))) + api[3] = (void *)_statechange_unregister_all; + api[4] = (void *)_statechange_vattr_cache_invalidator_callback; + +- if (0 == (buffer_lock = slapi_new_mutex())) /* we never free this mutex */ ++ if (0 == (buffer_lock = slapi_new_rwlock())) + { + /* badness */ + slapi_log_err(SLAPI_LOG_ERR, SCN_PLUGIN_SUBSYSTEM, "statechange_start - Failed to create lock\n"); +@@ -180,7 +180,9 @@ statechange_close(Slapi_PBlock *pb __attribute__((unused))) + slapi_counter_destroy(&op_counter); + + slapi_apib_unregister(StateChange_v1_0_GUID); +- slapi_destroy_mutex(buffer_lock); ++ if (buffer_lock) { ++ slapi_destroy_rwlock(buffer_lock); ++ } + buffer_lock = NULL; + + slapi_log_err(SLAPI_LOG_TRACE, SCN_PLUGIN_SUBSYSTEM, "<-- statechange_close\n"); +@@ -240,7 +242,7 @@ statechange_post_op(Slapi_PBlock *pb, int modtype) + slapi_log_err(SLAPI_LOG_TRACE, SCN_PLUGIN_SUBSYSTEM, "--> statechange_post_op\n"); + + /* evaluate this operation against the notification entries */ +- slapi_lock_mutex(buffer_lock); ++ slapi_rwlock_rdlock(buffer_lock); + if (head) { + slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn); + if (NULL == sdn) { +@@ -290,7 +292,7 @@ statechange_post_op(Slapi_PBlock *pb, int modtype) + } while (notify && notify != head); + } + bail: +- slapi_unlock_mutex(buffer_lock); ++ slapi_rwlock_unlock(buffer_lock); + slapi_log_err(SLAPI_LOG_TRACE, SCN_PLUGIN_SUBSYSTEM, "<-- statechange_post_op\n"); + + return SLAPI_PLUGIN_SUCCESS; /* always succeed */ +@@ -338,7 +340,7 @@ _statechange_register(char *caller_id, char *dn, char *filter, void *caller_data + } + item->func = func; + +- slapi_lock_mutex(buffer_lock); ++ slapi_rwlock_wrlock(buffer_lock); + if (head == NULL) { + head = item; + head->next = head; +@@ -349,7 +351,7 @@ _statechange_register(char *caller_id, char *dn, char *filter, void *caller_data + head->prev = item; + item->prev->next = item; + } +- slapi_unlock_mutex(buffer_lock); ++ slapi_rwlock_unlock(buffer_lock); + slapi_ch_free_string(&writable_filter); + + ret = SLAPI_PLUGIN_SUCCESS; +@@ -371,7 +373,7 @@ _statechange_unregister(char *dn, char *filter, notify_callback thefunc) + return ret; + } + +- slapi_lock_mutex(buffer_lock); ++ slapi_rwlock_wrlock(buffer_lock); + + if ((func = statechange_find_notify(dn, filter, thefunc))) { + func->prev->next = func->next; +@@ -392,7 +394,7 @@ _statechange_unregister(char *dn, char *filter, notify_callback thefunc) + slapi_ch_free((void **)&func); + } + +- slapi_unlock_mutex(buffer_lock); ++ slapi_rwlock_unlock(buffer_lock); + slapi_counter_decrement(op_counter); + + return ret; +@@ -410,7 +412,7 @@ _statechange_unregister_all(char *caller_id, caller_data_free_callback callback) + return; + } + +- slapi_lock_mutex(buffer_lock); ++ slapi_rwlock_wrlock(buffer_lock); + + if (notify) { + do { +@@ -441,7 +443,7 @@ _statechange_unregister_all(char *caller_id, caller_data_free_callback callback) + } while (notify != start_notify && notify != NULL); + } + +- slapi_unlock_mutex(buffer_lock); ++ slapi_rwlock_unlock(buffer_lock); + slapi_counter_decrement(op_counter); + } + +diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h +index 679bdbb5c..865d83b9b 100644 +--- a/ldap/servers/slapd/slapi-plugin.h ++++ b/ldap/servers/slapd/slapi-plugin.h +@@ -6126,6 +6126,22 @@ void slapi_destroy_condvar(Slapi_CondVar *cvar); + int slapi_wait_condvar(Slapi_CondVar *cvar, struct timeval *timeout); + int slapi_notify_condvar(Slapi_CondVar *cvar, int notify_all); + ++/** ++ * Creates a new read/write lock ++ * If prio_writer the rwlock gives priority on writers ++ * else it give priority on readers (default) ++ * ++ * \return A pointer to a \c Slapi_RWLock ++ * ++ * \note Free the returned lock by calling slapi_destroy_rwlock() when finished ++ * ++ * \see slapi_destroy_rwlock() ++ * \see slapi_rwlock_rdlock() ++ * \see slapi_rwlock_wrlock() ++ * \see slapi_rwlock_unlock() ++ */ ++Slapi_RWLock *slapi_new_rwlock_prio(int32_t prio_writer); ++ + /** + * Creates a new read/write lock. + * +diff --git a/ldap/servers/slapd/slapi2nspr.c b/ldap/servers/slapd/slapi2nspr.c +index b3e6d94c2..232d1599e 100644 +--- a/ldap/servers/slapd/slapi2nspr.c ++++ b/ldap/servers/slapd/slapi2nspr.c +@@ -181,6 +181,31 @@ slapi_notify_condvar(Slapi_CondVar *cvar, int notify_all) + return (prrc == PR_SUCCESS ? 1 : 0); + } + ++Slapi_RWLock * ++slapi_new_rwlock_prio(int32_t prio_writer) ++{ ++#ifdef USE_POSIX_RWLOCKS ++ pthread_rwlock_t *rwlock = NULL; ++ pthread_rwlockattr_t attr; ++ ++ pthread_rwlockattr_init(&attr); ++ if (prio_writer) { ++ pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); ++ } else { ++ pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_READER_NP); ++ } ++ ++ rwlock = (pthread_rwlock_t *)slapi_ch_malloc(sizeof(pthread_rwlock_t)); ++ if (rwlock) { ++ pthread_rwlock_init(rwlock, &attr); ++ } ++ ++ return ((Slapi_RWLock *)rwlock); ++#else ++ return ((Slapi_RWLock *)PR_NewRWLock(PR_RWLOCK_RANK_NONE, "slapi_rwlock")); ++#endif ++} ++ + Slapi_RWLock * + slapi_new_rwlock(void) + { +diff --git a/ldap/servers/slapd/vattr.c b/ldap/servers/slapd/vattr.c +index 852a887ce..eef444270 100644 +--- a/ldap/servers/slapd/vattr.c ++++ b/ldap/servers/slapd/vattr.c +@@ -1996,7 +1996,7 @@ vattr_map_create(void) + return ENOMEM; + } + +- the_map->lock = slapi_new_rwlock(); ++ the_map->lock = slapi_new_rwlock_prio(1 /* priority on writers */); + if (NULL == the_map) { + slapd_nasty(sourcefile, 3, 0); + return ENOMEM; +-- +2.26.2 + diff --git a/SOURCES/0027-Issue-50745-ns-slapd-hangs-during-CleanAllRUV-tests.patch b/SOURCES/0027-Issue-50745-ns-slapd-hangs-during-CleanAllRUV-tests.patch new file mode 100644 index 0000000..e9ce0d3 --- /dev/null +++ b/SOURCES/0027-Issue-50745-ns-slapd-hangs-during-CleanAllRUV-tests.patch @@ -0,0 +1,70 @@ +From b69687377d6afd973a8bc27d8d34bf8069943a9d Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 19 May 2020 11:25:13 -0400 +Subject: [PATCH] Issue 50745: ns-slapd hangs during CleanAllRUV tests + +Bug Description: + The hang condition: + - is not systematic + - occurs in rare case, for example here during the deletion of a replica. + - a thread is waiting for a dblock that an other thread "forgot" to + release. + - have always existed, at least since 1.4.0 but likely since 1.2.x + + When deleting a replica, the replica is retrieved from + mapping tree structure (mtnode). + The replica is also retrieved through the mapping tree + when writing updates to the changelog. + + When deleting the replica, mapping tree structure is cleared + after the changelog is deleted (that can take some cycles). + There is a window where an update can retrieve the replica, + from the not yet cleared MT, while the changelog being removed. + + At the end, the update will update the changelog that is + currently removed and keeps an unfree lock in the DB. + +Fix description: + Ideally mapping tree should be protected by a lock but it + is not done systematically (e.g. slapi_get_mapping_tree_node). + Using a lock looks an overkill and can probably introduce + deadlock and performance hit. + The idea of the fix is to reduce the window, moving the + mapping tree clear before the changelog removal. + +https://pagure.io/389-ds-base/issue/50745 + +Reviewed by: Mark Reynolds, Ludwig Krispenz +--- + ldap/servers/plugins/replication/repl5_replica_config.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index 80a079784..95b7fa50e 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -735,18 +735,18 @@ replica_config_delete(Slapi_PBlock *pb __attribute__((unused)), + PR_ASSERT(mtnode_ext); + + if (mtnode_ext->replica) { ++ Object *repl_obj = mtnode_ext->replica; + /* remove object from the hash */ + r = (Replica *)object_get_data(mtnode_ext->replica); ++ mtnode_ext->replica = NULL; + PR_ASSERT(r); + /* The changelog for this replica is no longer valid, so we should remove it. */ + slapi_log_err(SLAPI_LOG_WARNING, repl_plugin_name, "replica_config_delete - " + "The changelog for replica %s is no longer valid since " + "the replica config is being deleted. Removing the changelog.\n", + slapi_sdn_get_dn(replica_get_root(r))); +- cl5DeleteDBSync(mtnode_ext->replica); ++ cl5DeleteDBSync(repl_obj); + replica_delete_by_name(replica_get_name(r)); +- object_release(mtnode_ext->replica); +- mtnode_ext->replica = NULL; + } + + PR_Unlock(s_configLock); +-- +2.26.2 + diff --git a/SPECS/389-ds-base.spec b/SPECS/389-ds-base.spec index d718cc4..40aa433 100644 --- a/SPECS/389-ds-base.spec +++ b/SPECS/389-ds-base.spec @@ -39,7 +39,7 @@ Summary: 389 Directory Server (%{variant}) Name: 389-ds-base Version: 1.3.10.1 -Release: %{?relprefix}9%{?prerel}%{?dist} +Release: %{?relprefix}14%{?prerel}%{?dist} License: GPLv3+ URL: https://www.port389.org/ Group: System Environment/Daemons @@ -169,6 +169,10 @@ Patch20: 0020-Ticket-50857-Memory-leak-in-ACI-using-IP-subject.patch Patch21: 0021-Ticket-50709-cont-Several-memory-leaks-reported-by-V.patch Patch22: 0022-fix-for-50542-crashes-in-filter-tests.patch Patch23: 0023-Ticket-49623-cont-cenotaph-errors-on-modrdn-operatio.patch +Patch24: 0024-Ticket-50905-intermittent-SSL-hang-with-rhds.patch +# Patch25: 0025-Issue-50940-Permissions-of-some-shipped-directories-.patch +Patch26: 0026-Ticket-51068-deadlock-when-updating-the-schema.patch +Patch27: 0027-Issue-50745-ns-slapd-hangs-during-CleanAllRUV-tests.patch %description 389 Directory Server is an LDAPv3 compliant server. The base package includes @@ -308,7 +312,7 @@ popd sed -i -e 's|#{{PERL-EXEC}}|#!/usr/bin/perl|' $RPM_BUILD_ROOT%{_datadir}/%{pkgname}/script-templates/template-*.pl # exclude 32-bit platforms from running tests -%if %{_arch} != "s390x" && %{_arch} != "s390" && %{_arch} != "i386" && %{_arch} != "ppc" +%if %{_arch} == "x86_64" %check # This checks the code, if it fails it prints why, then re-raises the fail to shortcircuit the rpm build. if ! make DESTDIR="$RPM_BUILD_ROOT" check; then cat ./test-suite.log && false; fi @@ -521,6 +525,27 @@ fi %{_sysconfdir}/%{pkgname}/dirsrvtests %changelog +* Mon Jun 15 2020 Mark Reynolds - 1.3.10.1-14 +- Bump version to 1.3.10.1-14 +- Resolves: Bug 1814603 - revert patch as it conflicts with 389-admin package + +* Thu Jun 4 2020 Mark Reynolds - 1.3.10.1-13 +- Bump version to 1.3.10.1-13 +- Resolves: Bug 1842469 - ns-slapd hangs during CleanAllRUV tests + +* Fri May 29 2020 Mark Reynolds - 1.3.10.1-12 +- Bump version to 1.3.10.1-12 +- Resolves: Bug 1814603 - 389-base-ds expected file permissions + +* Fri May 29 2020 Mark Reynolds - 1.3.10.1-11 +- Bump version to 1.3.10.1-11 +- Resolves: Bug 1839173 - ipa ns-slapd 3 threads deadlock, db pages, state_change lock, write vattr lock + +* Tue May 19 2020 Mark Reynolds - 1.3.10.1-10 +- Bump version to 1.3.10.1-10 +- Resolves: Bug 1814603 - 389-base-ds expected file permissions in package don't match final runtime permissions +- Resolves: Bug 1836171 - intermittent SSL hang with rhds + * Mon Apr 6 2020 Mark Reynolds - 1.3.10.1-9 - Bump version to 1.3.10.1-9 - Resolves: Bug 1817933 - cenotaph errors on modrdn operations