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 <mreynolds@redhat.com>
+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 <mreynolds@redhat.com>
+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 <tbordaz@redhat.com>
+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 <mreynolds@redhat.com>
+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 <mreynolds@redhat.com>
+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 <mreynolds@redhat.com>
+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 <mreynolds@redhat.com> - 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 <mreynolds@redhat.com> - 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 <mreynolds@redhat.com> - 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 <mreynolds@redhat.com> - 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