s4:dsdb/schema: don't update the in memory schema->prefixmap without reloading the...
authorStefan Metzmacher <metze@samba.org>
Mon, 8 Aug 2016 09:22:13 +0000 (11:22 +0200)
committerJeremy Allison <jra@samba.org>
Wed, 10 Aug 2016 22:49:14 +0000 (00:49 +0200)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12128

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source4/dsdb/schema/schema_init.c
source4/torture/drs/unit/prefixmap_tests.c

index c1cf466493ae982253a3d24842da27245fd400b1..3fac3c13b84c29f9349d340d443795f61d48a65c 100644 (file)
@@ -276,6 +276,7 @@ WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *s
        uint32_t attid;
        TALLOC_CTX *mem_ctx;
        struct dsdb_schema_prefixmap *pfm;
+       struct dsdb_schema_prefixmap *orig_pfm = NULL;
 
        mem_ctx = talloc_new(ldb);
        W_ERROR_HAVE_NO_MEMORY(mem_ctx);
@@ -312,8 +313,11 @@ WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *s
                return status;
        }
 
-       talloc_unlink(schema, schema->prefixmap);
-       schema->prefixmap = talloc_steal(schema, pfm);
+       /*
+        * We temporary replcate schema->prefixmap.
+        */
+       orig_pfm = schema->prefixmap;
+       schema->prefixmap = pfm;
 
        /* Update prefixMap in ldb*/
        status = dsdb_write_prefixes_from_schema_to_ldb(mem_ctx, ldb, schema);
@@ -327,6 +331,13 @@ WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *s
        DEBUG(2,(__location__ " Added prefixMap %s - now have %u prefixes\n",
                 full_oid, schema->prefixmap->length));
 
+       /*
+        * We restore the original prefix map.
+        *
+        * The next schema reload should get an updated prefix map!
+        */
+       schema->prefixmap = orig_pfm;
+
        talloc_free(mem_ctx);
        return status;
 }
index 969d641af291fad3486ba423b3a2a3af587b942b..ec5fec5625cdcc04e27373356d12a2dbff6d7a57 100644 (file)
@@ -692,6 +692,7 @@ static bool torture_drs_unit_dsdb_create_prefix_mapping(struct torture_context *
        uint32_t i;
        struct dsdb_schema *schema;
        TALLOC_CTX *mem_ctx;
+       struct dsdb_schema_prefixmap *pfm_ldb = NULL;
 
        mem_ctx = talloc_new(tctx);
        torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
@@ -708,44 +709,58 @@ static bool torture_drs_unit_dsdb_create_prefix_mapping(struct torture_context *
        werr = dsdb_write_prefixes_from_schema_to_ldb(mem_ctx, priv->ldb_ctx, schema);
        torture_assert_werr_ok(tctx, werr, "dsdb_write_prefixes_from_schema_to_ldb() failed");
 
+       /* read from ldb what we have written */
+       werr = dsdb_read_prefixes_from_ldb(priv->ldb_ctx, mem_ctx, &pfm_ldb);
+       torture_assert_werr_ok(tctx, werr, "dsdb_read_prefixes_from_ldb() failed");
+       /* compare data written/read */
+       if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, pfm_ldb, true)) {
+               torture_fail(tctx, "pfm in LDB is different");
+       }
+       TALLOC_FREE(pfm_ldb);
+
        for (i = 0; i < ARRAY_SIZE(_prefixmap_test_data); i++) {
-               struct dsdb_schema_prefixmap *pfm_ldb;
                struct dsdb_schema_prefixmap *pfm_prev;
+               struct dsdb_schema_prefixmap *pfm_new;
+
+               pfm_prev = schema->prefixmap;
 
-               /* add ref to prefixMap so we can use it later */
-               pfm_prev = talloc_reference(schema, schema->prefixmap);
+               pfm_new = dsdb_schema_pfm_copy_shallow(schema, pfm_prev);
+               torture_assert(tctx, pfm_new != NULL, "dsdb_schema_pfm_copy_shallow() failed");
+
+               if (!_prefixmap_test_data[i].exists) {
+                       uint32_t attid;
+
+                       werr = dsdb_schema_pfm_make_attid(pfm_new,
+                                                         _prefixmap_test_data[i].oid,
+                                                         &attid);
+                       torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_make_attid() failed");
+               }
 
                /* call dsdb_create_prefix_mapping() and check result accordingly */
                werr = dsdb_create_prefix_mapping(priv->ldb_ctx, schema, _prefixmap_test_data[i].oid);
                torture_assert_werr_ok(tctx, werr, "dsdb_create_prefix_mapping() failed");
 
-               /* verify pfm has been altered or not if needed */
-               if (_prefixmap_test_data[i].exists) {
-                       torture_assert(tctx, pfm_prev == schema->prefixmap,
-                                      "schema->prefixmap has been reallocated!");
-                       if (!_torture_drs_pfm_compare_same(tctx, pfm_prev, schema->prefixmap, true)) {
-                               torture_fail(tctx, "schema->prefixmap has changed");
-                       }
-               } else {
-                       torture_assert(tctx, pfm_prev != schema->prefixmap,
-                                      "schema->prefixmap should be reallocated!");
-                       if (_torture_drs_pfm_compare_same(tctx, pfm_prev, schema->prefixmap, true)) {
-                               torture_fail(tctx, "schema->prefixmap should be changed");
-                       }
+               /*
+                * The prefix should not change, only on reload
+                */
+               torture_assert(tctx, pfm_prev == schema->prefixmap,
+                              "schema->prefixmap has been reallocated!");
+               if (!_torture_drs_pfm_compare_same(tctx, pfm_prev, schema->prefixmap, true)) {
+                       torture_fail(tctx, "schema->prefixmap has changed");
                }
 
                /* read from ldb what we have written */
                werr = dsdb_read_prefixes_from_ldb(priv->ldb_ctx, mem_ctx, &pfm_ldb);
                torture_assert_werr_ok(tctx, werr, "dsdb_read_prefixes_from_ldb() failed");
                /* compare data written/read */
-               if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, pfm_ldb, true)) {
-                       torture_fail(tctx, "schema->prefixmap and pfm in LDB are different");
+               if (!_torture_drs_pfm_compare_same(tctx, pfm_new, pfm_ldb, true)) {
+                       torture_fail(tctx, talloc_asprintf(tctx, "%u: pfm in LDB is different", i));
                }
                /* free mem for pfm read from LDB */
-               talloc_free(pfm_ldb);
+               TALLOC_FREE(pfm_ldb);
 
-               /* release prefixMap pointer */
-               talloc_unlink(schema, pfm_prev);
+               /* prepare for the next round */
+               schema->prefixmap = pfm_new;
        }
 
        talloc_free(mem_ctx);