summaryrefslogtreecommitdiff
path: root/ctdb/server
diff options
context:
space:
mode:
authorMartin Schwenke <martin@meltin.net>2019-05-06 15:22:49 +1000
committerAmitay Isaacs <amitay@samba.org>2019-05-13 07:27:24 +0000
commit8663e0a64fbdb9ea16babbfe87d6f5d7a7b72bbd (patch)
treed05f61f48967d29574e0e5cd29d293f4e589fb6f /ctdb/server
parent21dc6f8e8d82f84e4afda355a48fbbd39c7fe800 (diff)
downloadsamba-8663e0a64fbdb9ea16babbfe87d6f5d7a7b72bbd.tar.gz
ctdb-daemon: Never use 0 as a client ID
ctdb_control_db_attach() and ctdb_control_db_detach() assume that any control with client ID 0 comes from another daemon and treat it specially. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13930 Signed-off-by: Martin Schwenke <martin@meltin.net> Reviewed-by: Amitay Isaacs <amitay@gmail.com>
Diffstat (limited to 'ctdb/server')
-rw-r--r--ctdb/server/ctdb_daemon.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/ctdb/server/ctdb_daemon.c b/ctdb/server/ctdb_daemon.c
index c5733bb2592..acb40bdb8df 100644
--- a/ctdb/server/ctdb_daemon.c
+++ b/ctdb/server/ctdb_daemon.c
@@ -1051,6 +1051,44 @@ static int ctdb_clientpid_destructor(struct ctdb_client_pid_list *client_pid)
return 0;
}
+static int get_new_client_id(struct reqid_context *idr,
+ struct ctdb_client *client,
+ uint32_t *out)
+{
+ uint32_t client_id;
+
+ client_id = reqid_new(idr, client);
+ /*
+ * Some places in the code (e.g. ctdb_control_db_attach(),
+ * ctdb_control_db_detach()) assign a special meaning to
+ * client_id 0. The assumption is that if client_id is 0 then
+ * the control has come from another daemon. Therefore, we
+ * should never return client_id == 0.
+ */
+ if (client_id == 0) {
+ /*
+ * Don't leak ID 0. This is safe because the ID keeps
+ * increasing. A test will be added to ensure that
+ * this doesn't change.
+ */
+ reqid_remove(idr, 0);
+
+ client_id = reqid_new(idr, client);
+ }
+
+ if (client_id == REQID_INVALID) {
+ return EINVAL;
+ }
+
+ if (client_id == 0) {
+ /* Every other ID must have been used and we can't use 0 */
+ reqid_remove(idr, 0);
+ return EINVAL;
+ }
+
+ *out = client_id;
+ return 0;
+}
static void ctdb_accept_client(struct tevent_context *ev,
struct tevent_fd *fde, uint16_t flags,
@@ -1094,7 +1132,15 @@ static void ctdb_accept_client(struct tevent_context *ev,
client->ctdb = ctdb;
client->fd = fd;
- client->client_id = reqid_new(ctdb->idr, client);
+
+ ret = get_new_client_id(ctdb->idr, client, &client->client_id);
+ if (ret != 0) {
+ DBG_ERR("Unable to get client ID (%d)\n", ret);
+ close(fd);
+ talloc_free(client);
+ return;
+ }
+
client->pid = peer_pid;
client_pid = talloc(client, struct ctdb_client_pid_list);