Save filter expressions as part of agent events
[lttng-tools.git] / src / bin / lttng-sessiond / cmd.c
index c26e5163c993f760885a5e1c7916d32b1397f284..10517fbc0f999ac8c7497f34e9756ec29a72cb6a 100644 (file)
 static pthread_mutex_t relayd_net_seq_idx_lock = PTHREAD_MUTEX_INITIALIZER;
 static uint64_t relayd_net_seq_idx;
 
+static int validate_event_name(const char *);
+static int validate_ust_event_name(const char *);
+static int cmd_enable_event_internal(struct ltt_session *session,
+               struct lttng_domain *domain,
+               char *channel_name, struct lttng_event *event,
+               char *filter_expression,
+               struct lttng_filter_bytecode *filter,
+               struct lttng_event_exclusion *exclusion,
+               int wpipe);
+
 /*
  * Create a session path used by list_lttng_sessions for the case that the
  * session consumer is on the network.
@@ -267,8 +277,7 @@ static int list_lttng_ust_global_events(char *channel_name,
 
        uchan = caa_container_of(&node->node, struct ltt_ust_channel, node.node);
 
-       nb_event += lttng_ht_get_count(uchan->events);
-
+       nb_event = lttng_ht_get_count(uchan->events);
        if (nb_event == 0) {
                ret = nb_event;
                goto error;
@@ -283,6 +292,11 @@ static int list_lttng_ust_global_events(char *channel_name,
        }
 
        cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent, node.node) {
+               if (uevent->internal) {
+                       /* This event should remain hidden from clients */
+                       nb_event--;
+                       continue;
+               }
                strncpy(tmp[i].name, uevent->attr.name, LTTNG_SYMBOL_NAME_LEN);
                tmp[i].name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
                tmp[i].enabled = uevent->enabled;
@@ -1132,11 +1146,16 @@ int cmd_disable_event(struct ltt_session *session, int domain,
        DBG("Disable event command for event \'%s\'", event->name);
 
        event_name = event->name;
+       if (validate_event_name(event_name)) {
+               ret = LTTNG_ERR_INVALID_EVENT_NAME;
+               goto error;
+       }
 
        /* Error out on unhandled search criteria */
        if (event->loglevel_type || event->loglevel != -1 || event->enabled
                        || event->pid || event->filter || event->exclusion) {
-               return LTTNG_ERR_UNK;
+               ret = LTTNG_ERR_UNK;
+               goto error;
        }
 
        rcu_read_lock();
@@ -1156,20 +1175,20 @@ int cmd_disable_event(struct ltt_session *session, int domain,
                 */
                if (ksess->has_non_default_channel && channel_name[0] == '\0') {
                        ret = LTTNG_ERR_NEED_CHANNEL_NAME;
-                       goto error;
+                       goto error_unlock;
                }
 
                kchan = trace_kernel_get_channel_by_name(channel_name, ksess);
                if (kchan == NULL) {
                        ret = LTTNG_ERR_KERN_CHAN_NOT_FOUND;
-                       goto error;
+                       goto error_unlock;
                }
 
                switch (event->type) {
                case LTTNG_EVENT_ALL:
                        ret = event_kernel_disable_event_all(kchan);
                        if (ret != LTTNG_OK) {
-                               goto error;
+                               goto error_unlock;
                        }
                        break;
                case LTTNG_EVENT_TRACEPOINT:    /* fall-through */
@@ -1182,7 +1201,7 @@ int cmd_disable_event(struct ltt_session *session, int domain,
                                        event_name);
                        }
                        if (ret != LTTNG_OK) {
-                               goto error;
+                               goto error_unlock;
                        }
                        break;
                case LTTNG_EVENT_PROBE:
@@ -1190,12 +1209,12 @@ int cmd_disable_event(struct ltt_session *session, int domain,
                case LTTNG_EVENT_FUNCTION_ENTRY:
                        ret = event_kernel_disable_event(kchan, event_name);
                        if (ret != LTTNG_OK) {
-                               goto error;
+                               goto error_unlock;
                        }
                        break;
                default:
                        ret = LTTNG_ERR_UNK;
-                       goto error;
+                       goto error_unlock;
                }
 
                kernel_wait_quiescent(kernel_tracer_fd);
@@ -1208,6 +1227,11 @@ int cmd_disable_event(struct ltt_session *session, int domain,
 
                usess = session->ust_session;
 
+               if (validate_ust_event_name(event_name)) {
+                       ret = LTTNG_ERR_INVALID_EVENT_NAME;
+                       goto error_unlock;
+               }
+
                /*
                 * If a non-default channel has been created in the
                 * session, explicitely require that -c chan_name needs
@@ -1215,26 +1239,26 @@ int cmd_disable_event(struct ltt_session *session, int domain,
                 */
                if (usess->has_non_default_channel && channel_name[0] == '\0') {
                        ret = LTTNG_ERR_NEED_CHANNEL_NAME;
-                       goto error;
+                       goto error_unlock;
                }
 
                uchan = trace_ust_find_channel_by_name(usess->domain_global.channels,
                                channel_name);
                if (uchan == NULL) {
                        ret = LTTNG_ERR_UST_CHAN_NOT_FOUND;
-                       goto error;
+                       goto error_unlock;
                }
 
                switch (event->type) {
                case LTTNG_EVENT_ALL:
                        ret = event_ust_disable_tracepoint(usess, uchan, event_name);
                        if (ret != LTTNG_OK) {
-                               goto error;
+                               goto error_unlock;
                        }
                        break;
                default:
                        ret = LTTNG_ERR_UNK;
-                       goto error;
+                       goto error_unlock;
                }
 
                DBG3("Disable UST event %s in channel %s completed", event_name,
@@ -1255,13 +1279,13 @@ int cmd_disable_event(struct ltt_session *session, int domain,
                        break;
                default:
                        ret = LTTNG_ERR_UNK;
-                       goto error;
+                       goto error_unlock;
                }
 
                agt = trace_ust_find_agent(usess, domain);
                if (!agt) {
                        ret = -LTTNG_ERR_UST_EVENT_NOT_FOUND;
-                       goto error;
+                       goto error_unlock;
                }
                /* The wild card * means that everything should be disabled. */
                if (strncmp(event->name, "*", 1) == 0 && strlen(event->name) == 1) {
@@ -1270,20 +1294,21 @@ int cmd_disable_event(struct ltt_session *session, int domain,
                        ret = event_agent_disable(usess, agt, event_name);
                }
                if (ret != LTTNG_OK) {
-                       goto error;
+                       goto error_unlock;
                }
 
                break;
        }
        default:
                ret = LTTNG_ERR_UND;
-               goto error;
+               goto error_unlock;
        }
 
        ret = LTTNG_OK;
 
-error:
+error_unlock:
        rcu_read_unlock();
+error:
        return ret;
 }
 
@@ -1409,14 +1434,36 @@ end:
        return ret;
 }
 
+static inline bool name_starts_with(const char *name, const char *prefix)
+{
+       const size_t max_cmp_len = min(strlen(prefix), LTTNG_SYMBOL_NAME_LEN);
 
-static int cmd_enable_event_internal(struct ltt_session *session,
-               struct lttng_domain *domain,
-               char *channel_name, struct lttng_event *event,
-               char *filter_expression,
-               struct lttng_filter_bytecode *filter,
-               struct lttng_event_exclusion *exclusion,
-               int wpipe);
+       return !strncmp(name, prefix, max_cmp_len);
+}
+
+/* Perform userspace-specific event name validation */
+static int validate_ust_event_name(const char *name)
+{
+       int ret = 0;
+
+       if (!name) {
+               ret = -1;
+               goto end;
+       }
+
+       /*
+        * Check name against all internal UST event component namespaces used
+        * by the agents.
+        */
+       if (name_starts_with(name, DEFAULT_JUL_EVENT_COMPONENT) ||
+               name_starts_with(name, DEFAULT_LOG4J_EVENT_COMPONENT) ||
+               name_starts_with(name, DEFAULT_PYTHON_EVENT_COMPONENT)) {
+               ret = -1;
+       }
+
+end:
+       return ret;
+}
 
 /*
  * Internal version of cmd_enable_event() with a supplemental
@@ -1624,6 +1671,21 @@ static int _cmd_enable_event(struct ltt_session *session,
                        assert(uchan);
                }
 
+               if (!internal_event) {
+                       /*
+                        * Ensure the event name is not reserved for internal
+                        * use.
+                        */
+                       ret = validate_ust_event_name(event->name);
+                       if (ret) {
+                               WARN("Userspace event name %s failed validation.",
+                                               event->name ?
+                                               event->name : "NULL");
+                               ret = LTTNG_ERR_INVALID_EVENT_NAME;
+                               goto error;
+                       }
+               }
+
                /* At this point, the session and channel exist on the tracer */
                ret = event_ust_enable_tracepoint(usess, uchan, event,
                                filter_expression, filter, exclusion,
@@ -1696,6 +1758,7 @@ static int _cmd_enable_event(struct ltt_session *session,
 
                {
                        struct lttng_filter_bytecode *filter_copy = NULL;
+                       char *filter_expression_copy = NULL;
 
                        if (filter) {
                                filter_copy = zmalloc(
@@ -1706,16 +1769,28 @@ static int _cmd_enable_event(struct ltt_session *session,
                                }
 
                                memcpy(filter_copy, filter,
-                                       sizeof(struct lttng_filter_bytecode)
-                                       + filter->len);
+                                      sizeof(struct lttng_filter_bytecode)
+                                      + filter->len);
+                       }
+
+                       if (filter_expression) {
+                               filter_expression_copy =
+                                               strdup(filter_expression);
+                               if (!filter_expression) {
+                                       ret = LTTNG_ERR_NOMEM;
+                                       goto error_free_copy;
+                               }
                        }
 
                        ret = cmd_enable_event_internal(session, &tmp_dom,
                                        (char *) default_chan_name,
-                                       &uevent, filter_expression, filter_copy,
-                                       NULL, wpipe);
-                       /* We have passed ownership */
-                       filter_expression = NULL;
+                                       &uevent, filter_expression_copy,
+                                       filter_copy, NULL, wpipe);
+                       filter_copy = NULL;
+                       filter_expression_copy = NULL;
+error_free_copy:
+                       free(filter_copy);
+                       free(filter_expression_copy);
                }
 
                if (ret != LTTNG_OK && ret != LTTNG_ERR_UST_EVENT_ENABLED) {
@@ -1724,10 +1799,12 @@ static int _cmd_enable_event(struct ltt_session *session,
 
                /* The wild card * means that everything should be enabled. */
                if (strncmp(event->name, "*", 1) == 0 && strlen(event->name) == 1) {
-                       ret = event_agent_enable_all(usess, agt, event, filter);
+                       ret = event_agent_enable_all(usess, agt, event, filter,
+                                       filter_expression);
                        filter = NULL;
                } else {
-                       ret = event_agent_enable(usess, agt, event, filter);
+                       ret = event_agent_enable(usess, agt, event, filter,
+                                       filter_expression);
                        filter = NULL;
                }
                if (ret != LTTNG_OK) {
This page took 0.055907 seconds and 4 git commands to generate.