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.
ntdll
Hallvard Furuseth 8 years ago
parent 58ba039b8f
commit 68eda68f0b
  1. 101
      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 Yu MDB_PRIy(u) /**< printf format for #mdb_size_t */
#define Yd MDB_PRIy(d) /**< printf format for 'signed #mdb_size_t' */ #define Yd MDB_PRIy(d) /**< printf format for 'signed #mdb_size_t' */
#if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) #ifdef MDB_USE_SYSV_SEM
#define MNAME_LEN 32
#elif defined(MDB_USE_SYSV_SEM)
#define MNAME_LEN (sizeof(int)) #define MNAME_LEN (sizeof(int))
#else #else
#define MNAME_LEN (sizeof(pthread_mutex_t)) #define MNAME_LEN (sizeof(pthread_mutex_t))
#endif #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 #ifdef MDB_USE_SYSV_SEM
#define SYSV_SEM_FLAG 1 /**< SysV sems in lockfile format */ #define SYSV_SEM_FLAG 1 /**< SysV sems in lockfile format */
#else #else
@ -692,6 +699,8 @@ static txnid_t mdb_debug_start;
*/ */
typedef uint16_t indx_t; typedef uint16_t indx_t;
typedef unsigned long long mdb_hash_t;
/** Default size of memory map. /** Default size of memory map.
* This is certainly too small for any actual applications. Apps should always set * This is certainly too small for any actual applications. Apps should always set
* the size explicitly using #mdb_env_set_mapsize(). * the size explicitly using #mdb_env_set_mapsize().
@ -820,7 +829,8 @@ typedef struct MDB_txbody {
*/ */
volatile unsigned mtb_numreaders; volatile unsigned mtb_numreaders;
#if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) #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) #elif defined(MDB_USE_SYSV_SEM)
int mtb_semid; int mtb_semid;
int mtb_rlocked; int mtb_rlocked;
@ -842,17 +852,16 @@ typedef struct MDB_txninfo {
#define mti_rmname mt1.mtb.mtb_rmname #define mti_rmname mt1.mtb.mtb_rmname
#define mti_txnid mt1.mtb.mtb_txnid #define mti_txnid mt1.mtb.mtb_txnid
#define mti_numreaders mt1.mtb.mtb_numreaders #define mti_numreaders mt1.mtb.mtb_numreaders
#define mti_mutexid mt1.mtb.mtb_mutexid
#ifdef MDB_USE_SYSV_SEM #ifdef MDB_USE_SYSV_SEM
#define mti_semid mt1.mtb.mtb_semid #define mti_semid mt1.mtb.mtb_semid
#define mti_rlocked mt1.mtb.mtb_rlocked #define mti_rlocked mt1.mtb.mtb_rlocked
#endif #endif
char pad[(sizeof(MDB_txbody)+CACHELINE-1) & ~(CACHELINE-1)]; char pad[(sizeof(MDB_txbody)+CACHELINE-1) & ~(CACHELINE-1)];
} mt1; } mt1;
#if !(defined(_WIN32) || defined(MDB_USE_POSIX_SEM))
union { union {
#if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) #ifdef MDB_USE_SYSV_SEM
char mt2_wmname[MNAME_LEN];
#define mti_wmname mt2.mt2_wmname
#elif defined MDB_USE_SYSV_SEM
int mt2_wlocked; int mt2_wlocked;
#define mti_wlocked mt2.mt2_wlocked #define mti_wlocked mt2.mt2_wlocked
#else #else
@ -861,6 +870,7 @@ typedef struct MDB_txninfo {
#endif #endif
char pad[(MNAME_LEN+CACHELINE-1) & ~(CACHELINE-1)]; char pad[(MNAME_LEN+CACHELINE-1) & ~(CACHELINE-1)];
} mt2; } mt2;
#endif
MDB_reader mti_readers[1]; MDB_reader mti_readers[1];
} MDB_txninfo; } MDB_txninfo;
@ -1447,6 +1457,10 @@ struct MDB_env {
#else #else
mdb_mutex_t me_rmutex; mdb_mutex_t me_rmutex;
mdb_mutex_t me_wmutex; 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 #endif
#ifdef MDB_VL32 #ifdef MDB_VL32
MDB_ID3L me_rpages; /**< like #mt_rpages, but global to env */ 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! :-) * Share and Enjoy! :-)
*/ */
typedef unsigned long long mdb_hash_t;
#define MDB_HASH_INIT ((mdb_hash_t)0xcbf29ce484222325ULL) #define MDB_HASH_INIT ((mdb_hash_t)0xcbf29ce484222325ULL)
/** perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer /** 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 const char mdb_a85[]= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
static void ESECT static void ESECT
mdb_pack85(unsigned long l, char *out) mdb_pack85(unsigned long long l, char *out)
{ {
int i; int i;
for (i=0; i<5; i++) { for (i=0; i<10 && l; i++) {
*out++ = mdb_a85[l % 85]; *out++ = mdb_a85[l % 85];
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 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); char *nm = env->me_mutexname;
strcpy(nm, MUTEXNAME_PREFIX);
mdb_pack85(h, encbuf); mdb_pack85(env->me_txns->mti_mutexid, nm + sizeof(MUTEXNAME_PREFIX));
mdb_pack85(h>>32, encbuf+5);
encbuf[10] = '\0';
} }
/** 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 #endif
/** Open and/or initialize the lock region for the environment. /** 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; DWORD nlow;
} idbuf; } idbuf;
MDB_val val; MDB_val val;
char encbuf[11];
if (!mdb_sec_inited) { if (!mdb_sec_inited) {
InitializeSecurityDescriptor(&mdb_null_sd, 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; idbuf.nlow = stbuf.nFileIndexLow;
val.mv_data = &idbuf; val.mv_data = &idbuf;
val.mv_size = sizeof(idbuf); val.mv_size = sizeof(idbuf);
mdb_hash_enc(&val, encbuf); env->me_txns->mti_mutexid = mdb_hash_val(&val, MDB_HASH_INIT);
sprintf(env->me_txns->mti_rmname, "Global\\MDBr%s", encbuf); mdb_env_mname_init(env);
sprintf(env->me_txns->mti_wmname, "Global\\MDBw%s", encbuf); env->me_rmutex = CreateMutexA(&mdb_all_sa, FALSE, MUTEXNAME(env, 'r'));
env->me_rmutex = CreateMutexA(&mdb_all_sa, FALSE, env->me_txns->mti_rmname);
if (!env->me_rmutex) goto fail_errno; 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; if (!env->me_wmutex) goto fail_errno;
#elif defined(MDB_USE_POSIX_SEM) #elif defined(MDB_USE_POSIX_SEM)
struct stat stbuf; struct stat stbuf;
@ -5141,7 +5160,6 @@ mdb_env_setup_locks(MDB_env *env, MDB_name *fname, int mode, int *excl)
ino_t ino; ino_t ino;
} idbuf; } idbuf;
MDB_val val; MDB_val val;
char encbuf[11];
#if defined(__NetBSD__) #if defined(__NetBSD__)
#define MDB_SHORT_SEMNAMES 1 /* limited to 14 chars */ #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; idbuf.ino = stbuf.st_ino;
val.mv_data = &idbuf; val.mv_data = &idbuf;
val.mv_size = sizeof(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 #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 #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 /* Clean up after a previous run, if needed: Try to
* remove both semaphores before doing anything else. * remove both semaphores before doing anything else.
*/ */
sem_unlink(env->me_txns->mti_rmname); sem_unlink(MUTEXNAME(env, 'r'));
sem_unlink(env->me_txns->mti_wmname); sem_unlink(MUTEXNAME(env, 'w'));
env->me_rmutex = sem_open(env->me_txns->mti_rmname, env->me_rmutex = sem_open(MUTEXNAME(env, 'r'), O_CREAT|O_EXCL, mode, 1);
O_CREAT|O_EXCL, mode, 1);
if (env->me_rmutex == SEM_FAILED) goto fail_errno; if (env->me_rmutex == SEM_FAILED) goto fail_errno;
env->me_wmutex = sem_open(env->me_txns->mti_wmname, env->me_wmutex = sem_open(MUTEXNAME(env, 'w'), O_CREAT|O_EXCL, mode, 1);
O_CREAT|O_EXCL, mode, 1);
if (env->me_wmutex == SEM_FAILED) goto fail_errno; if (env->me_wmutex == SEM_FAILED) goto fail_errno;
#elif defined(MDB_USE_SYSV_SEM) #elif defined(MDB_USE_SYSV_SEM)
unsigned short vals[2] = {1, 1}; 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; goto fail;
} }
#ifdef _WIN32 #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; 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; if (!env->me_wmutex) goto fail_errno;
#elif defined(MDB_USE_POSIX_SEM) #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; 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; if (env->me_wmutex == SEM_FAILED) goto fail_errno;
#elif defined(MDB_USE_SYSV_SEM) #elif defined(MDB_USE_SYSV_SEM)
semid = env->me_txns->mti_semid; semid = env->me_txns->mti_semid;
@ -5517,8 +5538,8 @@ mdb_env_close0(MDB_env *env, int excl)
if (excl == 0) if (excl == 0)
mdb_env_excl_lock(env, &excl); mdb_env_excl_lock(env, &excl);
if (excl > 0) { if (excl > 0) {
sem_unlink(env->me_txns->mti_rmname); sem_unlink(MUTEXNAME(env, 'r'));
sem_unlink(env->me_txns->mti_wmname); sem_unlink(MUTEXNAME(env, 'w'));
} }
} }
#elif defined(MDB_USE_SYSV_SEM) #elif defined(MDB_USE_SYSV_SEM)

Loading…
Cancel
Save