From 83068484723e043e424b460c3073021b26e8dfa0 Mon Sep 17 00:00:00 2001 From: Ludwig Krispenz Date: Tue, 12 May 2015 10:24:29 +0200 Subject: [PATCH 329/329] Ticket 48149 - ns-slapd double free or corruption crash Bug Description: if the per file statistics are retrived from the BDB backend, there is a race condition, which corrupts the memory allcated for the statistics. It happens id a new file with a longer backend/filename is openend between the alloaction for the statistics data and the actual populating if it Fix Description: The bug is in BDB and there is a fix from Oracle for the latest versions, it is unclear if it will be backported to the versions used in current supported389 platforms. A fix in DS code is to lock the open calls from the file statistic call https://fedorahosted.org/389/ticket/48149 Reviewed by: ? (cherry picked from commit d620bb644a9b71ca9259edba42d62058e628cc0a) --- ldap/servers/slapd/back-ldbm/dblayer.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c index b25fccb..031523c 100644 --- a/ldap/servers/slapd/back-ldbm/dblayer.c +++ b/ldap/servers/slapd/back-ldbm/dblayer.c @@ -97,15 +97,19 @@ #include "dblayer.h" #if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 4100 -#define DB_OPEN(oflags, db, txnid, file, database, type, flags, mode, rval) \ +#define DB_OPEN(priv, oflags, db, txnid, file, database, type, flags, mode, rval) \ { \ if (((oflags) & DB_INIT_TXN) && ((oflags) & DB_INIT_LOG)) \ { \ + if ((priv)) slapi_rwlock_rdlock((priv)->dblayer_env_lock); \ (rval) = ((db)->open)((db), (txnid), (file), (database), (type), (flags)|DB_AUTO_COMMIT, (mode)); \ + if ((priv)) slapi_rwlock_unlock((priv)->dblayer_env_lock); \ } \ else \ { \ + if ((priv)) slapi_rwlock_rdlock((priv)->dblayer_env_lock); \ (rval) = ((db)->open)((db), (txnid), (file), (database), (type), (flags), (mode)); \ + if ((priv)) slapi_rwlock_unlock((priv)->dblayer_env_lock); \ } \ } /* 608145: db4.1 and newer does not require exclusive lock for checkpointing @@ -113,7 +117,7 @@ #define DB_CHECKPOINT_LOCK(use_lock, lock) ; #define DB_CHECKPOINT_UNLOCK(use_lock, lock) ; #else /* older then db 41 */ -#define DB_OPEN(oflags, db, txnid, file, database, type, flags, mode, rval) \ +#define DB_OPEN(env, oflags, db, txnid, file, database, type, flags, mode, rval) \ (rval) = (db)->open((db), (file), (database), (type), (flags), (mode)) #define DB_CHECKPOINT_LOCK(use_lock, lock) if(use_lock) slapi_rwlock_wrlock(lock); #define DB_CHECKPOINT_UNLOCK(use_lock, lock) if(use_lock) slapi_rwlock_unlock(lock); @@ -2225,7 +2229,7 @@ int dblayer_instance_start(backend *be, int mode) abs_id2entry_file = slapi_ch_smprintf( "%s%c%s", inst_dirp, get_sep(inst_dirp), ID2ENTRY LDBM_FILENAME_SUFFIX); - DB_OPEN(mypEnv->dblayer_openflags, + DB_OPEN(mypEnv, mypEnv->dblayer_openflags, dbp, NULL/* txnid */, abs_id2entry_file, subname, DB_BTREE, open_flags, priv->dblayer_file_mode, return_value); dbp->close(dbp, 0); @@ -2256,7 +2260,7 @@ int dblayer_instance_start(backend *be, int mode) #endif slapi_ch_free_string(&abs_id2entry_file); } - DB_OPEN(mypEnv->dblayer_openflags, + DB_OPEN(mypEnv, mypEnv->dblayer_openflags, dbp, NULL/* txnid */, id2entry_file, subname, DB_BTREE, open_flags, priv->dblayer_file_mode, return_value); if (0 != return_value) { @@ -2533,7 +2537,7 @@ dblayer_get_aux_id2entry_ext(backend *be, DB **ppDB, DB_ENV **ppEnv, } PR_ASSERT(dblayer_inst_exists(inst, NULL)); - DB_OPEN(envflags, dbp, NULL/* txnid */, id2entry_file, subname, DB_BTREE, + DB_OPEN(mypEnv, envflags, dbp, NULL/* txnid */, id2entry_file, subname, DB_BTREE, dbflags, priv->dblayer_file_mode, rval); if (rval) { LDAPDebug(LDAP_DEBUG_ANY, @@ -3085,7 +3089,7 @@ dblayer_open_file(backend *be, char* indexname, int open_flag, } abs_file_name = slapi_ch_smprintf("%s%c%s", inst_dirp, get_sep(inst_dirp), file_name); - DB_OPEN(pENV->dblayer_openflags, + DB_OPEN(pENV, pENV->dblayer_openflags, dbp, NULL/* txnid */, abs_file_name, subname, DB_BTREE, open_flags, priv->dblayer_file_mode, return_value); dbp->close(dbp, 0); @@ -3101,7 +3105,7 @@ dblayer_open_file(backend *be, char* indexname, int open_flag, slapi_ch_free_string(&abs_file_name); } - DB_OPEN(pENV->dblayer_openflags, + DB_OPEN(pENV, pENV->dblayer_openflags, dbp, NULL, /* txnid */ rel_path, subname, DB_BTREE, open_flags, priv->dblayer_file_mode, return_value); #if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR == 4100 @@ -4743,6 +4747,7 @@ int dblayer_memp_stat(struct ldbminfo *li, DB_MPOOL_STAT **gsp, { dblayer_private *priv = NULL; DB_ENV *env = NULL; + int rc; PR_ASSERT(NULL != li); @@ -4752,7 +4757,10 @@ int dblayer_memp_stat(struct ldbminfo *li, DB_MPOOL_STAT **gsp, env = priv->dblayer_env->dblayer_DB_ENV; PR_ASSERT(NULL != env); - return MEMP_STAT(env, gsp, fsp, 0, (void *)slapi_ch_malloc); + slapi_rwlock_wrlock(priv->dblayer_env->dblayer_env_lock); + rc = MEMP_STAT(env, gsp, fsp, 0, (void *)slapi_ch_malloc); + slapi_rwlock_unlock(priv->dblayer_env->dblayer_env_lock); + return rc; } /* import wants this one */ @@ -4761,6 +4769,7 @@ int dblayer_memp_stat_instance(ldbm_instance *inst, DB_MPOOL_STAT **gsp, { DB_ENV *env = NULL; dblayer_private *priv = NULL; + int rc; PR_ASSERT(NULL != inst); @@ -4773,7 +4782,10 @@ int dblayer_memp_stat_instance(ldbm_instance *inst, DB_MPOOL_STAT **gsp, } PR_ASSERT(NULL != env); - return MEMP_STAT(env, gsp, fsp, 0, (void *)slapi_ch_malloc); + slapi_rwlock_wrlock(priv->dblayer_env->dblayer_env_lock); + rc = MEMP_STAT(env, gsp, fsp, 0, (void *)slapi_ch_malloc); + slapi_rwlock_unlock(priv->dblayer_env->dblayer_env_lock); + return rc; } /* Helper functions for recovery */ -- 1.9.3