Prevent disable event on internal UST events
[lttng-tools.git] / src / bin / lttng-sessiond / cmd.c
index 50ff1632fb1bc3439e3517cdd66cc5129ed85146..e74e5a90299440a56a7c1e13b481965d8067c0d0 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.
@@ -268,8 +278,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;
@@ -284,6 +293,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;
@@ -1133,11 +1147,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();
@@ -1157,20 +1176,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 */
@@ -1183,7 +1202,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:
@@ -1191,12 +1210,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);
@@ -1209,6 +1228,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
@@ -1216,26 +1240,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,
@@ -1256,13 +1280,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) {
@@ -1271,20 +1295,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;
 }
 
@@ -1415,14 +1440,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
@@ -1630,6 +1677,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,7 +1758,7 @@ static int _cmd_enable_event(struct ltt_session *session,
                        default_chan_name = DEFAULT_PYTHON_CHANNEL_NAME;
                        break;
                default:
-                       /* The switch/case we are in should avoid this else big problem */
+                       /* The switch/case we are in makes this impossible */
                        assert(0);
                }
 
This page took 0.027522 seconds and 4 git commands to generate.