mirror of
https://github.com/samba-team/samba.git
synced 2025-01-18 06:04:06 +03:00
drepl: schema repl race condition fix
Adds final schema consistency check before committing changes. Aborts if corruption found. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12889 Signed-off-by: Aaron Haslett <aaronhaslett@catalyst.net.nz> Reviewed-by: Gary Lockyer <gary@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
parent
f460bb52ed
commit
1fd4cdfafa
@ -914,8 +914,10 @@ WERROR dsdb_replicated_objects_commit(struct ldb_context *ldb,
|
|||||||
}
|
}
|
||||||
talloc_free(ext_res);
|
talloc_free(ext_res);
|
||||||
|
|
||||||
/* Save our updated prefixMap */
|
/* Save our updated prefixMap and check the schema is good. */
|
||||||
if (working_schema) {
|
if (working_schema) {
|
||||||
|
struct ldb_result *ext_res_2;
|
||||||
|
|
||||||
werr = dsdb_write_prefixes_from_schema_to_ldb(working_schema,
|
werr = dsdb_write_prefixes_from_schema_to_ldb(working_schema,
|
||||||
ldb,
|
ldb,
|
||||||
working_schema);
|
working_schema);
|
||||||
@ -924,7 +926,9 @@ WERROR dsdb_replicated_objects_commit(struct ldb_context *ldb,
|
|||||||
if (used_global_schema) {
|
if (used_global_schema) {
|
||||||
dsdb_set_global_schema(ldb);
|
dsdb_set_global_schema(ldb);
|
||||||
} else if (cur_schema ) {
|
} else if (cur_schema ) {
|
||||||
dsdb_reference_schema(ldb, cur_schema, SCHEMA_MEMORY_ONLY);
|
dsdb_reference_schema(ldb,
|
||||||
|
cur_schema,
|
||||||
|
SCHEMA_MEMORY_ONLY);
|
||||||
}
|
}
|
||||||
DEBUG(0,("Failed to save updated prefixMap: %s\n",
|
DEBUG(0,("Failed to save updated prefixMap: %s\n",
|
||||||
win_errstr(werr)));
|
win_errstr(werr)));
|
||||||
@ -932,6 +936,33 @@ WERROR dsdb_replicated_objects_commit(struct ldb_context *ldb,
|
|||||||
TALLOC_FREE(tmp_ctx);
|
TALLOC_FREE(tmp_ctx);
|
||||||
return werr;
|
return werr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use dsdb_schema_from_db through dsdb extended to check we
|
||||||
|
* can load the schema currently sitting in the transaction.
|
||||||
|
* We need this check because someone might have written to
|
||||||
|
* the schema or prefixMap before we started the transaction,
|
||||||
|
* which may have caused corruption.
|
||||||
|
*/
|
||||||
|
ret = ldb_extended(ldb, DSDB_EXTENDED_SCHEMA_LOAD,
|
||||||
|
NULL, &ext_res_2);
|
||||||
|
|
||||||
|
if (ret != LDB_SUCCESS) {
|
||||||
|
if (used_global_schema) {
|
||||||
|
dsdb_set_global_schema(ldb);
|
||||||
|
} else if (cur_schema) {
|
||||||
|
dsdb_reference_schema(ldb, cur_schema, SCHEMA_MEMORY_ONLY);
|
||||||
|
}
|
||||||
|
DEBUG(0,("Corrupt schema write attempt detected, "
|
||||||
|
"aborting schema modification operation.\n"
|
||||||
|
"This probably happened due to bad timing of "
|
||||||
|
"another schema edit: %s (%s)\n",
|
||||||
|
ldb_errstring(ldb),
|
||||||
|
ldb_strerror(ret)));
|
||||||
|
ldb_transaction_cancel(ldb);
|
||||||
|
TALLOC_FREE(tmp_ctx);
|
||||||
|
return WERR_FOOBAR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ldb_transaction_prepare_commit(ldb);
|
ret = ldb_transaction_prepare_commit(ldb);
|
||||||
|
@ -552,26 +552,35 @@ static int schema_load_extended(struct ldb_module *module, struct ldb_request *r
|
|||||||
struct dsdb_schema *schema;
|
struct dsdb_schema *schema;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) {
|
if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_LOAD) == 0) {
|
||||||
|
|
||||||
|
ret = dsdb_schema_from_db(module, req, 0, &schema);
|
||||||
|
if (ret == LDB_SUCCESS) {
|
||||||
|
return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
} else if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) == 0) {
|
||||||
|
/* Force a refresh */
|
||||||
|
schema = dsdb_get_schema(ldb, NULL);
|
||||||
|
|
||||||
|
ret = dsdb_schema_set_indices_and_attributes(ldb,
|
||||||
|
schema,
|
||||||
|
SCHEMA_WRITE);
|
||||||
|
|
||||||
|
if (ret != LDB_SUCCESS) {
|
||||||
|
ldb_asprintf_errstring(ldb, "Failed to write new "
|
||||||
|
"@INDEXLIST and @ATTRIBUTES "
|
||||||
|
"records for updated schema: %s",
|
||||||
|
ldb_errstring(ldb));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ldb_next_request(module, req);
|
||||||
|
} else {
|
||||||
|
/* Pass to next module, the partition one should finish the chain */
|
||||||
return ldb_next_request(module, req);
|
return ldb_next_request(module, req);
|
||||||
}
|
}
|
||||||
/* Force a refresh */
|
|
||||||
schema = dsdb_get_schema(ldb, NULL);
|
|
||||||
|
|
||||||
ret = dsdb_schema_set_indices_and_attributes(ldb,
|
|
||||||
schema,
|
|
||||||
SCHEMA_WRITE);
|
|
||||||
|
|
||||||
if (ret != LDB_SUCCESS) {
|
|
||||||
ldb_asprintf_errstring(ldb, "Failed to write new "
|
|
||||||
"@INDEXLIST and @ATTRIBUTES "
|
|
||||||
"records for updated schema: %s",
|
|
||||||
ldb_errstring(ldb));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pass to next module, the partition one should finish the chain */
|
|
||||||
return ldb_next_request(module, req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int schema_read_lock(struct ldb_module *module)
|
static int schema_read_lock(struct ldb_module *module)
|
||||||
|
@ -272,6 +272,8 @@ struct dsdb_create_partition_exop {
|
|||||||
*/
|
*/
|
||||||
#define DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID "1.3.6.1.4.1.7165.4.4.2"
|
#define DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID "1.3.6.1.4.1.7165.4.4.2"
|
||||||
|
|
||||||
|
#define DSDB_EXTENDED_SCHEMA_LOAD "1.3.6.1.4.1.7165.4.4.10"
|
||||||
|
|
||||||
#define DSDB_EXTENDED_SCHEMA_UPGRADE_IN_PROGRESS_OID "1.3.6.1.4.1.7165.4.4.6"
|
#define DSDB_EXTENDED_SCHEMA_UPGRADE_IN_PROGRESS_OID "1.3.6.1.4.1.7165.4.4.6"
|
||||||
|
|
||||||
#define DSDB_OPENLDAP_DEREFERENCE_CONTROL "1.3.6.1.4.1.4203.666.5.16"
|
#define DSDB_OPENLDAP_DEREFERENCE_CONTROL "1.3.6.1.4.1.4203.666.5.16"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user