Use lttng_trigger credentials to send evaluation to client
[lttng-tools.git] / src / bin / lttng-sessiond / notification-thread-events.c
index bdbac0c4001f44f218ea0821eab5891972d35043..c650c974fa09489dcb8e27614d22c92f7f7476d9 100644 (file)
@@ -1,18 +1,8 @@
 /*
- * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License, version 2 only, as
- * published by the Free Software Foundation.
+ * SPDX-License-Identifier: GPL-2.0-only
  *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #define _LGPL_SOURCE
@@ -501,7 +491,7 @@ enum lttng_object_type get_condition_binding_object(
        case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
        case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
        case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
-               return LTTNG_OBJECT_TYPE_CHANNEL;
+               return LTTNG_OBJECT_TYPE_CHANNEL;
        case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
        case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
                return LTTNG_OBJECT_TYPE_SESSION;
@@ -692,7 +682,7 @@ struct notification_client_list *get_client_list_from_condition(
                        &iter);
        node = cds_lfht_iter_get_node(&iter);
 
-        return node ? caa_container_of(node,
+       return node ? caa_container_of(node,
                        struct notification_client_list,
                        notification_trigger_ht_node) : NULL;
 }
@@ -928,7 +918,10 @@ int evaluate_condition_for_client(const struct lttng_trigger *trigger,
                ret = -1;
                goto end;
        }
-
+       if (ret) {
+               /* Fatal error. */
+               goto end;
+       }
        if (!evaluation) {
                /* Evaluation yielded nothing. Normal exit. */
                DBG("[notification-thread] Newly subscribed-to condition evaluated to false, nothing to report to client");
@@ -1313,7 +1306,7 @@ struct lttng_session_trigger_list *get_session_trigger_list(
                goto end;
        }
 
-        list = caa_container_of(node,
+       list = caa_container_of(node,
                        struct lttng_session_trigger_list,
                        session_triggers_ht_node);
 end:
@@ -2153,10 +2146,6 @@ error_free_ht_element:
        free(trigger_ht_element);
 error:
        if (free_trigger) {
-               struct lttng_action *action = lttng_trigger_get_action(trigger);
-
-               lttng_condition_destroy(condition);
-               lttng_action_destroy(action);
                lttng_trigger_destroy(trigger);
        }
        rcu_read_unlock();
@@ -2191,7 +2180,6 @@ int handle_notification_thread_command_unregister_trigger(
        struct lttng_trigger_ht_element *trigger_ht_element = NULL;
        struct lttng_condition *condition = lttng_trigger_get_condition(
                        trigger);
-       struct lttng_action *action;
        enum lttng_error_code cmd_reply;
 
        rcu_read_lock();
@@ -2253,10 +2241,7 @@ int handle_notification_thread_command_unregister_trigger(
                        struct lttng_trigger_ht_element, node);
        cds_lfht_del(state->triggers_ht, triggers_ht_node);
 
-       condition = lttng_trigger_get_condition(trigger_ht_element->trigger);
-       lttng_condition_destroy(condition);
-       action = lttng_trigger_get_action(trigger_ht_element->trigger);
-       lttng_action_destroy(action);
+       /* Release the ownership of the trigger. */
        lttng_trigger_destroy(trigger_ht_element->trigger);
        call_rcu(&trigger_ht_element->rcu_node, free_lttng_trigger_ht_element_rcu);
 end:
@@ -2433,7 +2418,7 @@ int handle_notification_thread_client_connect(
        ret = client_reset_inbound_state(client);
        if (ret) {
                ERR("[notification-thread] Failed to reset client communication's inbound state");
-               ret = 0;
+               ret = 0;
                goto error;
        }
 
@@ -2505,7 +2490,7 @@ int handle_notification_thread_client_disconnect(
        if (ret) {
                ERR("[notification-thread] Failed to remove client socket from poll set");
        }
-        cds_lfht_del(state->client_socket_ht,
+       cds_lfht_del(state->client_socket_ht,
                        &client->client_socket_ht_node);
        notification_client_destroy(client, state);
 end:
@@ -2571,8 +2556,7 @@ int client_flush_outgoing_queue(struct notification_client *client,
        ret = lttcomm_send_unix_sock_non_block(client->socket,
                        client->communication.outbound.buffer.data,
                        to_send_count);
-       if ((ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) ||
-                       (ret > 0 && ret < to_send_count)) {
+       if ((ret >= 0 && ret < to_send_count)) {
                DBG("[notification-thread] Client (socket fd = %i) outgoing queue could not be completely flushed",
                                client->socket);
                to_send_count -= max(ret, 0);
@@ -2808,14 +2792,14 @@ int client_dispatch_message(struct notification_client *client,
                struct lttng_condition *condition;
                enum lttng_notification_channel_status status =
                                LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
-               const struct lttng_buffer_view condition_view =
-                               lttng_buffer_view_from_dynamic_buffer(
+               struct lttng_payload_view condition_view =
+                               lttng_payload_view_from_dynamic_buffer(
                                        &client->communication.inbound.buffer,
                                        0, -1);
                size_t expected_condition_size =
                                client->communication.inbound.buffer.size;
 
-               ret = lttng_condition_create_from_buffer(&condition_view,
+               ret = lttng_condition_create_from_payload(&condition_view,
                                &condition);
                if (ret != expected_condition_size) {
                        ERR("[notification-thread] Malformed condition received from client");
@@ -2956,7 +2940,7 @@ bool evaluate_buffer_usage_condition(const struct lttng_condition *condition,
                 * forego this double-multiplication or it could be performed
                 * as fixed-point math.
                 *
-                * Note that caching should accomodate the case where the
+                * Note that caching should accommodates the case where the
                 * condition applies to multiple channels (i.e. don't assume
                 * that all channels matching my_chann* have the same size...)
                 */
@@ -3096,8 +3080,7 @@ end:
 }
 
 static
-int client_enqueue_dropped_notification(struct notification_client *client,
-               struct notification_thread_state *state)
+int client_enqueue_dropped_notification(struct notification_client *client)
 {
        int ret;
        struct lttng_notification_channel_message msg = {
@@ -3116,10 +3099,10 @@ int send_evaluation_to_clients(const struct lttng_trigger *trigger,
                const struct lttng_evaluation *evaluation,
                struct notification_client_list* client_list,
                struct notification_thread_state *state,
-               uid_t channel_uid, gid_t channel_gid)
+               uid_t object_uid, gid_t object_gid)
 {
        int ret = 0;
-       struct lttng_dynamic_buffer msg_buffer;
+       struct lttng_payload msg_payload;
        struct notification_client_list_element *client_list_element, *tmp;
        const struct lttng_notification notification = {
                .condition = (struct lttng_condition *) lttng_trigger_get_const_condition(trigger),
@@ -3128,16 +3111,17 @@ int send_evaluation_to_clients(const struct lttng_trigger *trigger,
        struct lttng_notification_channel_message msg_header = {
                .type = (int8_t) LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION,
        };
+       const struct lttng_credentials *trigger_creds = lttng_trigger_get_credentials(trigger);
 
-       lttng_dynamic_buffer_init(&msg_buffer);
+       lttng_payload_init(&msg_payload);
 
-       ret = lttng_dynamic_buffer_append(&msg_buffer, &msg_header,
+       ret = lttng_dynamic_buffer_append(&msg_payload.buffer, &msg_header,
                        sizeof(msg_header));
        if (ret) {
                goto end;
        }
 
-       ret = lttng_notification_serialize(&notification, &msg_buffer);
+       ret = lttng_notification_serialize(&notification, &msg_payload);
        if (ret) {
                ERR("[notification-thread] Failed to serialize notification");
                ret = -1;
@@ -3145,23 +3129,28 @@ int send_evaluation_to_clients(const struct lttng_trigger *trigger,
        }
 
        /* Update payload size. */
-       ((struct lttng_notification_channel_message * ) msg_buffer.data)->size =
-                       (uint32_t) (msg_buffer.size - sizeof(msg_header));
+       ((struct lttng_notification_channel_message * ) msg_payload.buffer.data)->size =
+                       (uint32_t) (msg_payload.buffer.size - sizeof(msg_header));
 
        cds_list_for_each_entry_safe(client_list_element, tmp,
                        &client_list->list, node) {
                struct notification_client *client =
                                client_list_element->client;
 
-               if (client->uid != channel_uid && client->gid != channel_gid &&
+               if (client->uid != object_uid && client->gid != object_gid &&
                                client->uid != 0) {
                        /* Client is not allowed to monitor this channel. */
-                       DBG("[notification-thread] Skipping client at it does not have the permission to receive notification for this channel");
+                       DBG("[notification-thread] Skipping client at it does not have the object permission to receive notification for this trigger");
+                       continue;
+               }
+
+               if (client->uid != trigger_creds->uid && client->gid != trigger_creds->gid) {
+                       DBG("[notification-thread] Skipping client at it does not have the permission to receive notification for this trigger");
                        continue;
                }
 
                DBG("[notification-thread] Sending notification to client (fd = %i, %zu bytes)",
-                               client->socket, msg_buffer.size);
+                               client->socket, msg_payload.buffer.size);
                if (client->communication.outbound.buffer.size) {
                        /*
                         * Outgoing data is already buffered for this client;
@@ -3175,7 +3164,7 @@ int send_evaluation_to_clients(const struct lttng_trigger *trigger,
                        if (!client->communication.outbound.dropped_notification) {
                                client->communication.outbound.dropped_notification = true;
                                ret = client_enqueue_dropped_notification(
-                                               client, state);
+                                               client);
                                if (ret) {
                                        goto end;
                                }
@@ -3185,7 +3174,7 @@ int send_evaluation_to_clients(const struct lttng_trigger *trigger,
 
                ret = lttng_dynamic_buffer_append_buffer(
                                &client->communication.outbound.buffer,
-                               &msg_buffer);
+                               &msg_payload.buffer);
                if (ret) {
                        goto end;
                }
@@ -3197,7 +3186,7 @@ int send_evaluation_to_clients(const struct lttng_trigger *trigger,
        }
        ret = 0;
 end:
-       lttng_dynamic_buffer_reset(&msg_buffer);
+       lttng_payload_reset(&msg_payload);
        return ret;
 }
 
@@ -3336,7 +3325,7 @@ int handle_notification_thread_channel_sample(
        trigger_list = caa_container_of(node, struct lttng_channel_trigger_list,
                        channel_triggers_ht_node);
        cds_list_for_each_entry(trigger_list_element, &trigger_list->list,
-                       node) {
+                       node) {
                const struct lttng_condition *condition;
                const struct lttng_action *action;
                const struct lttng_trigger *trigger;
This page took 0.027827 seconds and 5 git commands to generate.