From c04070527a4abfbb683373e9e82757b0d87ca13b Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jul 29 2019 12:53:15 +0000 Subject: import 389-ds-base-1.3.8.4-25.1.el7_6 --- diff --git a/SOURCES/0024-Ticket-50396-Crash-in-PAM-plugin-when-user-does-not-.patch b/SOURCES/0024-Ticket-50396-Crash-in-PAM-plugin-when-user-does-not-.patch new file mode 100644 index 0000000..6cd2f51 --- /dev/null +++ b/SOURCES/0024-Ticket-50396-Crash-in-PAM-plugin-when-user-does-not-.patch @@ -0,0 +1,37 @@ +From 6984b34fe496d696e37f003dbf57a5ca1b5899ea Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Mon, 20 May 2019 15:06:54 -0400 +Subject: [PATCH] Ticket 50396 - Crash in PAM plugin when user does not exist + +Description: pam passthru & addn plugin causes crash in bind when + user does not exist. Need to make sure we don't + dereference NULL pointer. + +https://pagure.io/389-ds-base/issue/50396 + +Reviewed by: mreynolds & tbordaz + +(cherry picked from commit 0935b8af6c8925c7a79a0a22103142ef5f7c5960) +--- + ldap/servers/plugins/pam_passthru/pam_ptpreop.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/ldap/servers/plugins/pam_passthru/pam_ptpreop.c b/ldap/servers/plugins/pam_passthru/pam_ptpreop.c +index de9448b90..b62c3c6b6 100644 +--- a/ldap/servers/plugins/pam_passthru/pam_ptpreop.c ++++ b/ldap/servers/plugins/pam_passthru/pam_ptpreop.c +@@ -436,8 +436,9 @@ pam_passthru_bindpreop(Slapi_PBlock *pb) + * We only handle simple bind requests that include non-NULL binddn and + * credentials. Let the Directory Server itself handle everything else. + */ +- if ((method != LDAP_AUTH_SIMPLE) || (*normbinddn == '\0') || +- (creds->bv_len == 0)) { ++ if (method != LDAP_AUTH_SIMPLE || normbinddn == NULL || ++ *normbinddn == '\0' || creds->bv_len == 0) ++ { + slapi_log_err(SLAPI_LOG_PLUGIN, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, + "pam_passthru_bindpreop - Not handled (not simple bind or NULL dn/credentials)\n"); + return retcode; +-- +2.21.0 + diff --git a/SOURCES/0025-Issue-50426-nsSSL3Ciphers-is-limited-to-1024-charact.patch b/SOURCES/0025-Issue-50426-nsSSL3Ciphers-is-limited-to-1024-charact.patch new file mode 100644 index 0000000..bae0073 --- /dev/null +++ b/SOURCES/0025-Issue-50426-nsSSL3Ciphers-is-limited-to-1024-charact.patch @@ -0,0 +1,186 @@ +From bc9ae5a810b8024e7ab1179f492c425793e0ddcf Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 7 Jun 2019 09:21:31 -0400 +Subject: [PATCH] Issue 50426 - nsSSL3Ciphers is limited to 1024 characters + +Bug Description: There was a hardcoded buffer for processing TLS ciphers. + Anything over 1024 characters was truncated and was not + applied. + +Fix Description: Don't use a fixed size buffer and just use the entire + string. When printing errors about invalid format then + we must use a fixed sized buffer, but we will truncate + that log value as to not exceed the ssl logging function's + buffer, and still output a useful message. + +ASAN approved + +https://pagure.io/389-ds-base/issue/50426 + +Reviewed by: firstyear, tbordaz, and spichugi (Thanks!!!) + +(cherry picked from commit 22f2f9a1502e63bb169b7d599b5a3b35ddb31b8a) +--- + dirsrvtests/tests/suites/tls/cipher_test.py | 51 +++++++++++++++++++++ + ldap/servers/slapd/ssl.c | 34 ++++++-------- + 2 files changed, 66 insertions(+), 19 deletions(-) + create mode 100644 dirsrvtests/tests/suites/tls/cipher_test.py + +diff --git a/dirsrvtests/tests/suites/tls/cipher_test.py b/dirsrvtests/tests/suites/tls/cipher_test.py +new file mode 100644 +index 000000000..058931046 +--- /dev/null ++++ b/dirsrvtests/tests/suites/tls/cipher_test.py +@@ -0,0 +1,51 @@ ++import pytest ++import os ++from lib389.config import Encryption ++from lib389.topologies import topology_st as topo ++ ++ ++def test_long_cipher_list(topo): ++ """Test a long cipher list, and makre sure it is not truncated ++ ++ :id: bc400f54-3966-49c8-b640-abbf4fb2377d ++ :setup: Standalone Instance ++ :steps: ++ 1. Set nsSSL3Ciphers to a very long list of ciphers ++ 2. Ciphers are applied correctly ++ :expectedresults: ++ 1. Success ++ 2. Success ++ """ ++ ENABLED_CIPHER = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384::AES-GCM::AEAD::256" ++ DISABLED_CIPHER = "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256::AES-GCM::AEAD::128" ++ CIPHER_LIST = ( ++ "-all,-SSL_CK_RC4_128_WITH_MD5,-SSL_CK_RC4_128_EXPORT40_WITH_MD5,-SSL_CK_RC2_128_CBC_WITH_MD5," ++ "-SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5,-SSL_CK_DES_64_CBC_WITH_MD5,-SSL_CK_DES_192_EDE3_CBC_WITH_MD5," ++ "-TLS_RSA_WITH_RC4_128_MD5,-TLS_RSA_WITH_RC4_128_SHA,-TLS_RSA_WITH_3DES_EDE_CBC_SHA," ++ "-TLS_RSA_WITH_DES_CBC_SHA,-SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,-SSL_RSA_FIPS_WITH_DES_CBC_SHA," ++ "-TLS_RSA_EXPORT_WITH_RC4_40_MD5,-TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,-TLS_RSA_WITH_NULL_MD5," ++ "-TLS_RSA_WITH_NULL_SHA,-TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,-SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA," ++ "-SSL_FORTEZZA_DMS_WITH_RC4_128_SHA,-SSL_FORTEZZA_DMS_WITH_NULL_SHA,-TLS_DHE_DSS_WITH_DES_CBC_SHA," ++ "-TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,-TLS_DHE_RSA_WITH_DES_CBC_SHA,-TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA," ++ "+TLS_RSA_WITH_AES_128_CBC_SHA,-TLS_DHE_DSS_WITH_AES_128_CBC_SHA,-TLS_DHE_RSA_WITH_AES_128_CBC_SHA," ++ "+TLS_RSA_WITH_AES_256_CBC_SHA,-TLS_DHE_DSS_WITH_AES_256_CBC_SHA,-TLS_DHE_RSA_WITH_AES_256_CBC_SHA," ++ "-TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,-TLS_DHE_DSS_WITH_RC4_128_SHA,-TLS_ECDHE_RSA_WITH_RC4_128_SHA," ++ "-TLS_RSA_WITH_NULL_SHA,-TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,-SSL_CK_DES_192_EDE3_CBC_WITH_MD5," ++ "-TLS_RSA_WITH_RC4_128_MD5,-TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,-TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA," ++ "-TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,+TLS_AES_128_GCM_SHA256,+TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" ++ ) ++ ++ topo.standalone.enable_tls() ++ enc = Encryption(topo.standalone) ++ enc.set('nsSSL3Ciphers', CIPHER_LIST) ++ topo.standalone.restart() ++ enabled_ciphers = enc.get_attr_vals_utf8('nssslenabledciphers') ++ assert ENABLED_CIPHER in enabled_ciphers ++ assert DISABLED_CIPHER not in enabled_ciphers ++ ++ ++if __name__ == '__main__': ++ # Run isolated ++ # -s for DEBUG mode ++ CURRENT_FILE = os.path.realpath(__file__) ++ pytest.main(["-s", CURRENT_FILE]) +diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c +index b8eba2da4..ed054db44 100644 +--- a/ldap/servers/slapd/ssl.c ++++ b/ldap/servers/slapd/ssl.c +@@ -95,7 +95,6 @@ static char *configDN = "cn=encryption,cn=config"; + #define CIPHER_SET_ALLOWWEAKDHPARAM 0x200 /* allowWeakDhParam is on */ + #define CIPHER_SET_DISALLOWWEAKDHPARAM 0x400 /* allowWeakDhParam is off */ + +- + #define CIPHER_SET_ISDEFAULT(flag) \ + (((flag)&CIPHER_SET_DEFAULT) ? PR_TRUE : PR_FALSE) + #define CIPHER_SET_ISALL(flag) \ +@@ -689,10 +688,12 @@ _conf_setciphers(char *setciphers, int flags) + active = 0; + break; + default: +- PR_snprintf(err, sizeof(err), "invalid ciphers <%s>: format is " +- "+cipher1,-cipher2...", +- raw); +- return slapi_ch_strdup(err); ++ if (strlen(raw) > MAGNUS_ERROR_LEN) { ++ PR_snprintf(err, sizeof(err) - 3, "%s...", raw); ++ return slapi_ch_smprintf("invalid ciphers <%s>: format is +cipher1,-cipher2...", err); ++ } else { ++ return slapi_ch_smprintf("invalid ciphers <%s>: format is +cipher1,-cipher2...", raw); ++ } + } + if ((t = strchr(setciphers, ','))) + *t++ = '\0'; +@@ -1689,7 +1690,6 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) + PRUint16 NSSVersionMax = enabledNSSVersions.max; + char mymin[VERSION_STR_LENGTH], mymax[VERSION_STR_LENGTH]; + char newmax[VERSION_STR_LENGTH]; +- char cipher_string[1024]; + int allowweakcipher = CIPHER_SET_DEFAULTWEAKCIPHER; + int_fast16_t renegotiation = (int_fast16_t)SSL_RENEGOTIATE_REQUIRES_XTN; + +@@ -1730,21 +1730,17 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) + "Ignoring it and set it to default.", val, configDN); + } + } +- slapi_ch_free((void **)&val); ++ slapi_ch_free_string(&val); + + /* Set SSL cipher preferences */ +- *cipher_string = 0; +- if (ciphers && (*ciphers) && PL_strcmp(ciphers, "blank")) +- PL_strncpyz(cipher_string, ciphers, sizeof(cipher_string)); +- slapi_ch_free((void **)&ciphers); +- +- if (NULL != (val = _conf_setciphers(cipher_string, allowweakcipher))) { ++ if (NULL != (val = _conf_setciphers(ciphers, allowweakcipher))) { + errorCode = PR_GetError(); + slapd_SSL_warn("Failed to set SSL cipher " + "preference information: %s (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", + val, errorCode, slapd_pr_strerror(errorCode)); +- slapi_ch_free((void **)&val); ++ slapi_ch_free_string(&val); + } ++ slapi_ch_free_string(&ciphers); + freeConfigEntry(&e); + + /* Import pr fd into SSL */ +@@ -1815,12 +1811,12 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) + activation = slapi_entry_attr_get_charptr(e, "nssslactivation"); + if ((!activation) || (!PL_strcasecmp(activation, "off"))) { + /* this family was turned off, goto next */ +- slapi_ch_free((void **)&activation); ++ slapi_ch_free_string(&activation); + freeConfigEntry(&e); + continue; + } + +- slapi_ch_free((void **)&activation); ++ slapi_ch_free_string(&activation); + + token = slapi_entry_attr_get_charptr(e, "nsssltoken"); + personality = slapi_entry_attr_get_charptr(e, "nssslpersonalityssl"); +@@ -1837,8 +1833,8 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) + "family information. Missing nsssltoken or" + "nssslpersonalityssl in %s (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", + *family, errorCode, slapd_pr_strerror(errorCode)); +- slapi_ch_free((void **)&token); +- slapi_ch_free((void **)&personality); ++ slapi_ch_free_string(&token); ++ slapi_ch_free_string(&personality); + freeConfigEntry(&e); + continue; + } +@@ -1865,7 +1861,7 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) + "private key for cert %s of family %s (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", + cert_name, *family, + errorCode, slapd_pr_strerror(errorCode)); +- slapi_ch_free((void **)&personality); ++ slapi_ch_free_string(&personality); + CERT_DestroyCertificate(cert); + cert = NULL; + freeConfigEntry(&e); +-- +2.21.0 + diff --git a/SOURCES/0026-Ticket-50329-2nd-Possible-Security-Issue-DOS-due-to-.patch b/SOURCES/0026-Ticket-50329-2nd-Possible-Security-Issue-DOS-due-to-.patch new file mode 100644 index 0000000..0ad1c92 --- /dev/null +++ b/SOURCES/0026-Ticket-50329-2nd-Possible-Security-Issue-DOS-due-to-.patch @@ -0,0 +1,46 @@ +From 4383a6cb666bc79feb9ca0ee62dda0520955d286 Mon Sep 17 00:00:00 2001 +From: Thierry Bordaz +Date: Wed, 15 May 2019 17:46:14 +0200 +Subject: [PATCH] Ticket 50329 - (2nd) Possible Security Issue: DOS due to + ioblocktimeout not applying to TLS + +Bug Description: + A secure socket is configured in blocking mode. If an event + is detected on a secure socket a worker tries to receive the request. + If handshake occurs during the read, it can hang longer than + ioblocktimeout because it takes into account the socket option + rather than the timeout used for the ssl_Recv + +Fix Description: + The fix is specific to secure socket and set this socket option + to do non blocking IO. + +https://pagure.io/389-ds-base/issue/50329 + +Reviewed by: ? + +Platforms tested: F28, RHEL7.6 + +Flag Day: no + +Doc impact: no +--- + ldap/servers/slapd/daemon.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c +index c77e1f15c..b1d41c858 100644 +--- a/ldap/servers/slapd/daemon.c ++++ b/ldap/servers/slapd/daemon.c +@@ -3191,7 +3191,7 @@ configure_pr_socket(PRFileDesc **pr_socket, int secure, int local) + + if (secure) { + pr_socketoption.option = PR_SockOpt_Nonblocking; +- pr_socketoption.value.non_blocking = 0; ++ pr_socketoption.value.non_blocking = 1; + if (PR_SetSocketOption(*pr_socket, &pr_socketoption) == PR_FAILURE) { + PRErrorCode prerr = PR_GetError(); + slapi_log_err(SLAPI_LOG_ERR, +-- +2.21.0 + diff --git a/SOURCES/0027-BZ1518320-entry-cache-crash-fix.patch b/SOURCES/0027-BZ1518320-entry-cache-crash-fix.patch new file mode 100644 index 0000000..062f943 --- /dev/null +++ b/SOURCES/0027-BZ1518320-entry-cache-crash-fix.patch @@ -0,0 +1,703 @@ +From 17aada4feb87407e004a890225700e730778d692 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Thu, 20 Jun 2019 15:50:08 -0400 +Subject: [PATCH 1/2] BZ1518320 - entry cache crash fix + +Description: THis patch is combination of all the entry cache fixes. + + If these fixes are not enough, there is an experimental + "fix" that should prevent the crash. A message will be + logged that reports the crash was averted: + + "(avoided crash, but cache was corrupted)" + + The customer should monitor the errors log for this text, + and let GSS know if they see it. +--- + configure.ac | 3 - + dirsrvtests/tests/suites/betxns/betxn_test.py | 57 ++++++ + ldap/servers/slapd/back-ldbm/back-ldbm.h | 68 ++++---- + ldap/servers/slapd/back-ldbm/backentry.c | 2 +- + ldap/servers/slapd/back-ldbm/cache.c | 163 ++++++++++++++++-- + ldap/servers/slapd/back-ldbm/ldbm_add.c | 13 ++ + ldap/servers/slapd/back-ldbm/ldbm_delete.c | 12 ++ + ldap/servers/slapd/back-ldbm/ldbm_modify.c | 12 ++ + ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 22 ++- + .../servers/slapd/back-ldbm/proto-back-ldbm.h | 1 + + ldap/servers/slapd/slapi-plugin.h | 15 ++ + ldap/servers/slapd/time.c | 26 +++ + 12 files changed, 341 insertions(+), 53 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 91d6d398b..ea528ff2b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -72,9 +72,6 @@ AC_FUNC_STRFTIME + AC_FUNC_VPRINTF + AC_CHECK_FUNCS([endpwent ftruncate getcwd gethostbyname inet_ntoa localtime_r memmove memset mkdir munmap putenv rmdir setrlimit socket strcasecmp strchr strcspn strdup strerror strncasecmp strpbrk strrchr strstr strtol tzset]) + +-# These functions are *required* without option. +-AC_CHECK_FUNCS([clock_gettime], [], AC_MSG_ERROR([unable to locate required symbol clock_gettime])) +- + # This will detect if we need to add the LIBADD_DL value for us. + LT_LIB_DLLOAD + +diff --git a/dirsrvtests/tests/suites/betxns/betxn_test.py b/dirsrvtests/tests/suites/betxns/betxn_test.py +index 175496495..48181a9ea 100644 +--- a/dirsrvtests/tests/suites/betxns/betxn_test.py ++++ b/dirsrvtests/tests/suites/betxns/betxn_test.py +@@ -8,6 +8,7 @@ + # + import pytest + import six ++import ldap + from lib389.tasks import * + from lib389.utils import * + from lib389.topologies import topology_st +@@ -248,6 +249,62 @@ def test_betxn_memberof(topology_st, dynamic_plugins): + log.info('test_betxn_memberof: PASSED') + + ++def test_betxn_modrdn_memberof(topology_st): ++ """Test modrdn operartions and memberOf ++ ++ :id: 70d0b96e-b693-4bf7-bbf5-102a66ac5994 ++ ++ :setup: Standalone instance ++ ++ :steps: 1. Enable and configure memberOf plugin ++ 2. Set memberofgroupattr="member" and memberofAutoAddOC="nsContainer" ++ 3. Create group and user outside of memberOf plugin scope ++ 4. Do modrdn to move group into scope ++ 5. Do modrdn to move group into scope (again) ++ ++ :expectedresults: ++ 1. memberOf plugin plugin should be ON ++ 2. Set memberofgroupattr="member" and memberofAutoAddOC="nsContainer" should PASS ++ 3. Creating group and user should PASS ++ 4. Modrdn should fail with objectclass violation ++ 5. Second modrdn should also fail with objectclass violation ++ """ ++ ++ peoplebase = 'ou=people,%s' % DEFAULT_SUFFIX ++ memberof = MemberOfPlugin(topology_st.standalone) ++ memberof.enable() ++ memberof.set_autoaddoc('nsContainer') # Bad OC ++ memberof.set('memberOfEntryScope', peoplebase) ++ memberof.set('memberOfAllBackends', 'on') ++ topology_st.standalone.restart() ++ ++ groups = Groups(topology_st.standalone, DEFAULT_SUFFIX) ++ group = groups.create(properties={ ++ 'cn': 'group', ++ }) ++ ++ # Create user and add it to group ++ users = UserAccounts(topology_st.standalone, basedn=DEFAULT_SUFFIX) ++ user = users.create(properties=TEST_USER_PROPERTIES) ++ if not ds_is_older('1.3.7'): ++ user.remove('objectClass', 'nsMemberOf') ++ ++ group.add_member(user.dn) ++ ++ # Attempt modrdn that should fail, but the original entry should stay in the cache ++ with pytest.raises(ldap.OBJECTCLASS_VIOLATION): ++ group.rename('cn=group_to_people', newsuperior=peoplebase) ++ ++ # Should fail, but not with NO_SUCH_OBJECT as the original entry should still be in the cache ++ with pytest.raises(ldap.OBJECTCLASS_VIOLATION): ++ group.rename('cn=group_to_people', newsuperior=peoplebase) ++ ++ # ++ # Done ++ # ++ log.info('test_betxn_modrdn_memberof: PASSED') ++ ++ + if __name__ == '__main__': + # Run isolated + # -s for DEBUG mode +diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h +index 4727961a9..399508561 100644 +--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h ++++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h +@@ -310,36 +310,37 @@ typedef struct + #define CACHE_TYPE_ENTRY 0 + #define CACHE_TYPE_DN 1 + +-struct backcommon +-{ +- int ep_type; /* to distinguish backdn from backentry */ +- struct backcommon *ep_lrunext; /* for the cache */ +- struct backcommon *ep_lruprev; /* for the cache */ +- ID ep_id; /* entry id */ +- char ep_state; /* state in the cache */ +-#define ENTRY_STATE_DELETED 0x1 /* entry is marked as deleted */ +-#define ENTRY_STATE_CREATING 0x2 /* entry is being created; don't touch it */ +-#define ENTRY_STATE_NOTINCACHE 0x4 /* cache_add failed; not in the cache */ +- int ep_refcnt; /* entry reference cnt */ +- size_t ep_size; /* for cache tracking */ ++struct backcommon { ++ int ep_type; /* to distinguish backdn from backentry */ ++ struct backcommon *ep_lrunext; /* for the cache */ ++ struct backcommon *ep_lruprev; /* for the cache */ ++ ID ep_id; /* entry id */ ++ char ep_state; /* state in the cache */ ++#define ENTRY_STATE_DELETED 0x1 /* entry is marked as deleted */ ++#define ENTRY_STATE_CREATING 0x2 /* entry is being created; don't touch it */ ++#define ENTRY_STATE_NOTINCACHE 0x4 /* cache_add failed; not in the cache */ ++#define ENTRY_STATE_INVALID 0x8 /* cache entry is invalid and needs to be removed */ ++ int ep_refcnt; /* entry reference cnt */ ++ size_t ep_size; /* for cache tracking */ ++ struct timespec ep_create_time; /* the time the entry was added to the cache */ + }; + + /* From ep_type through ep_size MUST be identical to backcommon */ +-struct backentry +-{ +- int ep_type; /* to distinguish backdn from backentry */ +- struct backcommon *ep_lrunext; /* for the cache */ +- struct backcommon *ep_lruprev; /* for the cache */ +- ID ep_id; /* entry id */ +- char ep_state; /* state in the cache */ +- int ep_refcnt; /* entry reference cnt */ +- size_t ep_size; /* for cache tracking */ +- Slapi_Entry *ep_entry; /* real entry */ +- Slapi_Entry *ep_vlventry; +- void *ep_dn_link; /* linkage for the 3 hash */ +- void *ep_id_link; /* tables used for */ +- void *ep_uuid_link; /* looking up entries */ +- PRMonitor *ep_mutexp; /* protection for mods; make it reentrant */ ++struct backentry { ++ int ep_type; /* to distinguish backdn from backentry */ ++ struct backcommon *ep_lrunext; /* for the cache */ ++ struct backcommon *ep_lruprev; /* for the cache */ ++ ID ep_id; /* entry id */ ++ char ep_state; /* state in the cache */ ++ int ep_refcnt; /* entry reference cnt */ ++ size_t ep_size; /* for cache tracking */ ++ struct timespec ep_create_time; /* the time the entry was added to the cache */ ++ Slapi_Entry *ep_entry; /* real entry */ ++ Slapi_Entry *ep_vlventry; ++ void * ep_dn_link; /* linkage for the 3 hash */ ++ void * ep_id_link; /* tables used for */ ++ void * ep_uuid_link; /* looking up entries */ ++ PRMonitor *ep_mutexp; /* protection for mods; make it reentrant */ + }; + + /* From ep_type through ep_size MUST be identical to backcommon */ +@@ -348,12 +349,13 @@ struct backdn + int ep_type; /* to distinguish backdn from backentry */ + struct backcommon *ep_lrunext; /* for the cache */ + struct backcommon *ep_lruprev; /* for the cache */ +- ID ep_id; /* entry id */ +- char ep_state; /* state in the cache; share ENTRY_STATE_* */ +- int ep_refcnt; /* entry reference cnt */ +- size_t ep_size; /* for cache tracking */ +- Slapi_DN *dn_sdn; +- void *dn_id_link; /* for hash table */ ++ ID ep_id; /* entry id */ ++ char ep_state; /* state in the cache; share ENTRY_STATE_* */ ++ int ep_refcnt; /* entry reference cnt */ ++ size_t ep_size; /* for cache tracking */ ++ struct timespec ep_create_time; /* the time the entry was added to the cache */ ++ Slapi_DN *dn_sdn; ++ void *dn_id_link; /* for hash table */ + }; + + /* for the in-core cache of entries */ +diff --git a/ldap/servers/slapd/back-ldbm/backentry.c b/ldap/servers/slapd/back-ldbm/backentry.c +index f2fe780db..a1f3ca1bb 100644 +--- a/ldap/servers/slapd/back-ldbm/backentry.c ++++ b/ldap/servers/slapd/back-ldbm/backentry.c +@@ -23,7 +23,7 @@ backentry_free(struct backentry **bep) + return; + } + ep = *bep; +- PR_ASSERT(ep->ep_state & (ENTRY_STATE_DELETED | ENTRY_STATE_NOTINCACHE)); ++ PR_ASSERT(ep->ep_state & (ENTRY_STATE_DELETED | ENTRY_STATE_NOTINCACHE | ENTRY_STATE_INVALID)); + if (ep->ep_entry != NULL) { + slapi_entry_free(ep->ep_entry); + } +diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c +index 86e1f7b39..054766df2 100644 +--- a/ldap/servers/slapd/back-ldbm/cache.c ++++ b/ldap/servers/slapd/back-ldbm/cache.c +@@ -56,6 +56,11 @@ + #define LOG(...) + #endif + ++typedef enum { ++ ENTRY_CACHE, ++ DN_CACHE, ++} CacheType; ++ + #define LRU_DETACH(cache, e) lru_detach((cache), (void *)(e)) + + #define CACHE_LRU_HEAD(cache, type) ((type)((cache)->c_lruhead)) +@@ -185,6 +190,7 @@ new_hash(u_long size, u_long offset, HashFn hfn, HashTestFn tfn) + int + add_hash(Hashtable *ht, void *key, uint32_t keylen, void *entry, void **alt) + { ++ struct backcommon *back_entry = (struct backcommon *)entry; + u_long val, slot; + void *e; + +@@ -202,6 +208,7 @@ add_hash(Hashtable *ht, void *key, uint32_t keylen, void *entry, void **alt) + e = HASH_NEXT(ht, e); + } + /* ok, it's not already there, so add it */ ++ back_entry->ep_create_time = slapi_current_rel_time_hr(); + HASH_NEXT(ht, entry) = ht->slot[slot]; + ht->slot[slot] = entry; + return 1; +@@ -492,6 +499,126 @@ cache_make_hashes(struct cache *cache, int type) + } + } + ++/* ++ * Helper function for flush_hash() to calculate if the entry should be ++ * removed from the cache. ++ */ ++static int32_t ++flush_remove_entry(struct timespec *entry_time, struct timespec *start_time) ++{ ++ struct timespec diff; ++ ++ slapi_timespec_diff(entry_time, start_time, &diff); ++ if (diff.tv_sec >= 0) { ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ ++/* ++ * Flush all the cache entries that were added after the "start time" ++ * This is called when a backend transaction plugin fails, and we need ++ * to remove all the possible invalid entries in the cache. ++ * ++ * If the ref count is 0, we can straight up remove it from the cache, but ++ * if the ref count is greater than 1, then the entry is currently in use. ++ * In the later case we set the entry state to ENTRY_STATE_INVALID, and ++ * when the owning thread cache_returns() the cache entry is automatically ++ * removed so another thread can not use/lock the invalid cache entry. ++ */ ++static void ++flush_hash(struct cache *cache, struct timespec *start_time, int32_t type) ++{ ++ Hashtable *ht = cache->c_idtable; /* start with the ID table as it's in both ENTRY and DN caches */ ++ void *e, *laste = NULL; ++ ++ cache_lock(cache); ++ ++ for (size_t i = 0; i < ht->size; i++) { ++ e = ht->slot[i]; ++ while (e) { ++ struct backcommon *entry = (struct backcommon *)e; ++ uint64_t remove_it = 0; ++ if (flush_remove_entry(&entry->ep_create_time, start_time)) { ++ /* Mark the entry to be removed */ ++ slapi_log_err(SLAPI_LOG_CACHE, "flush_hash", "[%s] Removing entry id (%d)\n", ++ type ? "DN CACHE" : "ENTRY CACHE", entry->ep_id); ++ remove_it = 1; ++ } ++ laste = e; ++ e = HASH_NEXT(ht, e); ++ ++ if (remove_it) { ++ /* since we have the cache lock we know we can trust refcnt */ ++ entry->ep_state |= ENTRY_STATE_INVALID; ++ if (entry->ep_refcnt == 0) { ++ entry->ep_refcnt++; ++ lru_delete(cache, laste); ++ if (type == ENTRY_CACHE) { ++ entrycache_remove_int(cache, laste); ++ entrycache_return(cache, (struct backentry **)&laste); ++ } else { ++ dncache_remove_int(cache, laste); ++ dncache_return(cache, (struct backdn **)&laste); ++ } ++ } else { ++ /* Entry flagged for removal */ ++ slapi_log_err(SLAPI_LOG_CACHE, "flush_hash", ++ "[%s] Flagging entry to be removed later: id (%d) refcnt: %d\n", ++ type ? "DN CACHE" : "ENTRY CACHE", entry->ep_id, entry->ep_refcnt); ++ } ++ } ++ } ++ } ++ ++ if (type == ENTRY_CACHE) { ++ /* Also check the DN hashtable */ ++ ht = cache->c_dntable; ++ ++ for (size_t i = 0; i < ht->size; i++) { ++ e = ht->slot[i]; ++ while (e) { ++ struct backcommon *entry = (struct backcommon *)e; ++ uint64_t remove_it = 0; ++ if (flush_remove_entry(&entry->ep_create_time, start_time)) { ++ /* Mark the entry to be removed */ ++ slapi_log_err(SLAPI_LOG_CACHE, "flush_hash", "[ENTRY CACHE] Removing entry id (%d)\n", ++ entry->ep_id); ++ remove_it = 1; ++ } ++ laste = e; ++ e = HASH_NEXT(ht, e); ++ ++ if (remove_it) { ++ /* since we have the cache lock we know we can trust refcnt */ ++ entry->ep_state |= ENTRY_STATE_INVALID; ++ if (entry->ep_refcnt == 0) { ++ entry->ep_refcnt++; ++ lru_delete(cache, laste); ++ entrycache_remove_int(cache, laste); ++ entrycache_return(cache, (struct backentry **)&laste); ++ } else { ++ /* Entry flagged for removal */ ++ slapi_log_err(SLAPI_LOG_CACHE, "flush_hash", ++ "[ENTRY CACHE] Flagging entry to be removed later: id (%d) refcnt: %d\n", ++ entry->ep_id, entry->ep_refcnt); ++ } ++ } ++ } ++ } ++ } ++ ++ cache_unlock(cache); ++} ++ ++void ++revert_cache(ldbm_instance *inst, struct timespec *start_time) ++{ ++ flush_hash(&inst->inst_cache, start_time, ENTRY_CACHE); ++ flush_hash(&inst->inst_dncache, start_time, DN_CACHE); ++} ++ + /* initialize the cache */ + int + cache_init(struct cache *cache, uint64_t maxsize, long maxentries, int type) +@@ -1141,10 +1268,10 @@ entrycache_return(struct cache *cache, struct backentry **bep) + backentry_free(bep); + } else { + ASSERT(e->ep_refcnt > 0); +- if (!--e->ep_refcnt) { +- if (e->ep_state & ENTRY_STATE_DELETED) { +- const char *ndn = slapi_sdn_get_ndn(backentry_get_sdn(e)); +- if (ndn) { ++ if (! --e->ep_refcnt) { ++ if (e->ep_state & (ENTRY_STATE_DELETED | ENTRY_STATE_INVALID)) { ++ const char* ndn = slapi_sdn_get_ndn(backentry_get_sdn(e)); ++ if (ndn){ + /* + * State is "deleted" and there are no more references, + * so we need to remove the entry from the DN cache because +@@ -1154,6 +1281,13 @@ entrycache_return(struct cache *cache, struct backentry **bep) + LOG("entrycache_return -Failed to remove %s from dn table\n", ndn); + } + } ++ if (e->ep_state & ENTRY_STATE_INVALID) { ++ /* Remove it from the hash table before we free the back entry */ ++ slapi_log_err(SLAPI_LOG_CACHE, "entrycache_return", ++ "Finally flushing invalid entry: %d (%s)\n", ++ e->ep_id, backentry_get_ndn(e)); ++ entrycache_remove_int(cache, e); ++ } + backentry_free(bep); + } else { + lru_add(cache, e); +@@ -1535,11 +1669,11 @@ cache_lock_entry(struct cache *cache, struct backentry *e) + + /* make sure entry hasn't been deleted now */ + cache_lock(cache); +- if (e->ep_state & (ENTRY_STATE_DELETED | ENTRY_STATE_NOTINCACHE)) { +- cache_unlock(cache); +- PR_ExitMonitor(e->ep_mutexp); +- LOG("<= cache_lock_entry (DELETED)\n"); +- return RETRY_CACHE_LOCK; ++ if (e->ep_state & (ENTRY_STATE_DELETED | ENTRY_STATE_NOTINCACHE | ENTRY_STATE_INVALID)) { ++ cache_unlock(cache); ++ PR_ExitMonitor(e->ep_mutexp); ++ LOG("<= cache_lock_entry (DELETED)\n"); ++ return RETRY_CACHE_LOCK; + } + cache_unlock(cache); + +@@ -1695,8 +1829,15 @@ dncache_return(struct cache *cache, struct backdn **bdn) + backdn_free(bdn); + } else { + ASSERT((*bdn)->ep_refcnt > 0); +- if (!--(*bdn)->ep_refcnt) { +- if ((*bdn)->ep_state & ENTRY_STATE_DELETED) { ++ if (! --(*bdn)->ep_refcnt) { ++ if ((*bdn)->ep_state & (ENTRY_STATE_DELETED | ENTRY_STATE_INVALID)) { ++ if ((*bdn)->ep_state & ENTRY_STATE_INVALID) { ++ /* Remove it from the hash table before we free the back dn */ ++ slapi_log_err(SLAPI_LOG_CACHE, "dncache_return", ++ "Finally flushing invalid entry: %d (%s)\n", ++ (*bdn)->ep_id, slapi_sdn_get_dn((*bdn)->dn_sdn)); ++ dncache_remove_int(cache, (*bdn)); ++ } + backdn_free(bdn); + } else { + lru_add(cache, (void *)*bdn); +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c +index 32c8e71ff..d3c8cdab2 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c +@@ -97,6 +97,8 @@ ldbm_back_add(Slapi_PBlock *pb) + PRUint64 conn_id; + int op_id; + int result_sent = 0; ++ int32_t parent_op = 0; ++ struct timespec parent_time; + + if (slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id) < 0) { + conn_id = 0; /* connection is NULL */ +@@ -147,6 +149,13 @@ ldbm_back_add(Slapi_PBlock *pb) + slapi_entry_delete_values(e, numsubordinates, NULL); + + dblayer_txn_init(li, &txn); ++ ++ if (txn.back_txn_txn == NULL) { ++ /* This is the parent operation, get the time */ ++ parent_op = 1; ++ parent_time = slapi_current_rel_time_hr(); ++ } ++ + /* the calls to perform searches require the parent txn if any + so set txn to the parent_txn until we begin the child transaction */ + if (parent_txn) { +@@ -1239,6 +1248,10 @@ ldbm_back_add(Slapi_PBlock *pb) + goto common_return; + + error_return: ++ if (parent_op) { ++ revert_cache(inst, &parent_time); ++ } ++ + if (addingentry_id_assigned) { + next_id_return(be, addingentry->ep_id); + } +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c +index f5f6c1e3a..80c53a3e0 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c +@@ -79,6 +79,8 @@ ldbm_back_delete(Slapi_PBlock *pb) + ID tomb_ep_id = 0; + int result_sent = 0; + Connection *pb_conn; ++ int32_t parent_op = 0; ++ struct timespec parent_time; + + if (slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id) < 0) { + conn_id = 0; /* connection is NULL */ +@@ -98,6 +100,13 @@ ldbm_back_delete(Slapi_PBlock *pb) + + /* dblayer_txn_init needs to be called before "goto error_return" */ + dblayer_txn_init(li, &txn); ++ ++ if (txn.back_txn_txn == NULL) { ++ /* This is the parent operation, get the time */ ++ parent_op = 1; ++ parent_time = slapi_current_rel_time_hr(); ++ } ++ + /* the calls to perform searches require the parent txn if any + so set txn to the parent_txn until we begin the child transaction */ + if (parent_txn) { +@@ -1356,6 +1365,9 @@ commit_return: + goto common_return; + + error_return: ++ if (parent_op) { ++ revert_cache(inst, &parent_time); ++ } + if (tombstone) { + if (cache_is_in_cache(&inst->inst_cache, tombstone)) { + tomb_ep_id = tombstone->ep_id; /* Otherwise, tombstone might have been freed. */ +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c +index cc4319e5f..93ab0a9e8 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c +@@ -412,6 +412,8 @@ ldbm_back_modify(Slapi_PBlock *pb) + int fixup_tombstone = 0; + int ec_locked = 0; + int result_sent = 0; ++ int32_t parent_op = 0; ++ struct timespec parent_time; + + slapi_pblock_get(pb, SLAPI_BACKEND, &be); + slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &li); +@@ -424,6 +426,13 @@ ldbm_back_modify(Slapi_PBlock *pb) + fixup_tombstone = operation_is_flag_set(operation, OP_FLAG_TOMBSTONE_FIXUP); + + dblayer_txn_init(li, &txn); /* must do this before first goto error_return */ ++ ++ if (txn.back_txn_txn == NULL) { ++ /* This is the parent operation, get the time */ ++ parent_op = 1; ++ parent_time = slapi_current_rel_time_hr(); ++ } ++ + /* the calls to perform searches require the parent txn if any + so set txn to the parent_txn until we begin the child transaction */ + if (parent_txn) { +@@ -887,6 +896,9 @@ ldbm_back_modify(Slapi_PBlock *pb) + goto common_return; + + error_return: ++ if (parent_op) { ++ revert_cache(inst, &parent_time); ++ } + if (postentry != NULL) { + slapi_entry_free(postentry); + postentry = NULL; +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +index e2e9d1b46..1ca1bdb28 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +@@ -97,6 +97,8 @@ ldbm_back_modrdn(Slapi_PBlock *pb) + int op_id; + int result_sent = 0; + Connection *pb_conn = NULL; ++ int32_t parent_op = 0; ++ struct timespec parent_time; + + if (slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id) < 0) { + conn_id = 0; /* connection is NULL */ +@@ -134,6 +136,13 @@ ldbm_back_modrdn(Slapi_PBlock *pb) + + /* dblayer_txn_init needs to be called before "goto error_return" */ + dblayer_txn_init(li, &txn); ++ ++ if (txn.back_txn_txn == NULL) { ++ /* This is the parent operation, get the time */ ++ parent_op = 1; ++ parent_time = slapi_current_rel_time_hr(); ++ } ++ + /* the calls to perform searches require the parent txn if any + so set txn to the parent_txn until we begin the child transaction */ + if (parent_txn) { +@@ -1276,6 +1285,10 @@ ldbm_back_modrdn(Slapi_PBlock *pb) + goto common_return; + + error_return: ++ /* Revert the caches if this is the parent operation */ ++ if (parent_op) { ++ revert_cache(inst, &parent_time); ++ } + /* result already sent above - just free stuff */ + if (postentry) { + slapi_entry_free(postentry); +@@ -1353,6 +1366,10 @@ error_return: + slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval); + } + slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message); ++ /* Revert the caches if this is the parent operation */ ++ if (parent_op) { ++ revert_cache(inst, &parent_time); ++ } + } + retval = plugin_call_mmr_plugin_postop(pb, NULL,SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN); + +@@ -1413,12 +1430,7 @@ common_return: + CACHE_RETURN(&inst->inst_dncache, &bdn); + } + +- /* remove the new entry from the cache if the op failed - +- otherwise, leave it in */ + if (ec && inst) { +- if (retval && cache_is_in_cache(&inst->inst_cache, ec)) { +- CACHE_REMOVE(&inst->inst_cache, ec); +- } + CACHE_RETURN(&inst->inst_cache, &ec); + } + ec = NULL; +diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h +index 61c3313c5..510d38f57 100644 +--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h ++++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h +@@ -55,6 +55,7 @@ void cache_unlock_entry(struct cache *cache, struct backentry *e); + int cache_replace(struct cache *cache, void *oldptr, void *newptr); + int cache_has_otherref(struct cache *cache, void *bep); + int cache_is_in_cache(struct cache *cache, void *ptr); ++void revert_cache(ldbm_instance *inst, struct timespec *start_time); + + #ifdef CACHE_DEBUG + void check_entry_cache(struct cache *cache, struct backentry *e); +diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h +index bdad4e59e..eefe88724 100644 +--- a/ldap/servers/slapd/slapi-plugin.h ++++ b/ldap/servers/slapd/slapi-plugin.h +@@ -6853,6 +6853,12 @@ void slapi_operation_time_expiry(Slapi_Operation *o, time_t timeout, struct time + */ + slapi_timer_result slapi_timespec_expire_check(struct timespec *expire); + ++/** ++ * Returns the current system time as a hr clock ++ * ++ * \return timespec of the current monotonic time. ++ */ ++struct timespec slapi_current_rel_time_hr(void); + + /* + * Plugin and parameter block related macros (remainder of this file). +@@ -8296,6 +8302,15 @@ uint64_t slapi_atomic_decr_64(uint64_t *ptr, int memorder); + + /* helper function */ + const char * fetch_attr(Slapi_Entry *e, const char *attrname, char *default_val); ++/** ++ * Diffs two timespects a - b into *diff. This is useful with ++ * clock_monotonic to find time taken to perform operations. ++ * ++ * \param struct timespec a the "end" time. ++ * \param struct timespec b the "start" time. ++ * \param struct timespec c the difference. ++ */ ++void slapi_timespec_diff(struct timespec *a, struct timespec *b, struct timespec *diff); + + #ifdef __cplusplus + } +diff --git a/ldap/servers/slapd/time.c b/ldap/servers/slapd/time.c +index 584bd1e63..2a3865858 100644 +--- a/ldap/servers/slapd/time.c ++++ b/ldap/servers/slapd/time.c +@@ -96,6 +96,32 @@ slapi_current_utc_time_hr(void) + return ltnow; + } + ++struct timespec ++slapi_current_rel_time_hr(void) ++{ ++ struct timespec now; ++ clock_gettime(CLOCK_MONOTONIC, &now); ++ return now; ++} ++ ++void ++slapi_timespec_diff(struct timespec *a, struct timespec *b, struct timespec *diff) ++{ ++ /* Now diff the two */ ++ time_t sec = a->tv_sec - b->tv_sec; ++ int32_t nsec = a->tv_nsec - b->tv_nsec; ++ ++ if (nsec < 0) { ++ /* It's negative so take one second */ ++ sec -= 1; ++ /* And set nsec to to a whole value */ ++ nsec = 1000000000 - nsec; ++ } ++ ++ diff->tv_sec = sec; ++ diff->tv_nsec = nsec; ++} ++ + time_t + slapi_current_utc_time(void) + { +-- +2.21.0 + diff --git a/SOURCES/0028-BZ1518320-entry-cache-crash-fix.patch b/SOURCES/0028-BZ1518320-entry-cache-crash-fix.patch new file mode 100644 index 0000000..f780d25 --- /dev/null +++ b/SOURCES/0028-BZ1518320-entry-cache-crash-fix.patch @@ -0,0 +1,50 @@ +From 12672d5bad1b1bbb71a281d33533b1829ab65fbc Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 21 Jun 2019 10:15:19 -0400 +Subject: [PATCH 2/2] BZ1518320 - entry cache crash fix + +Description: Fix cherry-pick error +--- + ldap/servers/slapd/time.c | 26 -------------------------- + 1 file changed, 26 deletions(-) + +diff --git a/ldap/servers/slapd/time.c b/ldap/servers/slapd/time.c +index 2a3865858..584bd1e63 100644 +--- a/ldap/servers/slapd/time.c ++++ b/ldap/servers/slapd/time.c +@@ -96,32 +96,6 @@ slapi_current_utc_time_hr(void) + return ltnow; + } + +-struct timespec +-slapi_current_rel_time_hr(void) +-{ +- struct timespec now; +- clock_gettime(CLOCK_MONOTONIC, &now); +- return now; +-} +- +-void +-slapi_timespec_diff(struct timespec *a, struct timespec *b, struct timespec *diff) +-{ +- /* Now diff the two */ +- time_t sec = a->tv_sec - b->tv_sec; +- int32_t nsec = a->tv_nsec - b->tv_nsec; +- +- if (nsec < 0) { +- /* It's negative so take one second */ +- sec -= 1; +- /* And set nsec to to a whole value */ +- nsec = 1000000000 - nsec; +- } +- +- diff->tv_sec = sec; +- diff->tv_nsec = nsec; +-} +- + time_t + slapi_current_utc_time(void) + { +-- +2.21.0 + diff --git a/SOURCES/0029-BZ1518320-entry-cache-crash-fix-cherry-pick-error.patch b/SOURCES/0029-BZ1518320-entry-cache-crash-fix-cherry-pick-error.patch new file mode 100644 index 0000000..7ce05a4 --- /dev/null +++ b/SOURCES/0029-BZ1518320-entry-cache-crash-fix-cherry-pick-error.patch @@ -0,0 +1,26 @@ +From 3edb83ca607bdf091cf46035b8e09e10b781f48a Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 21 Jun 2019 11:40:57 -0400 +Subject: [PATCH] BZ1518320 - entry cache crash fix cherry-pick error + +--- + configure.ac | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/configure.ac b/configure.ac +index ea528ff2b..91d6d398b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -72,6 +72,9 @@ AC_FUNC_STRFTIME + AC_FUNC_VPRINTF + AC_CHECK_FUNCS([endpwent ftruncate getcwd gethostbyname inet_ntoa localtime_r memmove memset mkdir munmap putenv rmdir setrlimit socket strcasecmp strchr strcspn strdup strerror strncasecmp strpbrk strrchr strstr strtol tzset]) + ++# These functions are *required* without option. ++AC_CHECK_FUNCS([clock_gettime], [], AC_MSG_ERROR([unable to locate required symbol clock_gettime])) ++ + # This will detect if we need to add the LIBADD_DL value for us. + LT_LIB_DLLOAD + +-- +2.21.0 + diff --git a/SPECS/389-ds-base.spec b/SPECS/389-ds-base.spec index 6c2b417..162cab2 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.8.4 -Release: %{?relprefix}23%{?prerel}%{?dist} +Release: %{?relprefix}25%{?prerel}.1%{?dist} License: GPLv3+ URL: https://www.port389.org/ Group: System Environment/Daemons @@ -170,6 +170,12 @@ Patch20: 0020-Ticket-50117-after-certain-failed-import-operation-i.patc Patch21: 0021-Ticket-49540-Fix-compiler-warning-in-ldif2ldbm.patch Patch22: 0022-Ticket-50078-cannot-add-cenotaph-in-read-only-consum.patch Patch23: 0023-Ticket-50177-import-task-should-not-be-deleted-too-r.patch +Patch24: 0024-Ticket-50396-Crash-in-PAM-plugin-when-user-does-not-.patch +Patch26: 0026-Ticket-50329-2nd-Possible-Security-Issue-DOS-due-to-.patch +Patch25: 0025-Issue-50426-nsSSL3Ciphers-is-limited-to-1024-charact.patch +Patch27: 0027-BZ1518320-entry-cache-crash-fix.patch +Patch28: 0028-BZ1518320-entry-cache-crash-fix.patch +Patch29: 0029-BZ1518320-entry-cache-crash-fix-cherry-pick-error.patch %description 389 Directory Server is an LDAPv3 compliant server. The base package includes @@ -517,6 +523,20 @@ fi %{_sysconfdir}/%{pkgname}/dirsrvtests %changelog +* Wed Jul 3 2019 Mark Reynolds - 1.3.8.4-25.1 +- Bump version to 1.3.8.4-25.1 +- Resolves: Bug 1718689 - dse.ldif strip-off string after 1023 character (missing patch file) + +* Fri Jun 21 2019 Mark Reynolds - 1.3.8.4-25 +- Bump version to 1.3.8.4-25 +- Resolves: Bug 1722828 - referint update should discard any changes if mep update fails +- Resolves: Bug 1718689 - dse.ldif strip-off string after 1023 character +- Resolves: Bug 1719720 - CVE-2019-3883 389-ds-base: DoS via hanging secured connections + +* Wed Jun 19 2019 Mark Reynolds - 1.3.8.4-24 +- Bump version to 1.3.8.4-24 +- Resolves: Bug 1718184 - segfault when using pam passthru and addn plugins together + * Wed Feb 6 2019 Mark Reynolds - 1.3.8.4-23 - Bump version to 1.3.8.4-23 - Resolves: Bug 1672173 - import task should not be deleted after import finishes to be able to query the status