ldb_tdb: Change ltdb_connect() NOT to request a kernel-level read only TDB
authorAndrew Bartlett <abartlet@samba.org>
Sun, 17 Sep 2017 22:43:32 +0000 (10:43 +1200)
committerDouglas Bagnall <dbagnall@samba.org>
Wed, 20 Sep 2017 00:25:30 +0000 (02:25 +0200)
We support opening and LDB multiple times in a process, but do not support this in tdb.

As we can open the ldb with different flags, we must ensure a later read-write
open is possible.

Additionally, a read-only TDB will refuse the all-record lock, preventing
the ldb from even loading.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13033

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
lib/ldb/ldb_tdb/ldb_index.c
lib/ldb/ldb_tdb/ldb_tdb.c
lib/ldb/ldb_tdb/ldb_tdb.h

index 3510dd9b1bc1fe01e45dcb2eb2d34e8c42415308..7b36ac4bce32333889a4928821b6bafdf28b7081 100644 (file)
@@ -310,6 +310,11 @@ static int ltdb_dn_list_store(struct ldb_module *module, struct ldb_dn *dn,
        rec.dptr = (uint8_t *)&list2;
        rec.dsize = sizeof(void *);
 
+
+       /*
+        * This is not a store into the main DB, but into an in-memory
+        * TDB, so we don't need a guard on ltdb->read_only
+        */
        ret = tdb_store(ltdb->idxptr->itdb, key, rec, TDB_INSERT);
        if (ret != 0) {
                return ltdb_err_map(tdb_error(ltdb->idxptr->itdb));
@@ -1760,6 +1765,14 @@ int ltdb_reindex(struct ldb_module *module)
        int ret;
        struct ltdb_reindex_context ctx;
 
+       /*
+        * Only triggered after a modification, but make clear we do
+        * not re-index a read-only DB
+        */
+       if (ltdb->read_only) {
+               return LDB_ERR_UNWILLING_TO_PERFORM;
+       }
+
        if (ltdb_cache_reload(module) != 0) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
index 3d4241f742b2a38a7b2504f848e1cfe36fcf475b..ca5b82e435944dd23e81b314dbbf21531d2ddf89 100644 (file)
@@ -308,6 +308,10 @@ int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flg
        struct ldb_val ldb_data;
        int ret = LDB_SUCCESS;
 
+       if (ltdb->read_only) {
+               return LDB_ERR_UNWILLING_TO_PERFORM;
+       }
+
        tdb_key = ltdb_key(module, msg->dn);
        if (tdb_key.dptr == NULL) {
                return LDB_ERR_OTHER;
@@ -476,6 +480,10 @@ int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn)
        TDB_DATA tdb_key;
        int ret;
 
+       if (ltdb->read_only) {
+               return LDB_ERR_UNWILLING_TO_PERFORM;
+       }
+
        tdb_key = ltdb_key(module, dn);
        if (!tdb_key.dptr) {
                return LDB_ERR_OTHER;
@@ -1165,6 +1173,11 @@ static int ltdb_start_trans(struct ldb_module *module)
        void *data = ldb_module_get_private(module);
        struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
 
+       /* Do not take out the transaction lock on a read-only DB */
+       if (ltdb->read_only) {
+               return LDB_ERR_UNWILLING_TO_PERFORM;
+       }
+
        if (tdb_transaction_start(ltdb->tdb) != 0) {
                return ltdb_err_map(tdb_error(ltdb->tdb));
        }
@@ -1648,20 +1661,36 @@ static int ltdb_connect(struct ldb_context *ldb, const char *url,
                tdb_flags |= TDB_NOMMAP;
        }
 
+       ltdb = talloc_zero(ldb, struct ltdb_private);
+       if (!ltdb) {
+               ldb_oom(ldb);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
        if (flags & LDB_FLG_RDONLY) {
-               open_flags = O_RDONLY;
+               /*
+                * This is weird, but because we can only have one tdb
+                * in this process, and the other one could be
+                * read-write, we can't use the tdb readonly.  Plus a
+                * read only tdb prohibits the all-record lock.
+                */
+               open_flags = O_RDWR;
+
+               ltdb->read_only = true;
+
        } else if (flags & LDB_FLG_DONT_CREATE_DB) {
+               /*
+                * This is used by ldbsearch to prevent creation of the database
+                * if the name is wrong
+                */
                open_flags = O_RDWR;
        } else {
+               /*
+                * This is the normal case
+                */
                open_flags = O_CREAT | O_RDWR;
        }
 
-       ltdb = talloc_zero(ldb, struct ltdb_private);
-       if (!ltdb) {
-               ldb_oom(ldb);
-               return LDB_ERR_OPERATIONS_ERROR;
-       }
-
        /* note that we use quite a large default hash size */
        ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000,
                                   tdb_flags, open_flags,
index a391606dd16e34c0c9188a2b3771ea471d5117a5..88cec3e8dceaa7f14c5499e264a98d034ee27bf5 100644 (file)
@@ -32,6 +32,8 @@ struct ltdb_private {
 
        bool warn_unindexed;
        bool warn_reindex;
+
+       bool read_only;
 };
 
 struct ltdb_context {