From 9d7d73df7f7888a3ea8420662fa5aa2ef6e3bd82 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 2 May 2016 15:49:33 +0100 Subject: [PATCH 1/2] sway: fix IPC resource leak --- sway/ipc-server.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/ipc-server.c b/sway/ipc-server.c index a9325a81..05041ec1 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -138,6 +138,7 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { int flags; if ((flags=fcntl(client_fd, F_GETFD)) == -1 || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) { sway_log_errno(L_INFO, "Unable to set CLOEXEC on IPC client socket"); + close(client_fd); return 0; } From 08bef67f85273a0330e2392ab7dcfe0b1f42f870 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 2 May 2016 21:32:20 +0100 Subject: [PATCH 2/2] sway: refactor ipc_client_handle_command() This fixes a few mem leaks, as well as remove a false-positive error msg in IPC_GET_BAR_CONFIG --- sway/ipc-server.c | 62 ++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 05041ec1..13e1837a 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -292,6 +292,11 @@ void ipc_client_handle_command(struct ipc_client *client) { } char *buf = malloc(client->payload_length + 1); + if (!buf) { + sway_log_errno(L_INFO, "Out of memory"); + ipc_client_disconnect(client); + return; + } if (client->payload_length > 0) { ssize_t received = recv(client->fd, buf, client->payload_length, 0); @@ -303,28 +308,27 @@ void ipc_client_handle_command(struct ipc_client *client) { return; } } + buf[client->payload_length] = '\0'; switch (client->current_command) { case IPC_COMMAND: { - buf[client->payload_length] = '\0'; struct cmd_results *results = handle_command(buf); const char *json = cmd_results_to_json(results); char reply[256]; int length = snprintf(reply, sizeof(reply), "%s", json); ipc_send_reply(client, reply, (uint32_t) length); free_cmd_results(results); - break; + goto exit_cleanup; } + case IPC_SUBSCRIBE: { - buf[client->payload_length] = '\0'; struct json_object *request = json_tokener_parse(buf); if (request == NULL) { ipc_send_reply(client, "{\"success\": false}", 18); - ipc_client_disconnect(client); - free(buf); - return; + sway_log_errno(L_INFO, "Failed to read request"); + goto exit_cleanup; } // parse requested event types @@ -344,18 +348,18 @@ void ipc_client_handle_command(struct ipc_client *client) { #endif } else { ipc_send_reply(client, "{\"success\": false}", 18); - ipc_client_disconnect(client); json_object_put(request); - free(buf); - return; + sway_log_errno(L_INFO, "Failed to parse request"); + goto exit_cleanup; } } json_object_put(request); ipc_send_reply(client, "{\"success\": true}", 17); - break; + goto exit_cleanup; } + case IPC_GET_WORKSPACES: { json_object *workspaces = json_object_new_array(); @@ -363,8 +367,9 @@ void ipc_client_handle_command(struct ipc_client *client) { const char *json_string = json_object_to_json_string(workspaces); ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); json_object_put(workspaces); // free - break; + goto exit_cleanup; } + case IPC_GET_INPUTS: { json_object *inputs = json_object_new_array(); @@ -381,8 +386,9 @@ void ipc_client_handle_command(struct ipc_client *client) { const char *json_string = json_object_to_json_string(inputs); ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); json_object_put(inputs); - break; + goto exit_cleanup; } + case IPC_GET_OUTPUTS: { json_object *outputs = json_object_new_array(); @@ -390,8 +396,9 @@ void ipc_client_handle_command(struct ipc_client *client) { const char *json_string = json_object_to_json_string(outputs); ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); json_object_put(outputs); // free - break; + goto exit_cleanup; } + case IPC_GET_VERSION: { #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE @@ -419,29 +426,29 @@ void ipc_client_handle_command(struct ipc_client *client) { ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); json_object_put(json); // free free(full_version); - break; + goto exit_cleanup; } + case IPC_SWAY_GET_PIXELS: { char response_header[9]; memset(response_header, 0, sizeof(response_header)); - buf[client->payload_length] = '\0'; swayc_t *output = swayc_by_test(&root_container, output_by_name_test, buf); if (!output) { sway_log(L_ERROR, "IPC GET_PIXELS request with unknown output name"); ipc_send_reply(client, response_header, sizeof(response_header)); - break; + goto exit_cleanup; } struct get_pixels_request *req = malloc(sizeof(struct get_pixels_request)); req->client = client; req->output = output->handle; list_add(ipc_get_pixel_requests, req); wlc_output_schedule_render(output->handle); - break; + goto exit_cleanup; } + case IPC_GET_BAR_CONFIG: { - buf[client->payload_length] = '\0'; if (!buf[0]) { // Send list of configured bar IDs json_object *bars = json_object_new_array(); @@ -455,7 +462,6 @@ void ipc_client_handle_command(struct ipc_client *client) { json_object_put(bars); // free } else { // Send particular bar's details - buf[client->payload_length] = '\0'; struct bar_config *bar = NULL; int i; for (i = 0; i < config->bars->length; ++i) { @@ -468,23 +474,24 @@ void ipc_client_handle_command(struct ipc_client *client) { if (!bar) { const char *error = "{ \"success\": false, \"error\": \"No bar with that ID\" }"; ipc_send_reply(client, error, (uint32_t)strlen(error)); - break; + goto exit_cleanup; } json_object *json = ipc_json_describe_bar_config(bar); const char *json_string = json_object_to_json_string(json); ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); json_object_put(json); // free - break; } + goto exit_cleanup; } + default: sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); - ipc_client_disconnect(client); - return; + goto exit_cleanup; } - client->payload_length = 0; +exit_cleanup: free(buf); + return; } bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length) { @@ -499,13 +506,11 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay if (write(client->fd, data, ipc_header_size) == -1) { sway_log_errno(L_INFO, "Unable to send header to IPC client"); - ipc_client_disconnect(client); return false; } if (write(client->fd, payload, payload_length) == -1) { sway_log_errno(L_INFO, "Unable to send payload to IPC client"); - ipc_client_disconnect(client); return false; } @@ -654,7 +659,10 @@ void ipc_send_event(const char *json_string, enum ipc_command_type event) { continue; } client->current_command = event; - ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); + if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) { + sway_log_errno(L_INFO, "Unable to send reply to IPC client"); + ipc_client_disconnect(client); + } } }