trigger: implement listing of registered trigger
authorJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Thu, 23 Jan 2020 19:13:11 +0000 (14:13 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 20 Nov 2020 21:51:24 +0000 (16:51 -0500)
Each client have visibility over triggers matching its user id (uid).

The root user have visibility over all registered triggers.

Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: I3e5ae75939214ed85c376bea12f1e4b307d78976

include/lttng/trigger/trigger.h
src/bin/lttng-sessiond/client.c
src/bin/lttng-sessiond/cmd.c
src/bin/lttng-sessiond/cmd.h
src/bin/lttng-sessiond/notification-thread-commands.c
src/bin/lttng-sessiond/notification-thread-commands.h
src/bin/lttng-sessiond/notification-thread-events.c
src/common/sessiond-comm/sessiond-comm.h
src/lib/lttng-ctl/lttng-ctl.c

index a0c312ddd1e92e2efdb94c6affcbb942696198ff..b36ee13a286f0d1d785a83da0c1ec85031776c4f 100644 (file)
@@ -187,6 +187,19 @@ extern int lttng_register_trigger(struct lttng_trigger *trigger);
  */
 extern int lttng_unregister_trigger(struct lttng_trigger *trigger);
 
+/*
+ * List triggers for the current user.
+ *
+ * On success, a newly-allocated trigger set is returned.
+ *
+ * The trigger set must be destroyed by the caller (see
+ * lttng_triggers_destroy()).
+ *
+ * Returns LTTNG_OK on success, else a suitable LTTng error code.
+ */
+extern enum lttng_error_code lttng_list_triggers(
+               struct lttng_triggers **triggers);
+
 /*
  * Get a trigger from the set at a given index.
  *
index ecd31ea48b11159d56b3f350f15d58b40eb19114..faf5d579fde6fbb7affa61267babdce675f6d844 100644 (file)
@@ -801,6 +801,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock,
        case LTTNG_ROTATION_SET_SCHEDULE:
        case LTTNG_SESSION_LIST_ROTATION_SCHEDULES:
        case LTTNG_CLEAR_SESSION:
+       case LTTNG_LIST_TRIGGERS:
                need_domain = 0;
                break;
        default:
@@ -847,6 +848,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock,
        case LTTNG_DATA_PENDING:
        case LTTNG_ROTATE_SESSION:
        case LTTNG_ROTATION_GET_INFO:
+       case LTTNG_LIST_TRIGGERS:
                break;
        default:
                /* Setup lttng message with no payload */
@@ -867,6 +869,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock,
        case LTTNG_SAVE_SESSION:
        case LTTNG_REGISTER_TRIGGER:
        case LTTNG_UNREGISTER_TRIGGER:
+       case LTTNG_LIST_TRIGGERS:
                need_tracing_session = 0;
                break;
        default:
@@ -2185,6 +2188,44 @@ error_add_context:
                ret = cmd_clear_session(cmd_ctx->session, sock);
                break;
        }
+       case LTTNG_LIST_TRIGGERS:
+       {
+               struct lttng_triggers *return_triggers = NULL;
+               size_t original_payload_size;
+               size_t payload_size;
+
+               ret = setup_empty_lttng_msg(cmd_ctx);
+               if (ret) {
+                       ret = LTTNG_ERR_NOMEM;
+                       goto setup_error;
+               }
+
+               original_payload_size = cmd_ctx->reply_payload.buffer.size;
+
+               ret = cmd_list_triggers(cmd_ctx,
+                               notification_thread_handle, &return_triggers);
+               if (ret != LTTNG_OK) {
+                       goto error;
+               }
+
+               assert(return_triggers);
+               ret = lttng_triggers_serialize(
+                               return_triggers, &cmd_ctx->reply_payload);
+               lttng_triggers_destroy(return_triggers);
+               if (ret) {
+                       ERR("Failed to serialize triggers in reply to `list triggers` command");
+                       ret = LTTNG_ERR_NOMEM;
+                       goto error;
+               }
+
+               payload_size = cmd_ctx->reply_payload.buffer.size -
+                       original_payload_size;
+
+               update_lttng_msg(cmd_ctx, 0, payload_size);
+
+               ret = LTTNG_OK;
+               break;
+       }
        default:
                ret = LTTNG_ERR_UND;
                break;
index 39e824bdef7e4fc10fae81cafc8f2882d4a13e81..2f5a4e98c74978d8ac8d7480cb539bc595e2afd7 100644 (file)
@@ -4450,6 +4450,29 @@ end:
        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 the set of triggers from the notification thread. */
+       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_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.
index eebb5a317c78038e52692f00362faff89a93515b..d376aee1e45e81b68b0ffff289fdce36c19ffbbb 100644 (file)
@@ -147,6 +147,10 @@ int cmd_register_trigger(struct command_ctx *cmd_ctx, int sock,
 int cmd_unregister_trigger(struct command_ctx *cmd_ctx, int sock,
                struct notification_thread_handle *notification_thread_handle);
 
+int cmd_list_triggers(struct command_ctx *cmd_ctx,
+               struct notification_thread_handle *notification_thread_handle,
+               struct lttng_triggers **return_triggers);
+
 int cmd_rotate_session(struct ltt_session *session,
                struct lttng_rotate_session_return *rotate_return,
                bool quiet_rotation,
index 28ed0b339d16c07e9d65763ff572a39a6e830945..a434b08cf47966309dc759d485d5ea23ce805bb3 100644 (file)
@@ -270,6 +270,36 @@ end:
        return ret_code;
 }
 
+enum lttng_error_code notification_thread_command_list_triggers(
+               struct notification_thread_handle *handle,
+               uid_t uid,
+               struct lttng_triggers **triggers)
+{
+       int ret;
+       enum lttng_error_code ret_code;
+       struct notification_thread_command cmd = {};
+
+       assert(handle);
+       assert(triggers);
+
+       init_notification_thread_command(&cmd);
+
+       cmd.type = NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS;
+       cmd.parameters.list_triggers.uid = uid;
+
+       ret = run_command_wait(handle, &cmd);
+       if (ret) {
+               ret_code = LTTNG_ERR_UNK;
+               goto end;
+       }
+
+       ret_code = cmd.reply_code;
+       *triggers = cmd.reply.list_triggers.triggers;
+
+end:
+       return ret_code;
+}
+
 void notification_thread_command_quit(
                struct notification_thread_handle *handle)
 {
index c09ebea46f0c72a0e0acc1e42da590dd3b096423..3f883bf20fbda7129eedac4d16516a8c3c2f8d2b 100644 (file)
@@ -27,6 +27,7 @@ enum notification_thread_command_type {
        NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL,
        NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING,
        NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED,
+       NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS,
        NOTIFICATION_COMMAND_TYPE_QUIT,
        NOTIFICATION_COMMAND_TYPE_CLIENT_COMMUNICATION_UPDATE,
 };
@@ -64,6 +65,11 @@ struct notification_thread_command {
                        uint64_t trace_archive_chunk_id;
                        struct lttng_trace_archive_location *location;
                } session_rotation;
+               /* List triggers. */
+               struct {
+                       /* Credentials of the requesting user. */
+                       uid_t uid;
+               } list_triggers;
                /* Client communication update. */
                struct {
                        notification_client_id id;
@@ -72,6 +78,11 @@ struct notification_thread_command {
 
        } parameters;
 
+       union {
+               struct {
+                       struct lttng_triggers *triggers;
+               } list_triggers;
+       } reply;
        /* lttng_waiter on which to wait for command reply (optional). */
        struct lttng_waiter reply_waiter;
        enum lttng_error_code reply_code;
@@ -108,6 +119,24 @@ enum lttng_error_code notification_thread_command_session_rotation_completed(
                uint64_t trace_archive_chunk_id,
                struct lttng_trace_archive_location *location);
 
+/*
+ * Return the set of triggers visible to a given client.
+ *
+ * The trigger objects contained in the set are the actual trigger instances
+ * used by the notification subsystem (i.e. not a copy). Given that the command
+ * is only used to serialize the triggers, this is fine: the properties that
+ * are serialized are immutable over the lifetime of the triggers.
+ *
+ * Moreover, the lifetime of the trigger instances is protected through
+ * reference counting (references are held by the trigger set).
+ *
+ * The caller has the exclusive ownership of the returned trigger set.
+ */
+enum lttng_error_code notification_thread_command_list_triggers(
+               struct notification_thread_handle *handle,
+               uid_t client_uid,
+               struct lttng_triggers **triggers);
+
 void notification_thread_command_quit(
                struct notification_thread_handle *handle);
 
index 40450304297230b96cdf980afde1b516dc6c02c9..c318f833c87f6f2930b1090b384f31cea3d62013 100644 (file)
@@ -1984,6 +1984,61 @@ end:
        return ret;
 }
 
+static int handle_notification_thread_command_list_triggers(
+               struct notification_thread_handle *handle,
+               struct notification_thread_state *state,
+               uid_t client_uid,
+               struct lttng_triggers **triggers,
+               enum lttng_error_code *_cmd_result)
+{
+       int ret = 0;
+       enum lttng_error_code cmd_result = LTTNG_OK;
+       struct cds_lfht_iter iter;
+       struct lttng_trigger_ht_element *trigger_ht_element;
+       struct lttng_triggers *local_triggers = NULL;
+       const struct lttng_credentials *creds;
+
+       rcu_read_lock();
+
+       local_triggers = lttng_triggers_create();
+       if (!local_triggers) {
+               /* Not a fatal error. */
+               cmd_result = LTTNG_ERR_NOMEM;
+               goto end;
+       }
+
+       cds_lfht_for_each_entry(state->triggers_ht, &iter,
+                       trigger_ht_element, node) {
+               /*
+                * Only return the triggers to which the client has access.
+                * The root user has visibility over all triggers.
+                */
+               creds = lttng_trigger_get_credentials(trigger_ht_element->trigger);
+               if (client_uid != lttng_credentials_get_uid(creds) && client_uid != 0) {
+                       continue;
+               }
+
+               ret = lttng_triggers_add(local_triggers,
+                               trigger_ht_element->trigger);
+               if (ret < 0) {
+                       /* Not a fatal error. */
+                       ret = 0;
+                       cmd_result = LTTNG_ERR_NOMEM;
+                       goto end;
+               }
+       }
+
+       /* Transferring ownership to the caller. */
+       *triggers = local_triggers;
+       local_triggers = NULL;
+
+end:
+       rcu_read_unlock();
+       lttng_triggers_destroy(local_triggers);
+       *_cmd_result = cmd_result;
+       return ret;
+}
+
 static
 int condition_is_supported(struct lttng_condition *condition)
 {
@@ -2658,6 +2713,20 @@ int handle_notification_thread_command(
                                cmd->parameters.session_rotation.location,
                                &cmd->reply_code);
                break;
+       case NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS:
+       {
+               struct lttng_triggers *triggers = NULL;
+
+               ret = handle_notification_thread_command_list_triggers(
+                               handle,
+                               state,
+                               cmd->parameters.list_triggers.uid,
+                               &triggers,
+                               &cmd->reply_code);
+               cmd->reply.list_triggers.triggers = triggers;
+               ret = 0;
+               break;
+       }
        case NOTIFICATION_COMMAND_TYPE_QUIT:
                DBG("[notification-thread] Received quit command");
                cmd->reply_code = LTTNG_OK;
index fca331fe7511efdf84f384f90749cf3abfc4014f..d1a2bd97de18574b82344a6cc52fa169c4ec3a14 100644 (file)
@@ -106,6 +106,7 @@ enum lttcomm_sessiond_command {
        LTTNG_SESSION_LIST_ROTATION_SCHEDULES           = 48,
        LTTNG_CREATE_SESSION_EXT                        = 49,
        LTTNG_CLEAR_SESSION                             = 50,
+       LTTNG_LIST_TRIGGERS                             = 51,
 };
 
 enum lttcomm_relayd_command {
index 1c51eedc7814ff4879a844303b280200ae2e6fe2..91d6109e5383b77f8013d67aad18b374d4e131ba 100644 (file)
@@ -3173,6 +3173,52 @@ end:
        return ret;
 }
 
+/*
+ * Ask the session daemon for all registered triggers for the current user.
+ *
+ * Allocates and return an lttng_triggers set.
+ * On error, returns a suitable lttng_error_code.
+ */
+enum lttng_error_code lttng_list_triggers(struct lttng_triggers **triggers)
+{
+       int ret;
+       enum lttng_error_code ret_code = LTTNG_OK;
+       struct lttcomm_session_msg lsm = { .cmd_type = LTTNG_LIST_TRIGGERS };
+       struct lttng_triggers *local_triggers = NULL;
+       struct lttng_payload reply;
+       struct lttng_payload_view lsm_view =
+                       lttng_payload_view_init_from_buffer(
+                               (const char *) &lsm, 0, sizeof(lsm));
+
+       lttng_payload_init(&reply);
+
+       ret = lttng_ctl_ask_sessiond_payload(&lsm_view, &reply);
+       if (ret < 0) {
+               ret_code = (enum lttng_error_code) -ret;
+               goto end;
+       }
+
+       {
+               struct lttng_payload_view reply_view =
+                               lttng_payload_view_from_payload(
+                                               &reply, 0, reply.buffer.size);
+
+               ret = lttng_triggers_create_from_payload(
+                               &reply_view, &local_triggers);
+               if (ret < 0) {
+                       ret_code = LTTNG_ERR_FATAL;
+                       goto end;
+               }
+       }
+
+       *triggers = local_triggers;
+       local_triggers = NULL;
+end:
+       lttng_payload_reset(&reply);
+       lttng_triggers_destroy(local_triggers);
+       return ret_code;
+}
+
 /*
  * lib constructor.
  */
This page took 0.044832 seconds and 4 git commands to generate.