diff options
author | Martin Schwenke <martin@meltin.net> | 2019-05-06 15:22:49 +1000 |
---|---|---|
committer | Amitay Isaacs <amitay@samba.org> | 2019-05-13 07:27:24 +0000 |
commit | 8663e0a64fbdb9ea16babbfe87d6f5d7a7b72bbd (patch) | |
tree | d05f61f48967d29574e0e5cd29d293f4e589fb6f /ctdb/server | |
parent | 21dc6f8e8d82f84e4afda355a48fbbd39c7fe800 (diff) | |
download | samba-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.c | 48 |
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); |