ldb_tdb: Ensure we can not commit an index that is corrupt due to partial re-index
authorAndrew Bartlett <abartlet@samba.org>
Mon, 26 Mar 2018 03:01:13 +0000 (16:01 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 5 Apr 2018 08:59:31 +0000 (20:59 +1200)
The re-index traverse can abort part-way though and we need to ensure
that the transaction is never committed as that will leave an un-useable db.

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

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
(cherry picked from commit e481e4f30f4dc540f6f129b4f2faea48ee195673)

lib/ldb/ldb_tdb/ldb_tdb.c
lib/ldb/ldb_tdb/ldb_tdb.h

index 16e4b8ea26e8eef67e3faba993444ce947e8b1c3..a530a454b29f4f7c642daa7d55150029582c21af 100644 (file)
@@ -410,6 +410,10 @@ static int ltdb_modified(struct ldb_module *module, struct ldb_dn *dn)
                ret = ltdb_cache_reload(module);
        }
 
+       if (ret != LDB_SUCCESS) {
+               ltdb->reindex_failed = true;
+       }
+
        return ret;
 }
 
@@ -1404,9 +1408,17 @@ static int ltdb_start_trans(struct ldb_module *module)
 
        ltdb_index_transaction_start(module);
 
+       ltdb->reindex_failed = false;
+
        return LDB_SUCCESS;
 }
 
+/*
+ * Forward declaration to allow prepare_commit to in fact abort the
+ * transaction
+ */
+static int ltdb_del_trans(struct ldb_module *module);
+
 static int ltdb_prepare_commit(struct ldb_module *module)
 {
        int ret;
@@ -1417,6 +1429,24 @@ static int ltdb_prepare_commit(struct ldb_module *module)
                return LDB_SUCCESS;
        }
 
+       /*
+        * Check if the last re-index failed.
+        *
+        * This can happen if for example a duplicate value was marked
+        * unique.  We must not write a partial re-index into the DB.
+        */
+       if (ltdb->reindex_failed) {
+               /*
+                * We must instead abort the transaction so we get the
+                * old values and old index back
+                */
+               ltdb_del_trans(module);
+               ldb_set_errstring(ldb_module_get_ctx(module),
+                                 "Failure during re-index, so "
+                                 "transaction must be aborted.");
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
        ret = ltdb_index_transaction_commit(module);
        if (ret != LDB_SUCCESS) {
                tdb_transaction_cancel(ltdb->tdb);
index 7e182495928c7f91ee59443ce2963b0da2fe1111..9591ee59bf1711020937e0680a82ce423d57b9fe 100644 (file)
@@ -37,6 +37,8 @@ struct ltdb_private {
 
        bool read_only;
 
+       bool reindex_failed;
+
        const struct ldb_schema_syntax *GUID_index_syntax;
 };