Fix: unchecked buffer size for communication header
[lttng-tools.git] / src / bin / lttng-sessiond / cmd.c
index b1b22012c2701ff8e8b3c2accf9be27674353786..39e824bdef7e4fc10fae81cafc8f2882d4a13e81 100644 (file)
@@ -3107,10 +3107,22 @@ enum lttng_error_code cmd_create_session(struct command_ctx *cmd_ctx, int sock,
                        &payload,
                        0,
                        cmd_ctx->lsm.u.create_session.home_dir_size);
+       if (cmd_ctx->lsm.u.create_session.home_dir_size > 0 &&
+                       !lttng_buffer_view_is_valid(&home_dir_view)) {
+               ERR("Invalid payload in \"create session\" command: buffer too short to contain home directory");
+               ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+               goto error;
+       }
+
        session_descriptor_view = lttng_buffer_view_from_dynamic_buffer(
                        &payload,
                        cmd_ctx->lsm.u.create_session.home_dir_size,
                        cmd_ctx->lsm.u.create_session.session_descriptor_size);
+       if (!lttng_buffer_view_is_valid(&session_descriptor_view)) {
+               ERR("Invalid payload in \"create session\" command: buffer too short to contain session descriptor");
+               ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+               goto error;
+       }
 
        ret = lttng_session_descriptor_create_from_buffer(
                        &session_descriptor_view, &session_descriptor);
@@ -3715,7 +3727,7 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions,
                /*
                 * Only list the sessions the user can control.
                 */
-               if (!session_access_ok(session, uid, gid) ||
+               if (!session_access_ok(session, uid) ||
                                session->destroyed) {
                        session_put(session);
                        continue;
@@ -4257,7 +4269,8 @@ end:
 }
 
 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 +4278,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,12 +4327,41 @@ 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;
+               }
+       }
 
-       /* Inform the notification thread */
+       /*
+        * A reference to the trigger is acquired by the notification thread.
+        * It is safe to return the same trigger to the caller since it the
+        * other user holds a reference.
+        *
+        * The trigger is modified during the execution of the
+        * "register trigger" command. However, by the time the command returns,
+        * it is safe to use without any locking as its properties are
+        * immutable.
+        */
        ret = notification_thread_command_register_trigger(notification_thread,
                        trigger);
+       if (ret != LTTNG_OK) {
+               goto end_notification_thread;
+       }
+
+       /* Return an updated trigger to the client. */
+       *return_trigger = trigger;
+
+end_notification_thread:
        /* Ownership of trigger was transferred. */
        trigger = NULL;
 end:
@@ -4337,8 +4379,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,7 +4427,20 @@ 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 = notification_thread_command_unregister_trigger(notification_thread,
                        trigger);
This page took 0.024816 seconds and 4 git commands to generate.