ldb_mdb: prevent MDB_env reuse across forks
authorGary Lockyer <gary@catalyst.net.nz>
Tue, 13 Mar 2018 02:08:10 +0000 (15:08 +1300)
committerStefan Metzmacher <metze@samba.org>
Thu, 12 Apr 2018 14:27:18 +0000 (16:27 +0200)
MDB_env's may not be reused accross forks.  Check the pid that the lmdb
structure was created by, and return an error if it is being used by a
different process.

Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
lib/ldb/ldb_mdb/ldb_mdb.c

index 0e81a824f0eff6f78864eef2ddacb57e32406c5e..6662aae434a3817bd6faaf53b74790cf07258ef8 100644 (file)
@@ -440,6 +440,18 @@ static int lmdb_lock_read(struct ldb_module *module)
        void *data = ldb_module_get_private(module);
        struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
        struct lmdb_private *lmdb = ltdb->lmdb_private;
+       pid_t pid = getpid();
+
+       if (pid != lmdb->pid) {
+               ldb_asprintf_errstring(
+                       lmdb->ldb,
+                       __location__": Reusing ldb opend by pid %d in "
+                       "process %d\n",
+                       lmdb->pid,
+                       pid);
+               lmdb->error = MDB_BAD_TXN;
+               return LDB_ERR_PROTOCOL_ERROR;
+       }
 
        lmdb->error = MDB_SUCCESS;
        if (ltdb->in_transaction == 0 &&
@@ -479,6 +491,7 @@ static int lmdb_transaction_start(struct ltdb_private *ltdb)
        struct lmdb_trans *ltx;
        struct lmdb_trans *ltx_head;
        MDB_txn *tx_parent;
+       pid_t pid = getpid();
 
        /* Do not take out the transaction lock on a read-only DB */
        if (ltdb->read_only) {
@@ -490,6 +503,18 @@ static int lmdb_transaction_start(struct ltdb_private *ltdb)
                return ldb_oom(lmdb->ldb);
        }
 
+       if (pid != lmdb->pid) {
+               ldb_asprintf_errstring(
+                       lmdb->ldb,
+                       __location__": Reusing ldb opened by pid %d in "
+                       "process %d\n",
+                       lmdb->pid,
+                       pid);
+               lmdb->error = MDB_BAD_TXN;
+               return LDB_ERR_PROTOCOL_ERROR;
+       }
+
+
        ltx_head = lmdb_private_trans_head(lmdb);
 
        tx_parent = lmdb_trans_get_tx(ltx_head);
@@ -657,7 +682,7 @@ struct mdb_env_wrap {
        dev_t device;
        ino_t inode;
        MDB_env *env;
-       int pid;
+       pid_t pid;
 };
 
 static struct mdb_env_wrap *mdb_list;
@@ -684,10 +709,13 @@ static int lmdb_open_env(TALLOC_CTX *mem_ctx,
 
        struct mdb_env_wrap *w;
        struct stat st;
+       pid_t pid = getpid();
 
        if (stat(path, &st) == 0) {
                for (w=mdb_list;w;w=w->next) {
-                       if (st.st_dev == w->device && st.st_ino == w->inode) {
+                       if (st.st_dev == w->device &&
+                           st.st_ino == w->inode &&
+                           pid == w->pid) {
                                /*
                                 * We must have only one MDB_env per process
                                 */
@@ -758,6 +786,7 @@ static int lmdb_open_env(TALLOC_CTX *mem_ctx,
        w->env = *env;
        w->device = st.st_dev;
        w->inode  = st.st_ino;
+       w->pid = pid;
 
        talloc_set_destructor(w, mdb_env_wrap_destructor);