X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fcmd.c;h=14c9bbd10993a415881cca30cb4de938d59bc205;hp=507937ca1259415915a0aa71849ea4645fcfa0ec;hb=670a26e4165562ab2dc5a16b9941f942e4f30996;hpb=989a08449dcb82204cd8caeb7841d5c20d32b475 diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 507937ca1..14c9bbd10 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -6,67 +6,69 @@ * */ -#include "bin/lttng-sessiond/session.h" + #define _LGPL_SOURCE #include #include +#include +#include #include #include -#include -#include -#include +#include #include -#include -#include -#include #include -#include +#include #include -#include -#include +#include #include +#include +#include +#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include #include -#include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include #include +#include +#include +#include #include -#include +#include +#include +#include "agent-thread.h" +#include "agent.h" +#include "buffer-registry.h" #include "channel.h" +#include "cmd.h" #include "consumer.h" +#include "event-notifier-error-accounting.h" #include "event.h" #include "health-sessiond.h" -#include "kernel.h" #include "kernel-consumer.h" +#include "kernel.h" #include "lttng-sessiond.h" -#include "utils.h" #include "lttng-syscall.h" -#include "agent.h" -#include "buffer-registry.h" -#include "notification-thread.h" #include "notification-thread-commands.h" +#include "notification-thread.h" #include "rotate.h" #include "rotation-thread.h" +#include "session.h" #include "timer.h" -#include "agent-thread.h" #include "tracker.h" - -#include "cmd.h" +#include "utils.h" /* Sleep for 100ms between each check for the shm path's deletion. */ #define SESSION_DESTROY_SHM_PATH_CHECK_DELAY_US 100000 @@ -4300,7 +4302,8 @@ enum lttng_error_code synchronize_tracer_notifier_register( struct lttng_trigger *trigger, const struct lttng_credentials *cmd_creds) { enum lttng_error_code ret_code; - struct lttng_condition *condition = lttng_trigger_get_condition(trigger); + const struct lttng_condition *condition = + lttng_trigger_get_const_condition(trigger); const char *trigger_name; uid_t trigger_owner; enum lttng_trigger_status trigger_status; @@ -4359,7 +4362,7 @@ enum lttng_error_code synchronize_tracer_notifier_register( goto end_unlock_session_list; } - agent_add(agt, trigger_agents_ht_by_domain); + agent_add(agt, the_trigger_agents_ht_by_domain); } ret_code = trigger_agent_enable(trigger, agt); @@ -4500,6 +4503,10 @@ enum lttng_error_code synchronize_tracer_notifier_unregister( switch (trigger_domain) { case LTTNG_DOMAIN_KERNEL: ret_code = kernel_unregister_event_notifier(trigger); + if (ret_code != LTTNG_OK) { + goto end_unlock_session_list; + } + break; case LTTNG_DOMAIN_UST: ust_app_global_update_all_event_notifier_rules(); @@ -4512,16 +4519,11 @@ enum lttng_error_code synchronize_tracer_notifier_unregister( struct agent *agt = agent_find_by_event_notifier_domain( trigger_domain); - if (!agt) { - agt = agent_create(trigger_domain); - if (!agt) { - ret_code = LTTNG_ERR_NOMEM; - goto end_unlock_session_list; - } - - agent_add(agt, trigger_agents_ht_by_domain); - } - + /* + * This trigger was never registered in the first place. Calling + * this function under those circumstances is an internal error. + */ + assert(agt); ret_code = trigger_agent_disable(trigger, agt); if (ret_code != LTTNG_OK) { goto end_unlock_session_list; @@ -4549,6 +4551,7 @@ enum lttng_error_code cmd_unregister_trigger(const struct lttng_credentials *cmd const char *trigger_name; uid_t trigger_owner; enum lttng_trigger_status trigger_status; + struct lttng_trigger *sessiond_trigger = NULL; trigger_status = lttng_trigger_get_name(trigger, &trigger_name); trigger_name = trigger_status == LTTNG_TRIGGER_STATUS_OK ? trigger_name : "(unnamed)"; @@ -4576,6 +4579,28 @@ enum lttng_error_code cmd_unregister_trigger(const struct lttng_credentials *cmd } } + /* Fetch the sessiond side trigger object. */ + ret_code = notification_thread_command_get_trigger( + notification_thread, trigger, &sessiond_trigger); + if (ret_code != LTTNG_OK) { + DBG("Failed to get trigger from notification thread during unregister: trigger name = '%s', trigger owner uid = %d, error code = %d", + trigger_name, (int) trigger_owner, ret_code); + goto end; + } + + assert(sessiond_trigger); + + /* + * From this point on, no matter what, consider the trigger + * unregistered. + * + * We set the unregistered state of the sessiond side trigger object in + * the client thread since we want to minimize the possibility of the + * notification thread being stalled due to a long execution of an + * action that required the trigger lock. + */ + lttng_trigger_set_as_unregistered(sessiond_trigger); + ret_code = notification_thread_command_unregister_trigger(notification_thread, trigger); if (ret_code != LTTNG_OK) { @@ -4600,6 +4625,7 @@ enum lttng_error_code cmd_unregister_trigger(const struct lttng_credentials *cmd } end: + lttng_trigger_put(sessiond_trigger); return ret_code; } @@ -4626,6 +4652,130 @@ end: lttng_triggers_destroy(triggers); return ret; } + +enum lttng_error_code cmd_execute_error_query(const struct lttng_credentials *cmd_creds, + const struct lttng_error_query *query, + struct lttng_error_query_results **_results, + struct notification_thread_handle *notification_thread) +{ + enum lttng_error_code ret_code; + const struct lttng_trigger *query_target_trigger; + struct lttng_action *query_target_action = NULL; + struct lttng_trigger *matching_trigger = NULL; + const char *trigger_name; + uid_t trigger_owner; + enum lttng_trigger_status trigger_status; + struct lttng_error_query_results *results = NULL; + + switch (lttng_error_query_get_target_type(query)) { + case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER: + query_target_trigger = lttng_error_query_trigger_borrow_target(query); + break; + case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION: + query_target_trigger = lttng_error_query_action_borrow_trigger_target( + query); + break; + default: + abort(); + } + + assert(query_target_trigger); + + ret_code = notification_thread_command_get_trigger(notification_thread, + query_target_trigger, &matching_trigger); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* No longer needed. */ + query_target_trigger = NULL; + + if (lttng_error_query_get_target_type(query) == + LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION) { + /* Get the sessiond-side version of the target action. */ + query_target_action = + lttng_error_query_action_borrow_action_target( + query, matching_trigger); + } + + trigger_status = lttng_trigger_get_name(matching_trigger, &trigger_name); + trigger_name = trigger_status == LTTNG_TRIGGER_STATUS_OK ? + trigger_name : "(unnamed)"; + trigger_status = lttng_trigger_get_owner_uid(matching_trigger, + &trigger_owner); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + results = lttng_error_query_results_create(); + if (!results) { + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + + DBG("Running \"execute error query\" command: trigger name = '%s', trigger owner uid = %d, command creds uid = %d", + trigger_name, (int) trigger_owner, + (int) lttng_credentials_get_uid(cmd_creds)); + + /* + * Validate the trigger credentials against the command credentials. + * Only the root user can target a trigger with non-matching + * credentials. + */ + if (!lttng_credentials_is_equal_uid( + lttng_trigger_get_credentials(matching_trigger), + cmd_creds)) { + if (lttng_credentials_get_uid(cmd_creds) != 0) { + ERR("Trigger credentials do not match the command credentials: trigger name = '%s', trigger owner uid = %d, command creds uid = %d", + trigger_name, (int) trigger_owner, + (int) lttng_credentials_get_uid(cmd_creds)); + ret_code = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + } + + switch (lttng_error_query_get_target_type(query)) { + case LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER: + trigger_status = lttng_trigger_add_error_results( + matching_trigger, results); + + switch (trigger_status) { + case LTTNG_TRIGGER_STATUS_OK: + break; + default: + ret_code = LTTNG_ERR_UNK; + goto end; + } + + break; + case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION: + { + const enum lttng_action_status action_status = + lttng_action_add_error_query_results( + query_target_action, results); + + switch (action_status) { + case LTTNG_ACTION_STATUS_OK: + break; + default: + ret_code = LTTNG_ERR_UNK; + goto end; + } + + break; + } + default: + abort(); + break; + } + + *_results = results; + results = NULL; + ret_code = LTTNG_OK; +end: + lttng_trigger_put(matching_trigger); + lttng_error_query_results_destroy(results); + return ret_code; +} + /* * Send relayd sockets from snapshot output to consumer. Ignore request if the * snapshot output is *not* set with a remote destination. @@ -5320,8 +5470,8 @@ int cmd_rotate_session(struct ltt_session *session, chunk_being_archived = NULL; if (!quiet_rotation) { ret = notification_thread_command_session_rotation_ongoing( - notification_thread_handle, - session->name, session->uid, session->gid, + the_notification_thread_handle, session->name, + session->uid, session->gid, ongoing_rotation_chunk_id); if (ret != LTTNG_OK) { ERR("Failed to notify notification thread that a session rotation is ongoing for session %s",