summaryrefslogtreecommitdiffstats
path: root/source4
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2014-04-17 15:39:56 +1200
committerStefan Metzmacher <metze@samba.org>2014-05-06 13:36:20 +0200
commit401f555c28aee861385b75c371b5f44cded1d391 (patch)
treec8c5847841eb8e925ab79964112a4e0e24098580 /source4
parent543c5bf94187473271767ad782439abbfccda00d (diff)
downloadsamba-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.c93
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)