Fix: unchecked buffer size for communication header
[lttng-tools.git] / src / bin / lttng-relayd / main.c
index 00292a02d6545db9d5b94cb4e08939e9b739a723..9f094f542f29b1ea97e01858ad9799b1b94254d2 100644 (file)
@@ -1,21 +1,11 @@
 /*
- * Copyright (C) 2012 Julien Desfossez <jdesfossez@efficios.com>
- *                      David Goulet <dgoulet@efficios.com>
- *               2013 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *               2015 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2012 Julien Desfossez <jdesfossez@efficios.com>
+ * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2 only,
- * as published by the Free Software Foundation.
+ * SPDX-License-Identifier: GPL-2.0-only
  *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #define _LGPL_SOURCE
@@ -240,7 +230,7 @@ static int set_option(int opt, const char *arg, const char *optname)
 
                        errno = 0;
                        v = strtoul(arg, NULL, 0);
-                       if (errno != 0 || !isdigit(arg[0])) {
+                       if (errno != 0 || !isdigit((unsigned char) arg[0])) {
                                ERR("Wrong value in --fd-pool-size parameter: %s", arg);
                                ret = -1;
                                goto end;
@@ -517,7 +507,7 @@ static int set_fd_pool_size(void)
                goto end;
        }
 
-       DBG("File descriptor pool size argument (%u) adjusted to %u to accomodate transient fd uses",
+       DBG("File descriptor pool size argument (%u) adjusted to %u to accommodates transient fd uses",
                        lttng_opt_fd_pool_size,
                        lttng_opt_fd_pool_size - DEFAULT_RELAYD_FD_POOL_SIZE_RESERVE);
        lttng_opt_fd_pool_size -= DEFAULT_RELAYD_FD_POOL_SIZE_RESERVE;
@@ -927,7 +917,11 @@ static int create_named_thread_poll_set(struct lttng_poll_event *events,
        }
 
        ret = fd_tracker_util_poll_create(the_fd_tracker,
-                       name, events, 1, LTTNG_CLOEXEC);
+                       name, events, 1, LTTNG_CLOEXEC);
+       if (ret) {
+               PERROR("Failed to create \"%s\" poll file descriptor", name);
+               goto error;
+       }
 
        /* Add quit pipe */
        ret = lttng_poll_add(events, thread_quit_pipe[0], LPOLLIN | LPOLLERR);
@@ -984,7 +978,7 @@ static int accept_sock(void *data, int *out_fd)
        struct lttcomm_sock **socks = data;
        struct lttcomm_sock *in_sock = socks[0];
 
-        socks[1] = in_sock->ops->accept(in_sock);
+       socks[1] = in_sock->ops->accept(in_sock);
        if (!socks[1]) {
                ret = -1;
                goto end;
@@ -1028,7 +1022,11 @@ static struct lttcomm_sock *relay_socket_create(struct lttng_uri *uri,
        ret = fd_tracker_open_unsuspendable_fd(the_fd_tracker, &sock_fd,
                        (const char **) (formated_name ? &formated_name : NULL),
                        1, create_sock, sock);
-       free(formated_name);
+       if (ret) {
+               PERROR("Failed to open \"%s\" relay socket",
+                               formated_name ?: "Unknown");
+               goto error;
+       }
        DBG("Listening on %s socket %d", name, sock->fd);
 
        ret = sock->ops->bind(sock);
@@ -1043,12 +1041,14 @@ static struct lttcomm_sock *relay_socket_create(struct lttng_uri *uri,
 
        }
 
+       free(formated_name);
        return sock;
 
 error:
        if (sock) {
                lttcomm_destroy_sock(sock);
        }
+       free(formated_name);
        return NULL;
 }
 
@@ -1060,7 +1060,7 @@ struct lttcomm_sock *accept_relayd_sock(struct lttcomm_sock *listening_sock,
        struct lttcomm_sock *socks[2] = { listening_sock, NULL };
        struct lttcomm_sock *new_sock = NULL;
 
-        ret = fd_tracker_open_unsuspendable_fd(
+       ret = fd_tracker_open_unsuspendable_fd(
                        the_fd_tracker, &out_fd,
                        (const char **) &name,
                        1, accept_sock, &socks);
@@ -1085,6 +1085,7 @@ static void *relay_thread_listener(void *data)
 
        DBG("[thread] Relay listener started");
 
+       rcu_register_thread();
        health_register(health_relayd, HEALTH_RELAYD_TYPE_LISTENER);
 
        health_code_update();
@@ -1268,6 +1269,7 @@ error_sock_control:
                ERR("Health error occurred in %s", __func__);
        }
        health_unregister(health_relayd);
+       rcu_unregister_thread();
        DBG("Relay listener thread cleanup complete");
        lttng_relay_stop_threads();
        return NULL;
@@ -1630,7 +1632,8 @@ static int relay_add_stream(const struct lttcomm_relayd_hdr *recv_hdr,
                        group_by_session_path_name =
                                        backward_compat_group_by_session(
                                                        path_name,
-                                                       session->session_name);
+                                                       session->session_name,
+                                                       session->creation_time.value);
                        if (!group_by_session_path_name) {
                                ERR("Failed to apply group by session to stream of session %" PRIu64,
                                                session->id);
@@ -1958,7 +1961,7 @@ static int relay_recv_metadata(const struct lttcomm_relayd_hdr *recv_hdr,
 
        packet_view = lttng_buffer_view_from_view(payload,
                        sizeof(metadata_payload_header), metadata_payload_size);
-       if (!packet_view.data) {
+       if (!lttng_buffer_view_is_valid(&packet_view)) {
                ERR("Invalid metadata packet length announced by header");
                ret = -1;
                goto end_put;
@@ -2664,7 +2667,6 @@ static int relay_create_trace_chunk(const struct lttcomm_relayd_hdr *recv_hdr,
        struct lttcomm_relayd_create_trace_chunk *msg;
        struct lttcomm_relayd_generic_reply reply = {};
        struct lttng_buffer_view header_view;
-       struct lttng_buffer_view chunk_name_view;
        struct lttng_trace_chunk *chunk = NULL, *published_chunk = NULL;
        enum lttng_error_code reply_code = LTTNG_OK;
        enum lttng_trace_chunk_status chunk_status;
@@ -2683,7 +2685,7 @@ static int relay_create_trace_chunk(const struct lttcomm_relayd_hdr *recv_hdr,
        }
 
        header_view = lttng_buffer_view_from_view(payload, 0, sizeof(*msg));
-       if (!header_view.data) {
+       if (!lttng_buffer_view_is_valid(&header_view)) {
                ERR("Failed to receive payload of chunk creation command");
                ret = -1;
                goto end_no_reply;
@@ -2724,16 +2726,25 @@ static int relay_create_trace_chunk(const struct lttcomm_relayd_hdr *recv_hdr,
                reply_code = LTTNG_ERR_NOMEM;
                goto end;
        }
+       lttng_trace_chunk_set_fd_tracker(chunk, the_fd_tracker);
 
        if (msg->override_name_length) {
                const char *name;
+               const struct lttng_buffer_view chunk_name_view =
+                               lttng_buffer_view_from_view(payload,
+                                               sizeof(*msg),
+                                               msg->override_name_length);
+
+               if (!lttng_buffer_view_is_valid(&chunk_name_view)) {
+                       ERR("Invalid payload of chunk creation command (protocol error): buffer too short for expected name length");
+                       ret = -1;
+                       reply_code = LTTNG_ERR_INVALID;
+                       goto end;
+               }
 
-               chunk_name_view = lttng_buffer_view_from_view(payload,
-                               sizeof(*msg),
-                               msg->override_name_length);
                name = chunk_name_view.data;
-               if (!name || name[msg->override_name_length - 1]) {
-                       ERR("Failed to receive payload of chunk creation command");
+               if (name[msg->override_name_length - 1]) {
+                       ERR("Invalid payload of chunk creation command (protocol error): name is not null-terminated");
                        ret = -1;
                        reply_code = LTTNG_ERR_INVALID;
                        goto end;
@@ -2868,7 +2879,7 @@ static int relay_close_trace_chunk(const struct lttcomm_relayd_hdr *recv_hdr,
        }
 
        header_view = lttng_buffer_view_from_view(payload, 0, sizeof(*msg));
-       if (!header_view.data) {
+       if (!lttng_buffer_view_is_valid(&header_view)) {
                ERR("Failed to receive payload of chunk close command");
                ret = -1;
                goto end_no_reply;
@@ -2941,7 +2952,7 @@ static int relay_close_trace_chunk(const struct lttcomm_relayd_hdr *recv_hdr,
                                new_path);
                if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
                        ret = -1;
-                       goto end;
+                       goto end_unlock_session;
                }
                session->ongoing_rotation = false;
        }
@@ -2959,7 +2970,7 @@ static int relay_close_trace_chunk(const struct lttcomm_relayd_hdr *recv_hdr,
                chunk_status = lttng_trace_chunk_rename_path(chunk, old_path);
                if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
                        ret = -1;
-                       goto end;
+                       goto end_unlock_session;
                }
        }
        chunk_status = lttng_trace_chunk_set_close_timestamp(
@@ -3101,20 +3112,20 @@ static int relay_trace_chunk_exists(const struct lttcomm_relayd_hdr *recv_hdr,
        bool chunk_exists;
 
        if (!session || !conn->version_check_done) {
-               ERR("Trying to close a trace chunk before version check");
+               ERR("Trying to check for the existance of a trace chunk before version check");
                ret = -1;
                goto end_no_reply;
        }
 
        if (session->major == 2 && session->minor < 11) {
-               ERR("Chunk close command is unsupported before 2.11");
+               ERR("Chunk exists command is unsupported before 2.11");
                ret = -1;
                goto end_no_reply;
        }
 
        header_view = lttng_buffer_view_from_view(payload, 0, sizeof(*msg));
-       if (!header_view.data) {
-               ERR("Failed to receive payload of chunk close command");
+       if (!lttng_buffer_view_is_valid(&header_view)) {
+               ERR("Failed to receive payload of chunk exists command");
                ret = -1;
                goto end_no_reply;
        }
@@ -3165,7 +3176,7 @@ static int relay_get_configuration(const struct lttcomm_relayd_hdr *recv_hdr,
        uint64_t result_flags = 0;
 
        header_view = lttng_buffer_view_from_view(payload, 0, sizeof(*msg));
-       if (!header_view.data) {
+       if (!lttng_buffer_view_is_valid(&header_view)) {
                ERR("Failed to receive payload of chunk close command");
                ret = -1;
                goto end_no_reply;
This page took 0.026407 seconds and 4 git commands to generate.