From a0a03793a3977ea448a496488d732fd63bf624dd Mon Sep 17 00:00:00 2001 From: Ludwig Krispenz Date: Nov 05 2013 20:46:46 +0000 Subject: Ticket 47577 - crash when removing entries from cache Bug Description: when the dn of an entry in the cache was adjusted to the parent dn, for soenm time teh dn was not defined, anothe thread accessing the dn of teh chached entry could crash Fix Description: hold the cache mutex when modifyingthe dn of an entry in the cache https://fedorahosted.org/389/ticket/47577 Reviewed by: rmeggins (cherry picked from commit 7272dbda7f43974eed003cbcfc0ddd57fe433687) (cherry picked from commit 1056a6282f246a9c396b8052d726005fe8189512) (cherry picked from commit 00b19f3b4af662341c72fa6cfd60b5e136f1428f) (cherry picked from commit ecc210f3ca25528f5f718680409ded0021d5604c) (cherry picked from commit 85a99e924e16ddc69b8b2cca97550d66f4ea11e0) --- diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h index 61c7af9..e912783 100644 --- a/ldap/servers/slapd/back-ldbm/back-ldbm.h +++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h @@ -408,6 +408,8 @@ struct cache { #define CACHE_ADD(cache, p, a) cache_add((cache), (void *)(p), (void **)(a)) #define CACHE_RETURN(cache, p) cache_return((cache), (void **)(p)) #define CACHE_REMOVE(cache, p) cache_remove((cache), (void *)(p)) +#define CACHE_LOCK(cache) cache_lock((cache)) +#define CACHE_UNLOCK(cache) cache_unlock((cache)) /* various modules keep private data inside the attrinfo structure */ typedef struct dblayer_private dblayer_private; diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c index 1c81a1b..d97644f 100644 --- a/ldap/servers/slapd/back-ldbm/cache.c +++ b/ldap/servers/slapd/back-ldbm/cache.c @@ -1460,6 +1460,14 @@ int cache_add_tentative(struct cache *cache, struct backentry *e, { return entrycache_add_int(cache, e, ENTRY_STATE_CREATING, alt); } +void cache_lock(struct cache *cache) +{ + PR_Lock(cache->c_mutex); +} +void cache_unlock(struct cache *cache) +{ + PR_Unlock(cache->c_mutex); +} /* locks an entry so that it can be modified (you should have gotten the * entry via cache_find_*). diff --git a/ldap/servers/slapd/back-ldbm/id2entry.c b/ldap/servers/slapd/back-ldbm/id2entry.c index e278a2a..ea4523d 100644 --- a/ldap/servers/slapd/back-ldbm/id2entry.c +++ b/ldap/servers/slapd/back-ldbm/id2entry.c @@ -167,10 +167,12 @@ id2entry_add_ext(backend *be, struct backentry *e, back_txn *txn, if (myparentdn && PL_strcmp(parentdn, myparentdn)) { Slapi_DN *sdn = slapi_entry_get_sdn(e->ep_entry); char *newdn = NULL; + CACHE_LOCK(&inst->inst_cache); slapi_sdn_done(sdn); newdn = slapi_ch_smprintf("%s,%s", myrdn, parentdn); slapi_sdn_init_dn_passin(sdn, newdn); slapi_sdn_get_ndn(sdn); /* to set ndn */ + CACHE_UNLOCK(&inst->inst_cache); } slapi_ch_free_string(&myparentdn); } diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h index a7fb06d..2e490d3 100644 --- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h +++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h @@ -76,6 +76,8 @@ void cache_get_stats(struct cache *cache, PRUint64 *hits, PRUint64 *tries, void cache_debug_hash(struct cache *cache, char **out); int cache_remove(struct cache *cache, void *e); void cache_return(struct cache *cache, void **bep); +void cache_lock(struct cache *cache); +void cache_unlock(struct cache *cache); struct backentry *cache_find_dn(struct cache *cache, const char *dn, unsigned long ndnlen); struct backentry *cache_find_id(struct cache *cache, ID id); struct backentry *cache_find_uuid(struct cache *cache, const char *uuid);