Blob Blame Raw
From afe5e1ac7306fd5024dcb6550dce3b0c722cbe31 Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@redhat.com>
Date: Wed, 8 Oct 2014 10:38:02 -0700
Subject: [PATCH 20/21] Ticket #47897 - Need to move slapi_pblock_set(pb,
 SLAPI_MODRDN_EXISTING_ENTRY, original_entry->ep_entry) prior to
 original_entry overwritten

Bug Description: In the DEADLOCK retry code in ldbm_back_modrdn,
SLAPI_MODRDN_EXISTING_ENTRY in pblock is reset with the new entry
to be renamed.  The location of the setting entry was inappropriate,
thus instead of the entry, but its backup is set in pblock.

Fix Description: Moving the slapi_pblock_set(SLAPI_MODRDN_EXISTING_
ENTRY) to the correct position.

Plus, in the DEADLOCK retry code, original_entry is duplicated and
used for the next loop.  The source of the duplication has to be
the clean entry before updated in the backend code, but in ldbm_add,
ldbm_modify, and ldbm_modrdn, the current entry was duplicated and
set to the original entry, which could have been updated in the
previous loop.  This patch fixes it, as well.

https://fedorahosted.org/389/ticket/47897

Reviewed by tbordaz@redhat.com (Thank you, Theirry!!)

(cherry picked from commit 2aabb017bd4eec6d30bf00486eb027f59129cf74)
(cherry picked from commit 2393a48021944230f5ebcf5363c0095b1c4679ab)
---
 ldap/servers/slapd/back-ldbm/ldbm_add.c    | 2 +-
 ldap/servers/slapd/back-ldbm/ldbm_modify.c | 2 +-
 ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index b74154a..75cb0dc 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -225,7 +225,7 @@ ldbm_back_add( Slapi_PBlock *pb )
 			slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
 			/* must duplicate addingentry before returning it to cache,
 			 * which could free the entry. */
-			if ( (tmpentry = backentry_dup( addingentry )) == NULL ) {
+			if ((tmpentry = backentry_dup(originalentry?originalentry:addingentry)) == NULL) {
 				ldap_result_code= LDAP_OPERATIONS_ERROR;
 				goto error_return;
 			}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index d15b050..b9f754d 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -521,7 +521,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
 			if (ec) {
 				/* must duplicate ec before returning it to cache,
 				 * which could free the entry. */
-				if ( (tmpentry = backentry_dup( ec )) == NULL ) {
+				if ((tmpentry = backentry_dup(original_entry?original_entry:ec)) == NULL) {
 					ldap_result_code= LDAP_OPERATIONS_ERROR;
 					goto error_return;
 				}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index 7bcbcee..6a4982c 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -275,7 +275,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
             orig_dn_newsuperiordn = slapi_sdn_dup(orig_dn_newsuperiordn);
             /* must duplicate ec before returning it to cache,
              * which could free the entry. */
-            if ( (tmpentry = backentry_dup( ec )) == NULL ) {
+            if ((tmpentry = backentry_dup(original_entry?original_entry:ec)) == NULL) {
                 ldap_result_code= LDAP_OPERATIONS_ERROR;
                 goto error_return;
             }
@@ -295,10 +295,10 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
                 slapi_entry_free(ent);
                 slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, NULL );
             }
+            slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, original_entry->ep_entry );
             ec = original_entry;
             original_entry = tmpentry;
             tmpentry = NULL;
-            slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, original_entry->ep_entry );
             free_modrdn_existing_entry = 0; /* owned by original_entry now */
             if (!cache_is_in_cache(&inst->inst_cache, ec)) {
                 /* Put the resetted entry 'ec' into the cache again. */
-- 
1.9.3