trigger: expose trigger owner uid
[lttng-tools.git] / src / lib / lttng-ctl / lttng-ctl.c
index 4eb36a2612d952bb71d38e9cedcc4d70a47d6148..60dcdc7d33872cbf190e79b1dfe9e3385f72e545 100644 (file)
 #define _LGPL_SOURCE
 #include <assert.h>
 #include <grp.h>
-#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include <common/common.h>
+#include <common/compat/errno.h>
 #include <common/compat/string.h>
 #include <common/defaults.h>
 #include <common/dynamic-buffer.h>
@@ -2956,6 +2956,10 @@ int lttng_register_trigger(struct lttng_trigger *trigger)
        struct lttcomm_session_msg *message_lsm;
        struct lttng_payload message;
        struct lttng_payload reply;
+       const struct lttng_credentials user_creds = {
+               .uid = LTTNG_OPTIONAL_INIT_VALUE(geteuid()),
+               .gid = LTTNG_OPTIONAL_INIT_UNSET,
+       };
 
        lttng_payload_init(&message);
        lttng_payload_init(&reply);
@@ -2965,12 +2969,41 @@ int lttng_register_trigger(struct lttng_trigger *trigger)
                goto end;
        }
 
+       if (!trigger->creds.uid.is_set) {
+               /* Use the client's credentials as the trigger credentials. */
+               lttng_trigger_set_credentials(trigger, &user_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, &user_creds)) {
+                       if (lttng_credentials_get_uid(&user_creds) != 0) {
+                               ret = -LTTNG_ERR_EPERM;
+                               goto end;
+                       }
+               }
+       }
+
        if (!lttng_trigger_validate(trigger)) {
                ret = -LTTNG_ERR_INVALID_TRIGGER;
                goto end;
        }
 
-       lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
+       ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
+       if (ret) {
+               ret = -LTTNG_ERR_NOMEM;
+               goto end;
+       }
 
        /*
         * This is needed to populate the trigger object size for the command
@@ -3013,6 +3046,10 @@ int lttng_unregister_trigger(struct lttng_trigger *trigger)
        struct lttcomm_session_msg *message_lsm;
        struct lttng_payload message;
        struct lttng_payload reply;
+       const struct lttng_credentials user_creds = {
+               .uid = LTTNG_OPTIONAL_INIT_VALUE(geteuid()),
+               .gid = LTTNG_OPTIONAL_INIT_UNSET,
+       };
 
        lttng_payload_init(&message);
        lttng_payload_init(&reply);
@@ -3022,6 +3059,31 @@ int lttng_unregister_trigger(struct lttng_trigger *trigger)
                goto end;
        }
 
+       if (!trigger->creds.uid.is_set) {
+               /* Use the client's credentials as the trigger credentials. */
+               lttng_trigger_set_credentials(trigger, &user_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, &user_creds)) {
+                       if (lttng_credentials_get_uid(&user_creds) != 0) {
+                               ret = -LTTNG_ERR_EPERM;
+                               goto end;
+                       }
+               }
+       }
+
        if (!lttng_trigger_validate(trigger)) {
                ret = -LTTNG_ERR_INVALID_TRIGGER;
                goto end;
@@ -3030,7 +3092,11 @@ int lttng_unregister_trigger(struct lttng_trigger *trigger)
        memset(&lsm, 0, sizeof(lsm));
        lsm.cmd_type = LTTNG_UNREGISTER_TRIGGER;
 
-       lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
+       ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
+       if (ret) {
+               ret = -LTTNG_ERR_NOMEM;
+               goto end;
+       }
 
        /*
         * This is needed to populate the trigger object size for the command
This page took 0.024167 seconds and 4 git commands to generate.