diff options
author | Andrew Bartlett <abartlet@samba.org> | 2014-04-17 15:39:56 +1200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2014-05-06 13:36:20 +0200 |
commit | 401f555c28aee861385b75c371b5f44cded1d391 (patch) | |
tree | c8c5847841eb8e925ab79964112a4e0e24098580 /source4 | |
parent | 543c5bf94187473271767ad782439abbfccda00d (diff) | |
download | samba-401f555c28aee861385b75c371b5f44cded1d391.tar.gz samba-401f555c28aee861385b75c371b5f44cded1d391.tar.xz samba-401f555c28aee861385b75c371b5f44cded1d391.zip |
dsdb: Do not permit nested event loops when in a transaction, use a nested event context
It is never safe to execute arbitary code inside a transaction - we
need to get in and get out, not run other events for the rest of the
server.
This patch avoids that by creating a private event loop during
transactions, so no unexpected operations fire, and returning the
original one when we finish it.
If an event fires during an LDB transaction, an unrelated operation
can occur during the transaction, and if the transaction were to be
cancelled, there would be a silent rollback (despite the client having
been indicated success).
Additionally, other processes could be called via IRPC that need to
operate on the database but are locked out due to the ongoing
transaction.
Andrew Bartlett
BUG: https://bugzilla.samba.org/show_bug.cgi?id=10582
Change-Id: I22322fc006e61d7291da17cdf6431416ebb7b30f
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Autobuild-User(master): Stefan Metzmacher <metze@samba.org>
Autobuild-Date(master): Tue May 6 13:36:20 CEST 2014 on sn-devel-104
Diffstat (limited to 'source4')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/rootdse.c | 93 |
1 files changed, 80 insertions, 13 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c index 87fbe6654d9..b13dc9e5c59 100644 --- a/source4/dsdb/samdb/ldb_modules/rootdse.c +++ b/source4/dsdb/samdb/ldb_modules/rootdse.c @@ -36,6 +36,7 @@ #include "librpc/gen_ndr/ndr_irpc_c.h" #include "lib/tsocket/tsocket.h" #include "cldap_server/cldap_server.h" +#include "lib/events/events.h" struct rootdse_private_data { unsigned int num_controls; @@ -43,6 +44,8 @@ struct rootdse_private_data { unsigned int num_partitions; struct ldb_dn **partitions; bool block_anonymous; + struct tevent_context *saved_ev; + struct tevent_context *private_ev; }; struct rootdse_context { @@ -1356,6 +1359,67 @@ static int rootdse_add(struct ldb_module *module, struct ldb_request *req) return LDB_ERR_NAMING_VIOLATION; } +static int rootdse_start_trans(struct ldb_module *module) +{ + int ret; + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct rootdse_private_data *data = talloc_get_type_abort(ldb_module_get_private(module), + struct rootdse_private_data); + ret = ldb_next_start_trans(module); + if (ret == LDB_SUCCESS) { + if (data->private_ev != NULL) { + return ldb_operr(ldb); + } + data->private_ev = s4_event_context_init(data); + if (data->private_ev == NULL) { + return ldb_operr(ldb); + } + data->saved_ev = ldb_get_event_context(ldb); + ldb_set_event_context(ldb, data->private_ev); + } + return ret; +} + +static int rootdse_end_trans(struct ldb_module *module) +{ + int ret; + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct rootdse_private_data *data = talloc_get_type_abort(ldb_module_get_private(module), + struct rootdse_private_data); + ret = ldb_next_end_trans(module); + if (data->saved_ev == NULL) { + return ldb_operr(ldb); + } + + if (data->private_ev != ldb_get_event_context(ldb)) { + return ldb_operr(ldb); + } + ldb_set_event_context(ldb, data->saved_ev); + data->saved_ev = NULL; + TALLOC_FREE(data->private_ev); + return ret; +} + +static int rootdse_del_trans(struct ldb_module *module) +{ + int ret; + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct rootdse_private_data *data = talloc_get_type_abort(ldb_module_get_private(module), + struct rootdse_private_data); + ret = ldb_next_del_trans(module); + if (data->saved_ev == NULL) { + return ldb_operr(ldb); + } + + if (data->private_ev != ldb_get_event_context(ldb)) { + return ldb_operr(ldb); + } + ldb_set_event_context(ldb, data->saved_ev); + data->saved_ev = NULL; + TALLOC_FREE(data->private_ev); + return ret; +} + struct fsmo_transfer_state { struct ldb_context *ldb; struct ldb_request *req; @@ -1383,7 +1447,7 @@ static void rootdse_fsmo_transfer_callback(struct tevent_req *treq) * Now that it is failed, start the transaction up * again so the wrappers can close it without additional error */ - ldb_next_start_trans(module); + rootdse_start_trans(module); ldb_module_done(req, NULL, NULL, LDB_ERR_UNAVAILABLE); return; } @@ -1393,7 +1457,7 @@ static void rootdse_fsmo_transfer_callback(struct tevent_req *treq) * Now that it is failed, start the transaction up * again so the wrappers can close it without additional error */ - ldb_next_start_trans(module); + rootdse_start_trans(module); ldb_module_done(req, NULL, NULL, LDB_ERR_UNAVAILABLE); return; } @@ -1402,7 +1466,7 @@ static void rootdse_fsmo_transfer_callback(struct tevent_req *treq) * Now that it is done, start the transaction up again so the * wrappers can close it without error */ - ret = ldb_next_start_trans(module); + ret = rootdse_start_trans(module); ldb_module_done(req, NULL, NULL, ret); } @@ -1443,7 +1507,7 @@ static int rootdse_become_master(struct ldb_module *module, * this gives the least supprise to this supprising action (as * we will never record anything done to this point */ - ldb_next_del_trans(module); + rootdse_del_trans(module); msg = imessaging_client_init(tmp_ctx, lp_ctx, ldb_get_event_context(ldb)); @@ -1612,15 +1676,18 @@ static int rootdse_extended(struct ldb_module *module, struct ldb_request *req) } static const struct ldb_module_ops ldb_rootdse_module_ops = { - .name = "rootdse", - .init_context = rootdse_init, - .search = rootdse_search, - .request = rootdse_request, - .add = rootdse_add, - .modify = rootdse_modify, - .rename = rootdse_rename, - .extended = rootdse_extended, - .del = rootdse_delete + .name = "rootdse", + .init_context = rootdse_init, + .search = rootdse_search, + .request = rootdse_request, + .add = rootdse_add, + .modify = rootdse_modify, + .rename = rootdse_rename, + .extended = rootdse_extended, + .del = rootdse_delete, + .start_transaction = rootdse_start_trans, + .end_transaction = rootdse_end_trans, + .del_transaction = rootdse_del_trans }; int ldb_rootdse_module_init(const char *version) |