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 02:50:16 +0000 (04:50 +0200)
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>
lib/ldb/ldb_tdb/ldb_tdb.c
lib/ldb/ldb_tdb/ldb_tdb.h

index 9c8c77155c4885812c527dd435f29ce7e63cf35c..20796f2162dd2180721f8bc5a31053ddd2f52f88 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;
 }
 
@@ -1443,9 +1447,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;
@@ -1456,6 +1468,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) {
                ltdb->kv_ops->abort_write(ltdb);
index 2235bd47c98bb918cb6a996aed30b760d43d84af..28dd20915c779d88f533a2e500820620d6b55c64 100644 (file)
@@ -65,6 +65,8 @@ struct ltdb_private {
 
        bool read_only;
 
+       bool reindex_failed;
+
        const struct ldb_schema_syntax *GUID_index_syntax;
 
        /*