]> git.sur5r.net Git - openldap/commitdiff
Store lock ID instead of pathname in lockfile
authorHallvard Furuseth <hallvard@openldap.org>
Sun, 12 Mar 2017 15:55:14 +0000 (16:55 +0100)
committerHallvard Furuseth <hallvard@openldap.org>
Sun, 19 Mar 2017 12:21:51 +0000 (13:21 +0100)
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

index 21f50f2a880778f7587db20fe36c2db248e309d3..d28f42ae9366c7fdc832f2139de4b80a4c90c6d7 100644 (file)
@@ -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)