From: Andrew Bartlett Date: Mon, 9 Apr 2018 06:13:59 +0000 (+1200) Subject: dsdb: ensure we take out a read lock during the dsdb_init X-Git-Tag: ldb-1.4.0~629 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=887b48c49328f7cede260923a33633096402a763;p=thirdparty%2Fsamba.git 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. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13379 Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- 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 cfd88fec467..e977e8b0ad5 100644 --- a/source4/dsdb/samdb/ldb_modules/schema_load.c +++ b/source4/dsdb/samdb/ldb_modules/schema_load.c @@ -498,17 +498,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; @@ -618,7 +612,14 @@ static int schema_read_lock(struct ldb_module *module) int ret; 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); } ret = ldb_next_read_lock(module); @@ -640,11 +641,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); private_data->in_read_transaction--;