From e55f8f307385e77ea561e7bbf9c76842ead9d7a3 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 6 Mar 2012 15:42:31 +0100 Subject: [PATCH] Add client references We have a use-after-free in the fio_handle_clients() loop. If we receive a QUIT command, we remove the client in fio_handle_client(). But fio_handle_clients() doesn't have a way to detect this, so it checks client->error after it has potentially been freed. Add a simple reference to get rid of this problem. Signed-off-by: Jens Axboe --- client.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/client.c b/client.c index 8c85d2b5..dd75882c 100644 --- a/client.c +++ b/client.c @@ -37,6 +37,7 @@ struct fio_client { char *hostname; int port; int fd; + unsigned int refs; char *name; @@ -119,8 +120,10 @@ static struct fio_client *find_client_by_fd(int fd) flist_for_each(entry, &client_hash[bucket]) { client = flist_entry(entry, struct fio_client, hash_list); - if (client->fd == fd) + if (client->fd == fd) { + client->refs++; return client; + } } return NULL; @@ -128,6 +131,11 @@ static struct fio_client *find_client_by_fd(int fd) static void remove_client(struct fio_client *client) { + assert(client->refs); + + if (--client->refs) + return; + dprint(FD_NET, "client: removed <%s>\n", client->hostname); flist_del(&client->list); @@ -149,6 +157,11 @@ static void remove_client(struct fio_client *client) sum_stat_clients--; } +static void put_client(struct fio_client *client) +{ + remove_client(client); +} + static void __fio_client_add_cmd_option(struct fio_client *client, const char *opt) { @@ -215,6 +228,7 @@ int fio_client_add(const char *hostname, void **cookie) return -1; client->fd = -1; + client->refs = 1; __fio_client_add_cmd_option(client, "fio"); @@ -1055,6 +1069,7 @@ int fio_handle_clients(void) retval = 1; } else if (client->error) retval = 1; + put_client(client); } } -- 2.25.1