From bf65b45fa9d6b6ea241bb741f5aba7df392ced65 Mon Sep 17 00:00:00 2001 From: Noriko Hosoi 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