X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fcmd.c;h=65553a538a1e62a6e570a5edbf127d741ef4c40e;hp=dc442035a3fe21e6b4c487a1007c9f05d1b38c56;hb=2463b7879c00298daa79744cdaae82ac061a4ed8;hpb=3a4595c2469472dee1656cde5f8882c2123efd3c;ds=inline diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index dc442035a..65553a538 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -29,6 +29,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -110,7 +117,7 @@ static int cmd_enable_event_internal(struct ltt_session *session, const struct lttng_domain *domain, char *channel_name, struct lttng_event *event, char *filter_expression, - struct lttng_filter_bytecode *filter, + struct lttng_bytecode *filter, struct lttng_event_exclusion *exclusion, int wpipe); @@ -2058,7 +2065,7 @@ static int _cmd_enable_event(struct ltt_session *session, const struct lttng_domain *domain, char *channel_name, struct lttng_event *event, char *filter_expression, - struct lttng_filter_bytecode *filter, + struct lttng_bytecode *filter, struct lttng_event_exclusion *exclusion, int wpipe, bool internal_event) { @@ -2141,7 +2148,7 @@ static int _cmd_enable_event(struct ltt_session *session, case LTTNG_EVENT_ALL: { char *filter_expression_a = NULL; - struct lttng_filter_bytecode *filter_a = NULL; + struct lttng_bytecode *filter_a = NULL; /* * We need to duplicate filter_expression and filter, @@ -2376,11 +2383,11 @@ static int _cmd_enable_event(struct ltt_session *session, { char *filter_expression_copy = NULL; - struct lttng_filter_bytecode *filter_copy = NULL; + struct lttng_bytecode *filter_copy = NULL; if (filter) { const size_t filter_size = sizeof( - struct lttng_filter_bytecode) + struct lttng_bytecode) + filter->len; filter_copy = zmalloc(filter_size); @@ -2456,7 +2463,7 @@ int cmd_enable_event(struct ltt_session *session, const struct lttng_domain *domain, char *channel_name, struct lttng_event *event, char *filter_expression, - struct lttng_filter_bytecode *filter, + struct lttng_bytecode *filter, struct lttng_event_exclusion *exclusion, int wpipe) { @@ -2473,7 +2480,7 @@ static int cmd_enable_event_internal(struct ltt_session *session, const struct lttng_domain *domain, char *channel_name, struct lttng_event *event, char *filter_expression, - struct lttng_filter_bytecode *filter, + struct lttng_bytecode *filter, struct lttng_event_exclusion *exclusion, int wpipe) { @@ -4256,8 +4263,59 @@ end: return ret; } +/* + * On success LTTNG_OK. On error, returns lttng_error code. + */ +static enum lttng_error_code prepare_trigger_object(struct lttng_trigger *trigger, const struct lttng_credentials *cmd_creds) +{ + enum lttng_error_code ret; + /* Internal object of the trigger might have to "generate" and + * "populate" internal field e.g filter bytecode + */ + struct lttng_condition *condition = NULL; + + condition = lttng_trigger_get_condition(trigger); + if (!condition) { + ret = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + + switch (lttng_condition_get_type(condition)) { + case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT: + { + struct lttng_event_rule *event_rule; + lttng_condition_event_rule_get_rule_mutable( + condition, &event_rule); + ret = lttng_event_rule_generate_filter_bytecode( + event_rule, lttng_credentials_get_uid(cmd_creds), lttng_credentials_get_gid(cmd_creds)); + if (ret != LTTNG_OK) { + goto end; + } + + /* Generate the capture bytecode set */ + ret = lttng_condition_event_rule_generate_capture_descriptor_bytecode_set( + condition, &trigger->capture_bytecode_set); + if (ret != LTTNG_OK) { + goto end; + } + + ret = LTTNG_OK; + break; + } + default: + { + ret = LTTNG_OK; + break; + } + } + +end: + return ret; +} + int cmd_register_trigger(struct command_ctx *cmd_ctx, int sock, - struct notification_thread_handle *notification_thread) + struct notification_thread_handle *notification_thread, + struct lttng_trigger **return_trigger) { int ret; size_t trigger_len; @@ -4265,8 +4323,8 @@ int cmd_register_trigger(struct command_ctx *cmd_ctx, int sock, struct lttng_trigger *trigger = NULL; struct lttng_payload trigger_payload; struct lttng_credentials cmd_creds = { - .uid = cmd_ctx->creds.uid, - .gid = cmd_ctx->creds.gid, + .uid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.uid), + .gid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.gid), }; lttng_payload_init(&trigger_payload); @@ -4314,13 +4372,118 @@ int cmd_register_trigger(struct command_ctx *cmd_ctx, int sock, } } - /* Set the trigger credential */ - lttng_trigger_set_credentials(trigger, &cmd_creds); + /* + * Validate the trigger credentials against the command credentials. + * Only the root user can register a trigger with non-matching + * credentials. + */ + if (!lttng_credentials_is_equal_uid( + lttng_trigger_get_credentials(trigger), + &cmd_creds)) { + if (lttng_credentials_get_uid(&cmd_creds) != 0) { + ERR("Trigger credentials do not match the command credentials"); + ret = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + } + + /* + * Since we return the trigger object, take a reference to it + * Caller is responsible for calling lttng_destroy_trigger on it. + * This thread does not OWN the trigger. + */ + lttng_trigger_get(trigger); + + /* Prepare internal trigger object if needed on reception. + * Handles also special treatment for certain internal object of the + * trigger (e.g uprobe event rule binary fd. + */ + ret = prepare_trigger_object(trigger, &cmd_creds); + if (ret != LTTNG_OK) { + goto end; + } /* Inform the notification thread */ ret = notification_thread_command_register_trigger(notification_thread, trigger); - /* Ownership of trigger was transferred. */ + if (ret != LTTNG_OK) { + goto end; + } + + /* Synchronize tracers, only if needed */ + /* TODO: maybe extract somewhere else */ + { + struct lttng_condition *condition = NULL; + condition = lttng_trigger_get_condition(trigger); + if (!condition) { + ret = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + + if (lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT) { + const struct lttng_event_rule *rule = NULL; + (void) lttng_condition_event_rule_get_rule(condition, &rule); + if (!rule) { + ret = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + if (lttng_event_rule_get_domain_type(rule) == LTTNG_DOMAIN_KERNEL) { + /* TODO: get the token value from the + * notification thread and only perform an + * enable and a disable.... This is NOT + * OPTIMIZED AT ALL + */ + ret = kernel_register_trigger(trigger, &cmd_creds); + if (ret != LTTNG_OK) { + enum lttng_error_code notif_thread_unregister_ret = + notification_thread_command_unregister_trigger( + notification_thread, + trigger); + if (notif_thread_unregister_ret != LTTNG_OK) { + ERR("Error unregistering notification thread trigger after kernel registration failure."); + } + goto end; + + } + } else { + /* TODO: get the token value from the + * notification thread and only perform an + * enable and a disable.... This is NOT + * OPTIMIZED AT ALL + */ + ust_app_global_update_all_tokens(); + /* Agent handling */ + if (lttng_event_rule_is_agent(rule)) { + struct agent *agt; + const char *pattern; + enum lttng_domain_type domain_type; + domain_type = lttng_event_rule_get_domain_type( + rule); + (void) lttng_event_rule_tracepoint_get_pattern( + rule, &pattern); + agt = trigger_find_agent(domain_type); + if (!agt) { + agt = agent_create(domain_type); + if (!agt) { + ret = LTTNG_ERR_NOMEM; + goto end; + } + agent_add(agt, trigger_agents_ht_by_domain); + } + + ret = trigger_agent_enable( + trigger, agt); + if (ret != LTTNG_OK) { + goto end; + } + } + } + } + } + + /* Return an image of the updated object to the client */ + *return_trigger = trigger; + /* Ownership of trigger was transferred to caller. */ trigger = NULL; end: lttng_trigger_destroy(trigger); @@ -4337,8 +4500,8 @@ int cmd_unregister_trigger(struct command_ctx *cmd_ctx, int sock, struct lttng_trigger *trigger = NULL; struct lttng_payload trigger_payload; struct lttng_credentials cmd_creds = { - .uid = cmd_ctx->creds.uid, - .gid = cmd_ctx->creds.gid, + .uid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.uid), + .gid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.gid), }; lttng_payload_init(&trigger_payload); @@ -4385,16 +4548,114 @@ int cmd_unregister_trigger(struct command_ctx *cmd_ctx, int sock, } } - lttng_trigger_set_credentials(trigger, &cmd_creds); + /* + * Validate the trigger credentials against the command credentials. + * Only the root user can unregister a trigger with non-matching + * credentials. + */ + if (!lttng_credentials_is_equal_uid( + lttng_trigger_get_credentials(trigger), + &cmd_creds)) { + if (lttng_credentials_get_uid(&cmd_creds) != 0) { + ERR("Trigger credentials do not match the command credentials"); + ret = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + } + + ret = prepare_trigger_object(trigger, &cmd_creds); + if (ret != LTTNG_OK) { + goto end; + } ret = notification_thread_command_unregister_trigger(notification_thread, trigger); + + /* Synchronize tracers, only if needed */ + /* TODO: maybe extract somewhere else */ + { + struct lttng_condition *condition = NULL; + condition = lttng_trigger_get_condition(trigger); + if (!condition) { + ret = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + + if (lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT) { + const struct lttng_event_rule *rule = NULL; + (void) lttng_condition_event_rule_get_rule(condition, &rule); + if (!rule) { + ret = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + if (lttng_event_rule_get_domain_type(rule) == LTTNG_DOMAIN_KERNEL) { + /* TODO: get the token value from the + * notification thread and only perform an + * enable and a disable.... This is NOT + * OPTIMIZED AT ALL + */ + ret = kernel_unregister_trigger(trigger); + } else { + /* TODO: get the token value from the + * notification thread and only perform an + * enable and a disable.... This is NOT + * OPTIMIZED AT ALL + */ + ust_app_global_update_all_tokens(); + if (lttng_event_rule_is_agent(rule)) { + struct agent *agt; + const char *pattern; + enum lttng_domain_type domain_type; + + domain_type = lttng_event_rule_get_domain_type( + rule); + (void) lttng_event_rule_tracepoint_get_pattern( + rule, &pattern); + + agt = trigger_find_agent(domain_type); + if (!agt) { + ret = LTTNG_ERR_UST_EVENT_NOT_FOUND; + goto end; + } + ret = trigger_agent_disable( + trigger, agt); + if (ret != LTTNG_OK) { + goto end; + } + } + } + } + } + end: lttng_trigger_destroy(trigger); lttng_payload_reset(&trigger_payload); return ret; } +int cmd_list_triggers(struct command_ctx *cmd_ctx, + struct notification_thread_handle *notification_thread, + struct lttng_triggers **return_triggers) +{ + int ret = 0; + enum lttng_error_code ret_code; + struct lttng_triggers *triggers = NULL; + + /* Get list of token trigger from the notification thread here */ + ret_code = notification_thread_command_list_triggers(notification_thread, cmd_ctx->creds.uid, &triggers); + if (ret_code != LTTNG_OK) { + ret = ret_code; + goto end; + } + + /* Return a "view" of the current triggers */ + *return_triggers = triggers; + triggers = NULL; + ret = LTTNG_OK; +end: + lttng_triggers_destroy(triggers); + return ret; +} /* * Send relayd sockets from snapshot output to consumer. Ignore request if the * snapshot output is *not* set with a remote destination.