Blob Blame Raw
From 583eda60ede7224cea8aed5bae1bc819fab77b45 Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Tue, 5 Nov 2013 16:58:44 +0100
Subject: [PATCH 44/44] 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)
---
 ldap/servers/slapd/back-ldbm/back-ldbm.h       | 2 ++
 ldap/servers/slapd/back-ldbm/cache.c           | 8 ++++++++
 ldap/servers/slapd/back-ldbm/id2entry.c        | 2 ++
 ldap/servers/slapd/back-ldbm/proto-back-ldbm.h | 2 ++
 4 files changed, 14 insertions(+)

diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h
index 970f3c2..5f8a05a 100644
--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h
@@ -409,6 +409,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 5fa06fb..a73ae6a 100644
--- a/ldap/servers/slapd/back-ldbm/cache.c
+++ b/ldap/servers/slapd/back-ldbm/cache.c
@@ -1472,6 +1472,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 dae558c..7a3b19e 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 3b2e586..d168714 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);
-- 
1.8.1.4