From 68eda68f0b99bd766d1fd52658e088640b67b39c Mon Sep 17 00:00:00 2001 From: Hallvard Furuseth Date: Sun, 12 Mar 2017 16:55:14 +0100 Subject: [PATCH] Store lock ID instead of pathname in lockfile This limits the namespace which the user can meddle with for POSIX semaphores and Windows mutexes. Their names change a bit, they no longer have fixed lengths. --- libraries/liblmdb/mdb.c | 101 ++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 40 deletions(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 21f50f2a88..d28f42ae93 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -465,14 +465,21 @@ typedef pthread_mutex_t *mdb_mutexref_t; #define Yu MDB_PRIy(u) /**< printf format for #mdb_size_t */ #define Yd MDB_PRIy(d) /**< printf format for 'signed #mdb_size_t' */ -#if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) -#define MNAME_LEN 32 -#elif defined(MDB_USE_SYSV_SEM) +#ifdef MDB_USE_SYSV_SEM #define MNAME_LEN (sizeof(int)) #else #define MNAME_LEN (sizeof(pthread_mutex_t)) #endif +/** Initial part of #MDB_env.me_mutexname[]. + * Changes to this code must be reflected in #MDB_LOCK_FORMAT. + */ +#ifdef _WIN32 +#define MUTEXNAME_PREFIX "Global\\MDB" +#elif defined MDB_USE_POSIX_SEM +#define MUTEXNAME_PREFIX "/MDB" +#endif + #ifdef MDB_USE_SYSV_SEM #define SYSV_SEM_FLAG 1 /**< SysV sems in lockfile format */ #else @@ -692,6 +699,8 @@ static txnid_t mdb_debug_start; */ typedef uint16_t indx_t; +typedef unsigned long long mdb_hash_t; + /** Default size of memory map. * This is certainly too small for any actual applications. Apps should always set * the size explicitly using #mdb_env_set_mapsize(). @@ -820,7 +829,8 @@ typedef struct MDB_txbody { */ volatile unsigned mtb_numreaders; #if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) - char mtb_rmname[MNAME_LEN]; + /** Binary form of names of the reader/writer locks */ + mdb_hash_t mtb_mutexid; #elif defined(MDB_USE_SYSV_SEM) int mtb_semid; int mtb_rlocked; @@ -842,17 +852,16 @@ typedef struct MDB_txninfo { #define mti_rmname mt1.mtb.mtb_rmname #define mti_txnid mt1.mtb.mtb_txnid #define mti_numreaders mt1.mtb.mtb_numreaders +#define mti_mutexid mt1.mtb.mtb_mutexid #ifdef MDB_USE_SYSV_SEM #define mti_semid mt1.mtb.mtb_semid #define mti_rlocked mt1.mtb.mtb_rlocked #endif char pad[(sizeof(MDB_txbody)+CACHELINE-1) & ~(CACHELINE-1)]; } mt1; +#if !(defined(_WIN32) || defined(MDB_USE_POSIX_SEM)) union { -#if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) - char mt2_wmname[MNAME_LEN]; -#define mti_wmname mt2.mt2_wmname -#elif defined MDB_USE_SYSV_SEM +#ifdef MDB_USE_SYSV_SEM int mt2_wlocked; #define mti_wlocked mt2.mt2_wlocked #else @@ -861,6 +870,7 @@ typedef struct MDB_txninfo { #endif char pad[(MNAME_LEN+CACHELINE-1) & ~(CACHELINE-1)]; } mt2; +#endif MDB_reader mti_readers[1]; } MDB_txninfo; @@ -1447,6 +1457,10 @@ struct MDB_env { #else mdb_mutex_t me_rmutex; mdb_mutex_t me_wmutex; +# if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) + /** Half-initialized name of mutexes, to be completed by #MUTEXNAME() */ + char me_mutexname[sizeof(MUTEXNAME_PREFIX) + 11]; +# endif #endif #ifdef MDB_VL32 MDB_ID3L me_rpages; /**< like #mt_rpages, but global to env */ @@ -4951,7 +4965,6 @@ mdb_env_excl_lock(MDB_env *env, int *excl) * Share and Enjoy! :-) */ -typedef unsigned long long mdb_hash_t; #define MDB_HASH_INIT ((mdb_hash_t)0xcbf29ce484222325ULL) /** perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer @@ -4993,25 +5006,33 @@ mdb_hash_val(MDB_val *val, mdb_hash_t hval) static const char mdb_a85[]= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"; static void ESECT -mdb_pack85(unsigned long l, char *out) +mdb_pack85(unsigned long long l, char *out) { int i; - for (i=0; i<5; i++) { + for (i=0; i<10 && l; i++) { *out++ = mdb_a85[l % 85]; l /= 85; } + *out = '\0'; } +/** Init #MDB_env.me_mutexname[] except the char which #MUTEXNAME() will set. + * Changes to this code must be reflected in #MDB_LOCK_FORMAT. + */ static void ESECT -mdb_hash_enc(MDB_val *val, char *encbuf) +mdb_env_mname_init(MDB_env *env) { - mdb_hash_t h = mdb_hash_val(val, MDB_HASH_INIT); - - mdb_pack85(h, encbuf); - mdb_pack85(h>>32, encbuf+5); - encbuf[10] = '\0'; + char *nm = env->me_mutexname; + strcpy(nm, MUTEXNAME_PREFIX); + mdb_pack85(env->me_txns->mti_mutexid, nm + sizeof(MUTEXNAME_PREFIX)); } + +/** Return env->me_mutexname after filling in ch ('r'/'w') for convenience */ +#define MUTEXNAME(env, ch) ( \ + (void) ((env)->me_mutexname[sizeof(MUTEXNAME_PREFIX)-1] = (ch)), \ + (env)->me_mutexname) + #endif /** Open and/or initialize the lock region for the environment. @@ -5110,7 +5131,6 @@ mdb_env_setup_locks(MDB_env *env, MDB_name *fname, int mode, int *excl) DWORD nlow; } idbuf; MDB_val val; - char encbuf[11]; if (!mdb_sec_inited) { InitializeSecurityDescriptor(&mdb_null_sd, @@ -5127,12 +5147,11 @@ mdb_env_setup_locks(MDB_env *env, MDB_name *fname, int mode, int *excl) idbuf.nlow = stbuf.nFileIndexLow; val.mv_data = &idbuf; val.mv_size = sizeof(idbuf); - mdb_hash_enc(&val, encbuf); - sprintf(env->me_txns->mti_rmname, "Global\\MDBr%s", encbuf); - sprintf(env->me_txns->mti_wmname, "Global\\MDBw%s", encbuf); - env->me_rmutex = CreateMutexA(&mdb_all_sa, FALSE, env->me_txns->mti_rmname); + env->me_txns->mti_mutexid = mdb_hash_val(&val, MDB_HASH_INIT); + mdb_env_mname_init(env); + env->me_rmutex = CreateMutexA(&mdb_all_sa, FALSE, MUTEXNAME(env, 'r')); if (!env->me_rmutex) goto fail_errno; - env->me_wmutex = CreateMutexA(&mdb_all_sa, FALSE, env->me_txns->mti_wmname); + env->me_wmutex = CreateMutexA(&mdb_all_sa, FALSE, MUTEXNAME(env, 'w')); if (!env->me_wmutex) goto fail_errno; #elif defined(MDB_USE_POSIX_SEM) struct stat stbuf; @@ -5141,7 +5160,6 @@ mdb_env_setup_locks(MDB_env *env, MDB_name *fname, int mode, int *excl) ino_t ino; } idbuf; MDB_val val; - char encbuf[11]; #if defined(__NetBSD__) #define MDB_SHORT_SEMNAMES 1 /* limited to 14 chars */ @@ -5151,22 +5169,23 @@ mdb_env_setup_locks(MDB_env *env, MDB_name *fname, int mode, int *excl) idbuf.ino = stbuf.st_ino; val.mv_data = &idbuf; val.mv_size = sizeof(idbuf); - mdb_hash_enc(&val, encbuf); + env->me_txns->mti_mutexid = mdb_hash_val(&val, MDB_HASH_INIT) #ifdef MDB_SHORT_SEMNAMES - encbuf[9] = '\0'; /* drop name from 15 chars to 14 chars */ + /* Max 9 base85-digits. We truncate here instead of in + * mdb_env_mname_init() to keep the latter portable. + */ + % ((mdb_hash_t)85*85*85*85*85*85*85*85*85) #endif - sprintf(env->me_txns->mti_rmname, "/MDBr%s", encbuf); - sprintf(env->me_txns->mti_wmname, "/MDBw%s", encbuf); + ; + mdb_env_mname_init(env); /* Clean up after a previous run, if needed: Try to * remove both semaphores before doing anything else. */ - sem_unlink(env->me_txns->mti_rmname); - sem_unlink(env->me_txns->mti_wmname); - env->me_rmutex = sem_open(env->me_txns->mti_rmname, - O_CREAT|O_EXCL, mode, 1); + sem_unlink(MUTEXNAME(env, 'r')); + sem_unlink(MUTEXNAME(env, 'w')); + env->me_rmutex = sem_open(MUTEXNAME(env, 'r'), O_CREAT|O_EXCL, mode, 1); if (env->me_rmutex == SEM_FAILED) goto fail_errno; - env->me_wmutex = sem_open(env->me_txns->mti_wmname, - O_CREAT|O_EXCL, mode, 1); + env->me_wmutex = sem_open(MUTEXNAME(env, 'w'), O_CREAT|O_EXCL, mode, 1); if (env->me_wmutex == SEM_FAILED) goto fail_errno; #elif defined(MDB_USE_SYSV_SEM) unsigned short vals[2] = {1, 1}; @@ -5230,14 +5249,16 @@ mdb_env_setup_locks(MDB_env *env, MDB_name *fname, int mode, int *excl) goto fail; } #ifdef _WIN32 - env->me_rmutex = OpenMutexA(SYNCHRONIZE, FALSE, env->me_txns->mti_rmname); + mdb_env_mname_init(env); + env->me_rmutex = OpenMutexA(SYNCHRONIZE, FALSE, MUTEXNAME(env, 'r')); if (!env->me_rmutex) goto fail_errno; - env->me_wmutex = OpenMutexA(SYNCHRONIZE, FALSE, env->me_txns->mti_wmname); + env->me_wmutex = OpenMutexA(SYNCHRONIZE, FALSE, MUTEXNAME(env, 'w')); if (!env->me_wmutex) goto fail_errno; #elif defined(MDB_USE_POSIX_SEM) - env->me_rmutex = sem_open(env->me_txns->mti_rmname, 0); + mdb_env_mname_init(env); + env->me_rmutex = sem_open(MUTEXNAME(env, 'r'), 0); if (env->me_rmutex == SEM_FAILED) goto fail_errno; - env->me_wmutex = sem_open(env->me_txns->mti_wmname, 0); + env->me_wmutex = sem_open(MUTEXNAME(env, 'w'), 0); if (env->me_wmutex == SEM_FAILED) goto fail_errno; #elif defined(MDB_USE_SYSV_SEM) semid = env->me_txns->mti_semid; @@ -5517,8 +5538,8 @@ mdb_env_close0(MDB_env *env, int excl) if (excl == 0) mdb_env_excl_lock(env, &excl); if (excl > 0) { - sem_unlink(env->me_txns->mti_rmname); - sem_unlink(env->me_txns->mti_wmname); + sem_unlink(MUTEXNAME(env, 'r')); + sem_unlink(MUTEXNAME(env, 'w')); } } #elif defined(MDB_USE_SYSV_SEM) -- 2.39.5