Fix: illegal memory access in cmd_snapshot_list_outputs
[lttng-tools.git] / src / bin / lttng-sessiond / cmd.c
index ba963ffc53c5e15f44ac756ce2842f9767d27ff5..201cbd183f8796f0bf716546562f31fd6b80b9b9 100644 (file)
@@ -187,6 +187,11 @@ static int get_ust_runtime_stats(struct ltt_session *session,
        int ret;
        struct ltt_ust_session *usess;
 
+       if (!discarded_events || !lost_packets) {
+               ret = -1;
+               goto end;
+       }
+
        usess = session->ust_session;
        assert(discarded_events);
        assert(lost_packets);
@@ -270,7 +275,7 @@ static void list_lttng_channels(enum lttng_domain_type domain,
                rcu_read_lock();
                cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
                                &iter.iter, uchan, node.node) {
-                       uint64_t discarded_events, lost_packets;
+                       uint64_t discarded_events = 0, lost_packets = 0;
 
                        strncpy(channels[i].name, uchan->name, LTTNG_SYMBOL_NAME_LEN);
                        channels[i].attr.overwrite = uchan->attr.overwrite;
@@ -753,12 +758,15 @@ static int add_uri_to_consumer(struct consumer_output *consumer,
                DBG2("Setting trace directory path from URI to %s", uri->dst.path);
                memset(consumer->dst.trace_path, 0,
                                sizeof(consumer->dst.trace_path));
-               strncpy(consumer->dst.trace_path, uri->dst.path,
-                               sizeof(consumer->dst.trace_path));
+               /* Explicit length checks for strcpy and strcat. */
+               if (strlen(uri->dst.path) + strlen(default_trace_dir)
+                               >= sizeof(consumer->dst.trace_path)) {
+                       ret = LTTNG_ERR_FATAL;
+                       goto error;
+               }
+               strcpy(consumer->dst.trace_path, uri->dst.path);
                /* Append default trace dir */
-               strncat(consumer->dst.trace_path, default_trace_dir,
-                               sizeof(consumer->dst.trace_path) -
-                               strlen(consumer->dst.trace_path) - 1);
+               strcat(consumer->dst.trace_path, default_trace_dir);
                /* Flag consumer as local. */
                consumer->type = CONSUMER_DST_LOCAL;
                break;
@@ -1805,7 +1813,7 @@ static int _cmd_enable_event(struct ltt_session *session,
                int wpipe, bool internal_event)
 {
        int ret, channel_created = 0;
-       struct lttng_channel *attr;
+       struct lttng_channel *attr = NULL;
 
        assert(session);
        assert(event);
@@ -1848,15 +1856,16 @@ static int _cmd_enable_event(struct ltt_session *session,
                                ret = LTTNG_ERR_FATAL;
                                goto error;
                        }
-                       strncpy(attr->name, channel_name, sizeof(attr->name));
+                       if (lttng_strncpy(attr->name, channel_name,
+                                       sizeof(attr->name))) {
+                               ret = LTTNG_ERR_INVALID;
+                               goto error;
+                       }
 
                        ret = cmd_enable_channel(session, domain, attr, wpipe);
                        if (ret != LTTNG_OK) {
-                               free(attr);
                                goto error;
                        }
-                       free(attr);
-
                        channel_created = 1;
                }
 
@@ -1985,14 +1994,16 @@ static int _cmd_enable_event(struct ltt_session *session,
                                ret = LTTNG_ERR_FATAL;
                                goto error;
                        }
-                       strncpy(attr->name, channel_name, sizeof(attr->name));
+                       if (lttng_strncpy(attr->name, channel_name,
+                                       sizeof(attr->name))) {
+                               ret = LTTNG_ERR_INVALID;
+                               goto error;
+                       }
 
                        ret = cmd_enable_channel(session, domain, attr, wpipe);
                        if (ret != LTTNG_OK) {
-                               free(attr);
                                goto error;
                        }
-                       free(attr);
 
                        /* Get the newly created channel reference back */
                        uchan = trace_ust_find_channel_by_name(
@@ -2167,6 +2178,7 @@ error:
        free(filter_expression);
        free(filter);
        free(exclusion);
+       free(attr);
        rcu_read_unlock();
        return ret;
 }
@@ -3344,10 +3356,18 @@ ssize_t cmd_snapshot_list_outputs(struct ltt_session *session,
                assert(output->consumer);
                list[idx].id = output->id;
                list[idx].max_size = output->max_size;
-               strncpy(list[idx].name, output->name, sizeof(list[idx].name));
+               if (lttng_strncpy(list[idx].name, output->name,
+                               sizeof(list[idx].name))) {
+                       ret = -LTTNG_ERR_INVALID;
+                       goto error;
+               }
                if (output->consumer->type == CONSUMER_DST_LOCAL) {
-                       strncpy(list[idx].ctrl_url, output->consumer->dst.trace_path,
-                                       sizeof(list[idx].ctrl_url));
+                       if (lttng_strncpy(list[idx].ctrl_url,
+                                       output->consumer->dst.trace_path,
+                                       sizeof(list[idx].ctrl_url))) {
+                               ret = -LTTNG_ERR_INVALID;
+                               goto error;
+                       }
                } else {
                        /* Control URI. */
                        ret = uri_to_str_url(&output->consumer->dst.net.control,
@@ -3588,13 +3608,6 @@ static int record_kernel_snapshot(struct ltt_kernel_session *ksess,
        assert(output);
        assert(session);
 
-       /* Get the datetime for the snapshot output directory. */
-       ret = utils_get_current_time_str("%Y%m%d-%H%M%S", output->datetime,
-                       sizeof(output->datetime));
-       if (!ret) {
-               ret = LTTNG_ERR_INVALID;
-               goto error;
-       }
 
        /*
         * Copy kernel session sockets so we can communicate with the right
@@ -3642,14 +3655,6 @@ static int record_ust_snapshot(struct ltt_ust_session *usess,
        assert(output);
        assert(session);
 
-       /* Get the datetime for the snapshot output directory. */
-       ret = utils_get_current_time_str("%Y%m%d-%H%M%S", output->datetime,
-                       sizeof(output->datetime));
-       if (!ret) {
-               ret = LTTNG_ERR_INVALID;
-               goto error;
-       }
-
        /*
         * Copy UST session sockets so we can communicate with the right
         * consumer for the snapshot record command.
@@ -3671,9 +3676,6 @@ static int record_ust_snapshot(struct ltt_ust_session *usess,
                case EINVAL:
                        ret = LTTNG_ERR_INVALID;
                        break;
-               case ENODATA:
-                       ret = LTTNG_ERR_SNAPSHOT_NODATA;
-                       break;
                default:
                        ret = LTTNG_ERR_SNAPSHOT_FAIL;
                        break;
@@ -3791,12 +3793,21 @@ int cmd_snapshot_record(struct ltt_session *session,
        unsigned int use_tmp_output = 0;
        struct snapshot_output tmp_output;
        unsigned int snapshot_success = 0;
+       char datetime[16];
 
        assert(session);
        assert(output);
 
        DBG("Cmd snapshot record for session %s", session->name);
 
+       /* Get the datetime for the snapshot output directory. */
+       ret = utils_get_current_time_str("%Y%m%d-%H%M%S", datetime,
+                       sizeof(datetime));
+       if (!ret) {
+               ret = LTTNG_ERR_INVALID;
+               goto error;
+       }
+
        /*
         * Permission denied to create an output if the session is not
         * set in no output mode.
@@ -3827,138 +3838,100 @@ int cmd_snapshot_record(struct ltt_session *session,
                }
                /* Use the global session count for the temporary snapshot. */
                tmp_output.nb_snapshot = session->snapshot.nb_snapshot;
+
+               /* Use the global datetime */
+               memcpy(tmp_output.datetime, datetime, sizeof(datetime));
                use_tmp_output = 1;
        }
 
-       if (session->kernel_session) {
-               struct ltt_kernel_session *ksess = session->kernel_session;
+       if (use_tmp_output) {
+               int64_t nb_packets_per_stream;
 
-               if (use_tmp_output) {
-                       int64_t nb_packets_per_stream;
+               nb_packets_per_stream = get_session_nb_packets_per_stream(session,
+                               tmp_output.max_size);
+               if (nb_packets_per_stream < 0) {
+                       ret = LTTNG_ERR_MAX_SIZE_INVALID;
+                       goto error;
+               }
 
-                       nb_packets_per_stream = get_session_nb_packets_per_stream(session,
-                                       tmp_output.max_size);
-                       if (nb_packets_per_stream < 0) {
-                               ret = LTTNG_ERR_MAX_SIZE_INVALID;
+               if (session->kernel_session) {
+                       ret = record_kernel_snapshot(session->kernel_session,
+                                       &tmp_output, session,
+                                       wait, nb_packets_per_stream);
+                       if (ret != LTTNG_OK) {
                                goto error;
                        }
-                       ret = record_kernel_snapshot(ksess, &tmp_output, session,
+               }
+
+               if (session->ust_session) {
+                       ret = record_ust_snapshot(session->ust_session,
+                                       &tmp_output, session,
                                        wait, nb_packets_per_stream);
                        if (ret != LTTNG_OK) {
                                goto error;
                        }
-                       snapshot_success = 1;
-               } else {
-                       struct snapshot_output *sout;
-                       struct lttng_ht_iter iter;
-
-                       rcu_read_lock();
-                       cds_lfht_for_each_entry(session->snapshot.output_ht->ht,
-                                       &iter.iter, sout, node.node) {
-                               int64_t nb_packets_per_stream;
-
-                               /*
-                                * Make a local copy of the output and assign the possible
-                                * temporary value given by the caller.
-                                */
-                               memset(&tmp_output, 0, sizeof(tmp_output));
-                               memcpy(&tmp_output, sout, sizeof(tmp_output));
-
-                               if (output->max_size != (uint64_t) -1ULL) {
-                                       tmp_output.max_size = output->max_size;
-                               }
+               }
 
-                               nb_packets_per_stream = get_session_nb_packets_per_stream(session,
-                                               tmp_output.max_size);
-                               if (nb_packets_per_stream < 0) {
-                                       ret = LTTNG_ERR_MAX_SIZE_INVALID;
-                                       goto error;
-                               }
+               snapshot_success = 1;
+       } else {
+               struct snapshot_output *sout;
+               struct lttng_ht_iter iter;
 
-                               /* Use temporary name. */
-                               if (*output->name != '\0') {
-                                       strncpy(tmp_output.name, output->name,
-                                                       sizeof(tmp_output.name));
-                               }
+               rcu_read_lock();
+               cds_lfht_for_each_entry(session->snapshot.output_ht->ht,
+                               &iter.iter, sout, node.node) {
+                       int64_t nb_packets_per_stream;
 
-                               tmp_output.nb_snapshot = session->snapshot.nb_snapshot;
+                       /*
+                        * Make a local copy of the output and assign the possible
+                        * temporary value given by the caller.
+                        */
+                       memset(&tmp_output, 0, sizeof(tmp_output));
+                       memcpy(&tmp_output, sout, sizeof(tmp_output));
 
-                               ret = record_kernel_snapshot(ksess, &tmp_output,
-                                               session, wait, nb_packets_per_stream);
-                               if (ret != LTTNG_OK) {
-                                       rcu_read_unlock();
-                                       goto error;
-                               }
-                               snapshot_success = 1;
+                       if (output->max_size != (uint64_t) -1ULL) {
+                               tmp_output.max_size = output->max_size;
                        }
-                       rcu_read_unlock();
-               }
-       }
-
-       if (session->ust_session) {
-               struct ltt_ust_session *usess = session->ust_session;
-
-               if (use_tmp_output) {
-                       int64_t nb_packets_per_stream;
 
                        nb_packets_per_stream = get_session_nb_packets_per_stream(session,
                                        tmp_output.max_size);
                        if (nb_packets_per_stream < 0) {
                                ret = LTTNG_ERR_MAX_SIZE_INVALID;
+                               rcu_read_unlock();
                                goto error;
                        }
-                       ret = record_ust_snapshot(usess, &tmp_output, session,
-                                       wait, nb_packets_per_stream);
-                       if (ret != LTTNG_OK) {
-                               goto error;
-                       }
-                       snapshot_success = 1;
-               } else {
-                       struct snapshot_output *sout;
-                       struct lttng_ht_iter iter;
-
-                       rcu_read_lock();
-                       cds_lfht_for_each_entry(session->snapshot.output_ht->ht,
-                                       &iter.iter, sout, node.node) {
-                               int64_t nb_packets_per_stream;
 
-                               /*
-                                * Make a local copy of the output and assign the possible
-                                * temporary value given by the caller.
-                                */
-                               memset(&tmp_output, 0, sizeof(tmp_output));
-                               memcpy(&tmp_output, sout, sizeof(tmp_output));
+                       /* Use temporary name. */
+                       if (*output->name != '\0') {
+                               strncpy(tmp_output.name, output->name,
+                                               sizeof(tmp_output.name));
+                       }
 
-                               if (output->max_size != (uint64_t) -1ULL) {
-                                       tmp_output.max_size = output->max_size;
-                               }
+                       tmp_output.nb_snapshot = session->snapshot.nb_snapshot;
+                       memcpy(tmp_output.datetime, datetime, sizeof(datetime));
 
-                               nb_packets_per_stream = get_session_nb_packets_per_stream(session,
-                                               tmp_output.max_size);
-                               if (nb_packets_per_stream < 0) {
-                                       ret = LTTNG_ERR_MAX_SIZE_INVALID;
+                       if (session->kernel_session) {
+                               ret = record_kernel_snapshot(session->kernel_session,
+                                               &tmp_output, session,
+                                               wait, nb_packets_per_stream);
+                               if (ret != LTTNG_OK) {
                                        rcu_read_unlock();
                                        goto error;
                                }
+                       }
 
-                               /* Use temporary name. */
-                               if (*output->name != '\0') {
-                                       strncpy(tmp_output.name, output->name,
-                                                       sizeof(tmp_output.name));
-                               }
-
-                               tmp_output.nb_snapshot = session->snapshot.nb_snapshot;
-
-                               ret = record_ust_snapshot(usess, &tmp_output, session,
+                       if (session->ust_session) {
+                               ret = record_ust_snapshot(session->ust_session,
+                                               &tmp_output, session,
                                                wait, nb_packets_per_stream);
                                if (ret != LTTNG_OK) {
                                        rcu_read_unlock();
                                        goto error;
                                }
-                               snapshot_success = 1;
                        }
-                       rcu_read_unlock();
+                       snapshot_success = 1;
                }
+               rcu_read_unlock();
        }
 
        if (snapshot_success) {
This page took 0.027476 seconds and 4 git commands to generate.