ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
New commits:
commit 1d9ae0f4a1ea12463ac59a04da5e6572db002d73
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Thu Mar 19 09:58:53 2015 -0400
Ticket 48132 - modrdn crashes server (invalid read/writes)
Bug Description: When performing a modrdn stress test using two masters
a double free can occur that will lead to a crash. When
the server is under load it might have to retry the modrdn
operation. During this retry the SLAPI_MODRDN_EXISTING_ENTRY
entry was previosuly replaced, and it can be freed twice on
the second retry..
Fix Description: Check if entry being retuned form the cache is the same as
the entry stored in SLAPI_MODRDN_EXISTING_ENTRY, if it is,
set it to NULL so it is not freed again.
https://fedorahosted.org/389/ticket/48132
valgrind: PASSED
Reviewed by: nhosoi(Thanks!)
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index f5a404b..d2e9737 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -279,8 +279,18 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
+ slapi_pblock_get( pb, SLAPI_MODRDN_EXISTING_ENTRY, &ent );
if (cache_is_in_cache(&inst->inst_cache, ec)) {
CACHE_REMOVE(&inst->inst_cache, ec);
+ if (ent && (ent == ec->ep_entry)){
+ /*
+ * On a retry, it's possible that ec is now stored in the
+ * pblock as SLAPI_MODRDN_EXISTING_ENTRY. "ec" will be
freed
+ * by CACHE_RETURN below, so set ent to NULL so don't free
+ * it again.
+ */
+ ent = NULL;
+ }
}
CACHE_RETURN(&inst->inst_cache, &ec);
if (!cache_is_in_cache(&inst->inst_cache, e)) {
@@ -290,7 +300,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
slapi_entry_get_dn_const(e->ep_entry));
}
}
- slapi_pblock_get( pb, SLAPI_MODRDN_EXISTING_ENTRY, &ent );
if (ent && (ent != original_entry->ep_entry)) {
slapi_entry_free(ent);
slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, NULL );