[PATCH] Hold a read lock during the samba_dsdb stack init() phase

Andrew Bartlett abartlet at samba.org
Tue Apr 10 10:13:30 UTC 2018


The init_module hook is not locked by ldb, as the module may need to do
things, but due to the multi-db nature of Samba's stack we need to lock
it, so we do so in samba_dsdb.

This should/may avoid lock ordering issues that show up as
prepare_commit locking failures.  (These seemed to show up a lot while
I was trying to merge the LMDB patches, but I've seen them without so
they are unrelated). 

CI results will be here:

https://gitlab.com/catalyst-samba/samba/pipelines/20250607

Please review and push if the CI indicates.

Andrew Bartlett
-- 
Andrew Bartlett                       http://samba.org/~abartlet/
Authentication Developer, Samba Team  http://samba.org
Samba Developer, Catalyst IT          http://catalyst.net.nz/services/samba
-------------- next part --------------
From e0e3b5d32a8797e3f2f0fc94db4045bf709c111f Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Thu, 15 Mar 2018 13:42:17 +1300
Subject: [PATCH 01/10] ldb_wrap: Remove ldb_transaction_cancel_noerr from
 ldb_wrap_fork_hook()

Writing to a TDB, without locks (these are per-process) in a forked child is never going to
end well, if a transaction is open at this point we have bigger problems.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 lib/ldb-samba/ldb_wrap.c | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/lib/ldb-samba/ldb_wrap.c b/lib/ldb-samba/ldb_wrap.c
index 9959b04ed95..8c3bf6f7bf3 100644
--- a/lib/ldb-samba/ldb_wrap.c
+++ b/lib/ldb-samba/ldb_wrap.c
@@ -329,20 +329,11 @@ int samba_ldb_connect(struct ldb_context *ldb, struct loadparm_context *lp_ctx,
 }
 
 /*
-  when we fork() we need to make sure that any open ldb contexts have
-  any open transactions cancelled (ntdb databases doesn't need reopening,
-  as we don't use clear_if_first).
- */
+  call tdb_reopen_all() in case there is a TDB open so we are
+  not blocked from re-opening it inside ldb_tdb.
+*/
  void ldb_wrap_fork_hook(void)
 {
-	struct ldb_wrap *w;
-
-	for (w=ldb_wrap_list; w; w=w->next) {
-		if (ldb_transaction_cancel_noerr(w->ldb) != LDB_SUCCESS) {
-			smb_panic("Failed to cancel child transactions\n");
-		}
-	}
-
 	if (tdb_reopen_all(1) != 0) {
 		smb_panic("tdb_reopen_all failed\n");
 	}
-- 
2.14.3


From 673f89fd0141f2dd905b681a7f366688ee009d7c Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 9 Apr 2018 14:52:47 +1200
Subject: [PATCH 02/10] dsdb: Ensure to cancel the transaction if we fail to
 save the prefixMap

This rare error case forgot to call ldb_transaction_cancel()

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 source4/dsdb/repl/replicated_objects.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c
index 0c44960cf5f..4c8890f0553 100644
--- a/source4/dsdb/repl/replicated_objects.c
+++ b/source4/dsdb/repl/replicated_objects.c
@@ -921,6 +921,7 @@ WERROR dsdb_replicated_objects_commit(struct ldb_context *ldb,
 			}
 			DEBUG(0,("Failed to save updated prefixMap: %s\n",
 				 win_errstr(werr)));
+			ldb_transaction_cancel(ldb);
 			TALLOC_FREE(tmp_ctx);
 			return werr;
 		}
-- 
2.14.3


From 039c39076c18167567852be389dec1520dc314fc Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 9 Apr 2018 17:51:57 +1200
Subject: [PATCH 03/10] dsdb: Do not create a transaction in partition_init()

This will allow us to lock the databases for read during all of the Samba init
hooks.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 .../dsdb/samdb/ldb_modules/partition_metadata.c    | 59 ++++++++++------------
 1 file changed, 27 insertions(+), 32 deletions(-)

diff --git a/source4/dsdb/samdb/ldb_modules/partition_metadata.c b/source4/dsdb/samdb/ldb_modules/partition_metadata.c
index e3ad0d8c6c2..3e60393a2c9 100644
--- a/source4/dsdb/samdb/ldb_modules/partition_metadata.c
+++ b/source4/dsdb/samdb/ldb_modules/partition_metadata.c
@@ -319,38 +319,6 @@ int partition_metadata_init(struct ldb_module *module)
 		return ret;
 	}
 
-	/*
-	 * We need to fill in the sequence number from the DB, so we
-	 * need to get a lock over all the databases.  We only read
-	 * from the main partitions, but write to metadata so to avoid
-	 * lock ordering we just get a transaction over the lot.
-	 */
-	ret = partition_start_trans(module);
-	if (ret != LDB_SUCCESS) {
-		TALLOC_FREE(data->metadata);
-		return ret;
-	}
-
-	ret = partition_metadata_set_sequence_number(module);
-	if (ret != LDB_SUCCESS) {
-		TALLOC_FREE(data->metadata);
-		partition_del_trans(module);
-		return ret;
-	}
-
-	ret = partition_prepare_commit(module);
-	if (ret != LDB_SUCCESS) {
-		TALLOC_FREE(data->metadata);
-		partition_del_trans(module);
-		return ret;
-	}
-
-	ret = partition_end_trans(module);
-	if (ret != LDB_SUCCESS) {
-		/* Nothing much we can do */
-		TALLOC_FREE(data->metadata);
-	}
-
 	return ret;
 }
 
@@ -370,6 +338,13 @@ int partition_metadata_sequence_number(struct ldb_module *module, uint64_t *valu
 		return ret;
 	}
 
+	/*
+	 * This means we will give a 0 until the first write
+	 * tranaction, which is actually pretty reasonable.
+	 *
+	 * All modern databases will have the metadata.tdb from
+	 * the time of the first transaction in provision anyway.
+	 */
 	ret = partition_metadata_get_uint64(module,
 					    LDB_METADATA_SEQ_NUM,
 					    value,
@@ -410,6 +385,26 @@ int partition_metadata_sequence_number_increment(struct ldb_module *module, uint
 		return ret;
 	}
 
+	if (*value == 0) {
+		/*
+		 * We are in a transaction now, so we can get the
+		 * sequence number from the partitions.
+		 */
+		ret = partition_metadata_set_sequence_number(module);
+		if (ret != LDB_SUCCESS) {
+			TALLOC_FREE(data->metadata);
+			partition_del_trans(module);
+			return ret;
+		}
+
+		ret = partition_metadata_get_uint64(module,
+						    LDB_METADATA_SEQ_NUM,
+						    value, 0);
+		if (ret != LDB_SUCCESS) {
+			return ret;
+		}
+	}
+
 	(*value)++;
 	ret = partition_metadata_set_uint64(module, LDB_METADATA_SEQ_NUM, *value, false);
 	return ret;
-- 
2.14.3


From a3115cfe01da0f120fb715fc282caebbbf7d4960 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 9 Apr 2018 21:15:25 +1200
Subject: [PATCH 04/10] dsdb: Allow search before init() call in
 encrypted_secrets

Simply do not decrypt anything until the init call is run.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 source4/dsdb/samdb/ldb_modules/encrypted_secrets.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source4/dsdb/samdb/ldb_modules/encrypted_secrets.c b/source4/dsdb/samdb/ldb_modules/encrypted_secrets.c
index 87ec9e4eb53..ef69bb0831c 100644
--- a/source4/dsdb/samdb/ldb_modules/encrypted_secrets.c
+++ b/source4/dsdb/samdb/ldb_modules/encrypted_secrets.c
@@ -1365,7 +1365,7 @@ static int es_search_post_process(struct ldb_module *module,
 	/*
 	 * Decrypt any encrypted secret attributes
 	 */
-	if (data->encrypt_secrets) {
+	if (data && data->encrypt_secrets) {
 		int err = decrypt_secret_attributes(ldb, msg, data);
 		if (err !=  LDB_SUCCESS) {
 			return err;
-- 
2.14.3


From 422e548d8b62766eae66ec0487884b78589f1151 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 9 Apr 2018 21:59:01 +1200
Subject: [PATCH 05/10] dsdb: Wait until a transaction starts to call
 dsdb_schema_set_indices_and_attributes()

This avoids starting a transaction in schema_load_init() and allows it
to operate with a read lock held, which will avoid locking issues
(deadlock detected due to lock odering if we do not have a global
read lock).

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 source4/dsdb/samdb/ldb_modules/schema_load.c | 60 +++++++---------------------
 1 file changed, 15 insertions(+), 45 deletions(-)

diff --git a/source4/dsdb/samdb/ldb_modules/schema_load.c b/source4/dsdb/samdb/ldb_modules/schema_load.c
index 2099fac1159..55fb63a0f30 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_load.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_load.c
@@ -42,6 +42,12 @@ struct schema_load_private_data {
 	uint64_t schema_seq_num_read_lock;
 	uint64_t schema_seq_num_cache;
 	int tdb_seqnum;
+
+	/*
+	 * Please write out the updated schema on the next transaction
+	 * start
+	 */
+	bool need_write;
 };
 
 static int dsdb_schema_from_db(struct ldb_module *module,
@@ -495,7 +501,6 @@ static int schema_load_init(struct ldb_module *module)
 	struct ldb_context *ldb = ldb_module_get_ctx(module);
 	struct schema_load_private_data *private_data;
 	int ret;
-	bool need_write = false;
 
 	private_data = talloc_zero(module, struct schema_load_private_data);
 	if (private_data == NULL) {
@@ -510,50 +515,7 @@ static int schema_load_init(struct ldb_module *module)
 		return ret;
 	}
 
-	ret = schema_load(ldb, module, &need_write);
-
-	if (ret == LDB_SUCCESS && need_write) {
-		TALLOC_CTX *frame = talloc_stackframe();
-		struct dsdb_schema *schema = NULL;
-
-		ret = ldb_transaction_start(ldb);
-		if (ret != LDB_SUCCESS) {
-			ldb_debug_set(ldb, LDB_DEBUG_FATAL,
-				      "schema_load_init: transaction start failed");
-			return LDB_ERR_OPERATIONS_ERROR;
-		}
-
-		schema = dsdb_get_schema(ldb, frame);
-		if (schema == NULL) {
-			ldb_debug_set(ldb, LDB_DEBUG_FATAL,
-				      "schema_load_init: dsdb_get_schema failed");
-			ldb_transaction_cancel(ldb);
-			return LDB_ERR_OPERATIONS_ERROR;
-		}
-		ret = dsdb_schema_set_indices_and_attributes(ldb, schema,
-							     SCHEMA_WRITE);
-
-		TALLOC_FREE(frame);
-
-		if (ret != LDB_SUCCESS) {
-			ldb_asprintf_errstring(ldb, "Failed to write new "
-					       "@INDEXLIST and @ATTRIBUTES "
-					       "records for updated schema: %s",
-					       ldb_errstring(ldb));
-			ldb_transaction_cancel(ldb);
-			return ret;
-		}
-
-		ret = ldb_transaction_commit(ldb);
-		if (ret != LDB_SUCCESS) {
-			ldb_debug_set(ldb, LDB_DEBUG_FATAL,
-				      "schema_load_init: transaction commit failed");
-			return LDB_ERR_OPERATIONS_ERROR;
-		}
-	}
-
-
-	return ret;
+	return schema_load(ldb, module, &private_data->need_write);
 }
 
 static int schema_search(struct ldb_module *module, struct ldb_request *req)
@@ -586,6 +548,14 @@ static int schema_load_start_transaction(struct ldb_module *module)
 			      "schema_load_init: dsdb_get_schema failed");
 		return LDB_ERR_OPERATIONS_ERROR;
 	}
+
+	if (private_data->need_write) {
+		ret = dsdb_schema_set_indices_and_attributes(ldb,
+							     schema,
+							     SCHEMA_WRITE);
+		private_data->need_write = false;
+	}
+
 	private_data->in_transaction++;
 
 	return ret;
-- 
2.14.3


From 018e6d8689fd10536cd6352f94e0d78f307fafc9 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 10 Apr 2018 07:58:07 +1200
Subject: [PATCH 06/10] dsdb: Create rootdse_get_private_data()

This will get the private data on the first call, allowing that not to be
the init() hook.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 source4/dsdb/samdb/ldb_modules/rootdse.c | 63 ++++++++++++++++++++++++--------
 1 file changed, 48 insertions(+), 15 deletions(-)

diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c
index 0d486218c0b..0d4cbc60f24 100644
--- a/source4/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source4/dsdb/samdb/ldb_modules/rootdse.c
@@ -863,11 +863,46 @@ static int rootdse_search(struct ldb_module *module, struct ldb_request *req)
 	return ldb_next_request(module, down_req);
 }
 
+static struct rootdse_private_data *rootdse_get_private_data(struct ldb_module *module)
+{
+	void *priv = ldb_module_get_private(module);
+	struct rootdse_private_data *data = NULL;
+
+	if (priv != NULL) {
+		data = talloc_get_type_abort(priv,
+					     struct rootdse_private_data);
+	}
+
+	if (data != NULL) {
+		return data;
+	}
+
+	data = talloc_zero(module, struct rootdse_private_data);
+	if (data == NULL) {
+		return NULL;
+	}
+
+	data->num_controls = 0;
+	data->controls = NULL;
+	data->num_partitions = 0;
+	data->partitions = NULL;
+	data->block_anonymous = true;
+
+	ldb_module_set_private(module, data);
+	return data;
+}
+
+
 static int rootdse_register_control(struct ldb_module *module, struct ldb_request *req)
 {
-	struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(module), struct rootdse_private_data);
+	struct rootdse_private_data *priv =
+		rootdse_get_private_data(module);
 	char **list;
 
+	if (priv == NULL) {
+		return ldb_module_oom(module);
+	}
+
 	list = talloc_realloc(priv, priv->controls, char *, priv->num_controls + 1);
 	if (!list) {
 		return ldb_oom(ldb_module_get_ctx(module));
@@ -886,9 +921,14 @@ static int rootdse_register_control(struct ldb_module *module, struct ldb_reques
 
 static int rootdse_register_partition(struct ldb_module *module, struct ldb_request *req)
 {
-	struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(module), struct rootdse_private_data);
+	struct rootdse_private_data *priv =
+		rootdse_get_private_data(module);
 	struct ldb_dn **list;
 
+	if (priv == NULL) {
+		return ldb_module_oom(module);
+	}
+
 	list = talloc_realloc(priv, priv->partitions, struct ldb_dn *, priv->num_partitions + 1);
 	if (!list) {
 		return ldb_oom(ldb_module_get_ctx(module));
@@ -924,28 +964,21 @@ static int rootdse_request(struct ldb_module *module, struct ldb_request *req)
 static int rootdse_init(struct ldb_module *module)
 {
 	int ret;
-	struct ldb_context *ldb;
 	struct ldb_result *res;
-	struct rootdse_private_data *data;
 	const char *attrs[] = { "msDS-Behavior-Version", NULL };
 	const char *ds_attrs[] = { "dsServiceName", NULL };
 	TALLOC_CTX *mem_ctx;
 
-	ldb = ldb_module_get_ctx(module);
+	struct ldb_context *ldb
+		= ldb_module_get_ctx(module);
+
+	struct rootdse_private_data *data
+		= rootdse_get_private_data(module);
 
-	data = talloc_zero(module, struct rootdse_private_data);
 	if (data == NULL) {
-		return ldb_oom(ldb);
+		return ldb_module_oom(module);
 	}
 
-	data->num_controls = 0;
-	data->controls = NULL;
-	data->num_partitions = 0;
-	data->partitions = NULL;
-	data->block_anonymous = true;
-
-	ldb_module_set_private(module, data);
-
 	ldb_set_default_dns(ldb);
 
 	ret = ldb_next_init(module);
-- 
2.14.3


From 5ce631b7143dbf98729c80e137388816a9598fef Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 10 Apr 2018 07:54:20 +1200
Subject: [PATCH 07/10] dsdb: Move ldb_set_default_dns() into
 rootdse_get_private_data()

This call needs to be done at the very first chance, in this case
during the first call to the lock_read() hook, otherwise the
schema_data module can't find the schema.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 source4/dsdb/samdb/ldb_modules/rootdse.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c
index 0d4cbc60f24..751fe15d1a1 100644
--- a/source4/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source4/dsdb/samdb/ldb_modules/rootdse.c
@@ -867,6 +867,8 @@ static struct rootdse_private_data *rootdse_get_private_data(struct ldb_module *
 {
 	void *priv = ldb_module_get_private(module);
 	struct rootdse_private_data *data = NULL;
+	struct ldb_context *ldb
+		= ldb_module_get_ctx(module);
 
 	if (priv != NULL) {
 		data = talloc_get_type_abort(priv,
@@ -889,6 +891,9 @@ static struct rootdse_private_data *rootdse_get_private_data(struct ldb_module *
 	data->block_anonymous = true;
 
 	ldb_module_set_private(module, data);
+
+	ldb_set_default_dns(ldb);
+
 	return data;
 }
 
@@ -979,8 +984,6 @@ static int rootdse_init(struct ldb_module *module)
 		return ldb_module_oom(module);
 	}
 
-	ldb_set_default_dns(ldb);
-
 	ret = ldb_next_init(module);
 
 	if (ret != LDB_SUCCESS) {
-- 
2.14.3


From 020deca15b7d298b9841dbdb8a022b3d1200fa7c Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 10 Apr 2018 16:34:21 +1200
Subject: [PATCH 08/10] dsdb: Allow search before init() is called in
 extended_dn_out

This matches the earlier check of p && p->normalise.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 source4/dsdb/samdb/ldb_modules/extended_dn_out.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
index ad4603fbbb9..6a869d0c482 100644
--- a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
+++ b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
@@ -498,7 +498,7 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares,
 			continue;
 		}
 
-		if (p->normalise) {
+		if (p && p->normalise) {
 			/* If we are also in 'normalise' mode, then
 			 * fix the attribute names to be in the
 			 * correct case */
-- 
2.14.3


From ff1e52640dff3dd134d4abe155cb7ef5a14d08f0 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Mon, 9 Apr 2018 18:13:59 +1200
Subject: [PATCH 09/10] dsdb: ensure we take out a read lock during the
 dsdb_init

We have to also take it out in the partitions code when we load the
partition backends.

This ensures that the init handlers hold a whole-db lock just as the
search code does.

To ensure the locking count in schema_load is balanced, the
private data is now created in the first lock_read() call.

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 source4/dsdb/samdb/ldb_modules/partition.c      | 24 +++++++++++++++++++
 source4/dsdb/samdb/ldb_modules/partition_init.c | 15 +++---------
 source4/dsdb/samdb/ldb_modules/samba_dsdb.c     | 17 ++++++++++++--
 source4/dsdb/samdb/ldb_modules/schema_load.c    | 31 ++++++++++++-------------
 4 files changed, 57 insertions(+), 30 deletions(-)

diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c
index 37e714d6e1b..9fb1b9dee12 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.c
+++ b/source4/dsdb/samdb/ldb_modules/partition.c
@@ -1236,6 +1236,30 @@ int partition_read_lock(struct ldb_module *module)
 	 *   ordering
 	 */
 
+	if (data == NULL) {
+		TALLOC_CTX *mem_ctx = talloc_new(module);
+
+		data = talloc_zero(mem_ctx, struct partition_private_data);
+		if (data == NULL) {
+			talloc_free(mem_ctx);
+			return ldb_operr(ldb);
+		}
+
+		/*
+		 * When used from Samba4, this message is set by the
+		 * samba4 module, as a fixed value not read from the
+		 * DB.  This avoids listing modules in the DB
+		 */
+		data->forced_module_msg = talloc_get_type(
+			ldb_get_opaque(ldb,
+				       DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME),
+			struct ldb_message);
+
+		ldb_module_set_private(module, talloc_steal(module,
+							    data));
+		talloc_free(mem_ctx);
+	}
+
 	/*
 	 * This will lock the metadata partition (sam.ldb) and
 	 * will also call event loops, so we do it before we
diff --git a/source4/dsdb/samdb/ldb_modules/partition_init.c b/source4/dsdb/samdb/ldb_modules/partition_init.c
index 9a6ac0c05a9..9a8bb7e211d 100644
--- a/source4/dsdb/samdb/ldb_modules/partition_init.c
+++ b/source4/dsdb/samdb/ldb_modules/partition_init.c
@@ -863,18 +863,9 @@ int partition_init(struct ldb_module *module)
 		return ldb_operr(ldb);
 	}
 
-	data = talloc_zero(mem_ctx, struct partition_private_data);
-	if (data == NULL) {
-		return ldb_operr(ldb);
-	}
-
-	/* When used from Samba4, this message is set by the samba4
-	 * module, as a fixed value not read from the DB.  This avoids
-	 * listing modules in the DB */
-	data->forced_module_msg = talloc_get_type(
-		ldb_get_opaque(ldb,
-			       DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME),
-		struct ldb_message);
+	/* We actually got this during the read_lock call */
+	data = talloc_get_type_abort(ldb_module_get_private(module),
+				     struct partition_private_data);
 
 	/* This loads the partitions */
 	ret = partition_reload_if_required(module, data, NULL);
diff --git a/source4/dsdb/samdb/ldb_modules/samba_dsdb.c b/source4/dsdb/samdb/ldb_modules/samba_dsdb.c
index 2605c1e511e..54ec6a26068 100644
--- a/source4/dsdb/samdb/ldb_modules/samba_dsdb.c
+++ b/source4/dsdb/samdb/ldb_modules/samba_dsdb.c
@@ -249,7 +249,7 @@ static bool check_required_features(struct ldb_message_element *el)
 static int samba_dsdb_init(struct ldb_module *module)
 {
 	struct ldb_context *ldb = ldb_module_get_ctx(module);
-	int ret, len, i, j;
+	int ret, lock_ret, len, i, j;
 	TALLOC_CTX *tmp_ctx = talloc_new(module);
 	struct ldb_result *res;
 	struct ldb_message *rootdse_msg = NULL, *partition_msg;
@@ -627,7 +627,20 @@ static int samba_dsdb_init(struct ldb_module *module)
 	/* Set this as the 'next' module, so that we effectivly append it to module chain */
 	ldb_module_set_next(module, module_chain);
 
-	return ldb_next_init(module);
+	ret = ldb_next_read_lock(module);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+
+	ret = ldb_next_init(module);
+
+	lock_ret = ldb_next_read_unlock(module);
+
+	if (lock_ret != LDB_SUCCESS) {
+		return lock_ret;
+	}
+
+	return ret;
 }
 
 static const struct ldb_module_ops ldb_samba_dsdb_module_ops = {
diff --git a/source4/dsdb/samdb/ldb_modules/schema_load.c b/source4/dsdb/samdb/ldb_modules/schema_load.c
index 55fb63a0f30..4b2ea606fa7 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_load.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_load.c
@@ -499,17 +499,11 @@ static int schema_load(struct ldb_context *ldb,
 static int schema_load_init(struct ldb_module *module)
 {
 	struct ldb_context *ldb = ldb_module_get_ctx(module);
-	struct schema_load_private_data *private_data;
+	struct schema_load_private_data *private_data =
+		talloc_get_type_abort(ldb_module_get_private(module),
+				      struct schema_load_private_data);
 	int ret;
 
-	private_data = talloc_zero(module, struct schema_load_private_data);
-	if (private_data == NULL) {
-		return ldb_oom(ldb);
-	}
-	private_data->module = module;
-
-	ldb_module_set_private(module, private_data);
-
 	ret = ldb_next_init(module);
 	if (ret != LDB_SUCCESS) {
 		return ret;
@@ -625,11 +619,19 @@ static int schema_load_extended(struct ldb_module *module, struct ldb_request *r
 static int schema_read_lock(struct ldb_module *module)
 {
 	struct schema_load_private_data *private_data =
-		talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
+		talloc_get_type(ldb_module_get_private(module),
+				struct schema_load_private_data);
 	uint64_t schema_seq_num = 0;
 
 	if (private_data == NULL) {
-		return ldb_next_read_lock(module);
+		private_data = talloc_zero(module, struct schema_load_private_data);
+		if (private_data == NULL) {
+			return ldb_module_oom(module);
+		}
+
+		private_data->module = module;
+
+		ldb_module_set_private(module, private_data);
 	}
 
 	if (private_data->in_transaction == 0 &&
@@ -653,11 +655,8 @@ static int schema_read_lock(struct ldb_module *module)
 static int schema_read_unlock(struct ldb_module *module)
 {
 	struct schema_load_private_data *private_data =
-		talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
-
-	if (private_data == NULL) {
-		return ldb_next_read_unlock(module);
-	}
+		talloc_get_type_abort(ldb_module_get_private(module),
+				      struct schema_load_private_data);
 
 	if (private_data->in_transaction == 0 &&
 	    private_data->in_read_transaction == 1) {
-- 
2.14.3


From 5a7fef5ad455414eb7b1dd49005547c9560d5185 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet at samba.org>
Date: Tue, 10 Apr 2018 13:34:56 +1200
Subject: [PATCH 10/10] dsdb: Use talloc_get_type_abort() in
 schema_load_{start,end}_transaction

Signed-off-by: Andrew Bartlett <abartlet at samba.org>
---
 source4/dsdb/samdb/ldb_modules/schema_load.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/source4/dsdb/samdb/ldb_modules/schema_load.c b/source4/dsdb/samdb/ldb_modules/schema_load.c
index 4b2ea606fa7..3664d471707 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_load.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_load.c
@@ -525,7 +525,8 @@ static int schema_search(struct ldb_module *module, struct ldb_request *req)
 static int schema_load_start_transaction(struct ldb_module *module)
 {
 	struct schema_load_private_data *private_data =
-		talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
+		talloc_get_type_abort(ldb_module_get_private(module),
+				      struct schema_load_private_data);
 	struct ldb_context *ldb = ldb_module_get_ctx(module);
 	struct dsdb_schema *schema;
 	int ret;
@@ -558,7 +559,8 @@ static int schema_load_start_transaction(struct ldb_module *module)
 static int schema_load_end_transaction(struct ldb_module *module)
 {
 	struct schema_load_private_data *private_data =
-		talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
+		talloc_get_type_abort(ldb_module_get_private(module),
+				      struct schema_load_private_data);
 	struct ldb_context *ldb = ldb_module_get_ctx(module);
 
 	if (private_data->in_transaction == 0) {
-- 
2.14.3



More information about the samba-technical mailing list