From bf65b45fa9d6b6ea241bb741f5aba7df392ced65 Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@redhat.com>
Date: Mon, 12 Oct 2015 15:24:55 -0700
Subject: [PATCH 362/363] Ticket #48287 - Double free while adding entries
(1.2.11 only)
Description: If a callback at SLAPI_PLUGIN_BE_TXN_*_ADD_FN fails and the
adding-entry is in a cache, the ldbm_back_add is supposed to remove the
adding-entry from the cache and free it. The issue was fixed in 1.3.1
and newer by these tickets:
Ticket #47808 - If be_txn plugin fails in ldbm_back_add, adding entry is double freed.
Ticket #47815 - Add operations rejected by betxn plugins remain in cache
which were not backported to 1.2.11.
https://fedorahosted.org/389/ticket/48287
Reviewed by tbordaz@redhat.com (Thank you, Thierry!!)
(cherry picked from commit 265c6e399016ad4a46c8709d32367b9c30ea57cf)
---
ldap/servers/slapd/add.c | 6 ++----
ldap/servers/slapd/back-ldbm/ldbm_add.c | 19 ++++++++++++++-----
2 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
index 0198b1c..9f0bbc0 100644
--- a/ldap/servers/slapd/add.c
+++ b/ldap/servers/slapd/add.c
@@ -726,10 +726,8 @@ static void op_shared_add (Slapi_PBlock *pb)
}
else
{
- /* restore e so we can free it below */
- if (save_e) {
- e = save_e;
- }
+ /* PR_ASSERT(!save_e); save_e is supposed to be freed in the backend. */
+ e = save_e;
if (rc == SLAPI_FAIL_DISKFULL)
{
operation_out_of_disk_space();
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index 5069f98..b915bfe 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -108,7 +108,6 @@ ldbm_back_add( Slapi_PBlock *pb )
Slapi_DN parentsdn;
Slapi_Operation *operation;
int dblock_acquired= 0;
- int is_remove_from_cache= 0;
int is_replicated_operation= 0;
int is_resurect_operation= 0;
int is_tombstone_operation= 0;
@@ -1173,7 +1172,20 @@ diskfull_return:
slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
}
}
-
+ if ( addingentry ) {
+ if (inst && cache_is_in_cache(&inst->inst_cache, addingentry)) {
+ CACHE_REMOVE(&inst->inst_cache, addingentry);
+ /* tell frontend not to free this entry */
+ slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL);
+ }
+ else if (!cache_has_otherref(&inst->inst_cache, addingentry))
+ {
+ if (!is_resurect_operation) { /* if resurect, tombstoneentry is dupped. */
+ backentry_clear_entry(addingentry); /* e is released in the frontend */
+ }
+ }
+ CACHE_RETURN( &inst->inst_cache, &addingentry );
+ }
if (!noabort) {
dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */
}
@@ -1225,9 +1237,6 @@ common_return:
}
}
}
- if (is_remove_from_cache) {
- CACHE_REMOVE(&inst->inst_cache, addingentry);
- }
CACHE_RETURN( &inst->inst_cache, &addingentry );
}
}
--
2.4.3