SoW-2020-0002: Trace Hit Counters: trigger error reporting integration
[lttng-tools.git] / src / lib / lttng-ctl / lttng-ctl.c
index 3f1ab9fdc4bb8f17abe91345355b11f3263d61e2..3216e5002efb950f00055ffa0f3b4e6f56f0ac6d 100644 (file)
@@ -19,6 +19,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <common/bytecode/bytecode.h>
 #include <common/common.h>
 #include <common/compat/string.h>
 #include <common/defaults.h>
@@ -45,7 +46,6 @@
 
 #include <common/filter/filter-ast.h>
 #include <common/filter/filter-parser.h>
-#include <common/filter/filter-bytecode.h>
 #include <common/filter/memstream.h>
 #include "lttng-ctl-helper.h"
 
@@ -2956,6 +2956,13 @@ int lttng_register_trigger(struct lttng_trigger *trigger)
        struct lttcomm_session_msg *message_lsm;
        struct lttng_payload message;
        struct lttng_payload reply;
+       struct lttng_trigger *reply_trigger = NULL;
+       enum lttng_domain_type domain_type;
+       struct lttng_credentials creds = {
+               .uid = LTTNG_OPTIONAL_INIT_VALUE(geteuid()),
+               .gid = LTTNG_OPTIONAL_INIT_UNSET,
+       };
+
 
        lttng_payload_init(&message);
        lttng_payload_init(&reply);
@@ -2965,11 +2972,39 @@ int lttng_register_trigger(struct lttng_trigger *trigger)
                goto end;
        }
 
+       if (!trigger->creds.uid.is_set) {
+               /* Use the client credentials as the trigger credentials */
+               lttng_trigger_set_credentials(trigger, &creds);
+       } else {
+               /*
+                * Validate that either the current trigger credentials and the
+                * client credentials are identical or that the current user is
+                * root. The root user can register, unregister triggers for
+                * himself and other users.
+                * This check is also present on the sessiond side, using the
+                * credentials passed on the socket. These check are all
+                * "safety" checks.
+                */
+               const struct lttng_credentials *trigger_creds =
+                               lttng_trigger_get_credentials(trigger);
+               if (!lttng_credentials_is_equal_uid(trigger_creds, &creds)) {
+                       if (lttng_credentials_get_uid(&creds) != 0) {
+                               ret = -LTTNG_ERR_EPERM;
+                               goto end;
+                       }
+               }
+       }
+
        if (!lttng_trigger_validate(trigger)) {
                ret = -LTTNG_ERR_INVALID_TRIGGER;
                goto end;
        }
 
+       domain_type = lttng_trigger_get_underlying_domain_type_restriction(
+                       trigger);
+
+       lsm.domain.type = domain_type;
+
        ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
        if (ret) {
                ret = -LTTNG_ERR_NOMEM;
@@ -2990,6 +3025,39 @@ int lttng_register_trigger(struct lttng_trigger *trigger)
 
        message_lsm->u.trigger.length = (uint32_t) message.buffer.size - sizeof(lsm);
 
+       if (getenv("LTTNG_REGISTER_TRIGGER_DRY_RUN")) {
+               /*
+                * Don't really send the request, just deserialize, validate
+                * that it is equal to the original trigger (to test
+                * serialization and deserialization), and return.
+                */
+               ssize_t sz;
+
+               struct lttng_payload_view pv = lttng_payload_view_from_payload(
+                               &message, sizeof(lsm), -1);
+               sz = lttng_trigger_create_from_payload(&pv, &reply_trigger);
+               if (sz != pv.buffer.size - sizeof(lsm)) {
+                       ret = -LTTNG_ERR_UNK;
+                       goto end;
+               }
+
+               if (!reply_trigger) {
+                       ret = -LTTNG_ERR_UNK;
+                       goto end;
+               }
+
+               if (!lttng_trigger_is_equal(trigger, reply_trigger)) {
+                       ret = -LTTNG_ERR_UNK;
+                       goto end;
+               }
+
+               /* Give it a dummy name. */
+               lttng_trigger_set_name(trigger, "yop");
+
+               ret = 0;
+               goto end;
+       }
+
        {
                struct lttng_payload_view message_view =
                                lttng_payload_view_from_payload(
@@ -3003,20 +3071,45 @@ int lttng_register_trigger(struct lttng_trigger *trigger)
                }
        }
 
+       {
+               struct lttng_payload_view reply_view =
+                               lttng_payload_view_from_payload(
+                                               &reply, 0, reply.buffer.size);
+
+               ret = lttng_trigger_create_from_payload(
+                               &reply_view, &reply_trigger);
+               if (ret < 0) {
+                       ret = -LTTNG_ERR_FATAL;
+                       goto end;
+               }
+       }
+
+       ret = lttng_trigger_assign_name(trigger, reply_trigger);
+       if (ret < 0) {
+               ret = -LTTNG_ERR_FATAL;
+               goto end;
+       }
+
        ret = 0;
 end:
        lttng_payload_reset(&message);
        lttng_payload_reset(&reply);
+       lttng_trigger_destroy(reply_trigger);
        return ret;
 }
 
-int lttng_unregister_trigger(struct lttng_trigger *trigger)
+int lttng_unregister_trigger(const struct lttng_trigger *trigger)
 {
        int ret;
        struct lttcomm_session_msg lsm;
        struct lttcomm_session_msg *message_lsm;
        struct lttng_payload message;
        struct lttng_payload reply;
+       struct lttng_trigger *copy = NULL;
+       struct lttng_credentials creds = {
+               .uid = LTTNG_OPTIONAL_INIT_VALUE(geteuid()),
+               .gid = LTTNG_OPTIONAL_INIT_UNSET,
+       };
 
        lttng_payload_init(&message);
        lttng_payload_init(&reply);
@@ -3026,7 +3119,36 @@ int lttng_unregister_trigger(struct lttng_trigger *trigger)
                goto end;
        }
 
-       if (!lttng_trigger_validate(trigger)) {
+       copy = lttng_trigger_copy(trigger);
+       if (!copy) {
+               ret = -LTTNG_ERR_UNK;
+               goto end;
+       }
+
+       if (!copy->creds.uid.is_set) {
+               /* Use the client credentials as the trigger credentials */
+               lttng_trigger_set_credentials(copy, &creds);
+       } else {
+               /*
+                * Validate that either the current trigger credentials and the
+                * client credentials are identical or that the current user is
+                * root. The root user can register, unregister triggers for
+                * himself and other users.
+                * This check is also present on the sessiond side, using the
+                * credentials passed on the socket. These check are all
+                * "safety" checks.
+                */
+               const struct lttng_credentials *trigger_creds =
+                               lttng_trigger_get_credentials(copy);
+               if (!lttng_credentials_is_equal_uid(trigger_creds, &creds)) {
+                       if (lttng_credentials_get_uid(&creds) != 0) {
+                               ret = -LTTNG_ERR_EPERM;
+                               goto end;
+                       }
+               }
+       }
+
+       if (!lttng_trigger_validate(copy)) {
                ret = -LTTNG_ERR_INVALID_TRIGGER;
                goto end;
        }
@@ -3046,7 +3168,7 @@ int lttng_unregister_trigger(struct lttng_trigger *trigger)
        */
        message_lsm = (struct lttcomm_session_msg *) message.buffer.data;
 
-       ret = lttng_trigger_serialize(trigger, &message);
+       ret = lttng_trigger_serialize(copy, &message);
        if (ret < 0) {
                ret = -LTTNG_ERR_UNK;
                goto end;
@@ -3074,11 +3196,58 @@ int lttng_unregister_trigger(struct lttng_trigger *trigger)
 
        ret = 0;
 end:
+       lttng_trigger_destroy(copy);
        lttng_payload_reset(&message);
        lttng_payload_reset(&reply);
        return ret;
 }
 
+/*
+ * Ask the session daemon for all registered triggers.
+ * Allocate a lttng_triggers collection.
+ * On error, returns a negative value.
+ */
+enum lttng_error_code lttng_list_triggers(struct lttng_triggers **triggers)
+{
+       int ret;
+       struct lttcomm_session_msg lsm;
+       struct lttng_payload_view lsm_view =
+                       lttng_payload_view_init_from_buffer(
+                               (const char *) &lsm, 0, sizeof(lsm));
+       struct lttng_triggers *local_triggers = NULL;
+       struct lttng_payload reply;
+
+       lttng_payload_init(&reply);
+
+       memset(&lsm, 0, sizeof(lsm));
+       lsm.cmd_type = LTTNG_LIST_TRIGGERS;
+
+       ret = lttng_ctl_ask_sessiond_payload(&lsm_view, &reply);
+       if (ret < 0) {
+               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 = -LTTNG_ERR_FATAL;
+                       goto end;
+               }
+       }
+
+       *triggers = local_triggers;
+       local_triggers = NULL;
+       ret = LTTNG_OK;
+end:
+       lttng_payload_reset(&reply);
+       lttng_triggers_destroy(local_triggers);
+       return ret;
+}
+
 /*
  * lib constructor.
  */
This page took 0.028 seconds and 5 git commands to generate.