X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fnotification-thread-events.c;h=a2fa8a1ca854933bdf505508002b3d113f609ce4;hp=c650c974fa09489dcb8e27614d22c92f7f7476d9;hb=1b5edb83504a933f6f5a1b07d574f8c6cf2e0e4e;hpb=90843f49fd95847b3b16e78a19879e123841d76f diff --git a/src/bin/lttng-sessiond/notification-thread-events.c b/src/bin/lttng-sessiond/notification-thread-events.c index c650c974f..a2fa8a1ca 100644 --- a/src/bin/lttng-sessiond/notification-thread-events.c +++ b/src/bin/lttng-sessiond/notification-thread-events.c @@ -131,6 +131,7 @@ struct notification_client_list { }; struct notification_client { + notification_client_id id; int socket; /* Client protocol version. */ uint8_t major, minor; @@ -148,7 +149,15 @@ struct notification_client { */ struct cds_list_head condition_list; struct cds_lfht_node client_socket_ht_node; + struct cds_lfht_node client_id_ht_node; struct { + /* + * If a client's communication is inactive, it means a fatal + * error (either a protocol error or the socket API returned + * a fatal error). No further communication should be attempted; + * the client is queued for clean-up. + */ + bool active; struct { /* * During the reception of a message, the reception @@ -262,16 +271,25 @@ int lttng_session_trigger_list_add(struct lttng_session_trigger_list *list, static -int match_client(struct cds_lfht_node *node, const void *key) +int match_client_socket(struct cds_lfht_node *node, const void *key) { /* This double-cast is intended to supress pointer-to-cast warning. */ - int socket = (int) (intptr_t) key; - struct notification_client *client; + const int socket = (int) (intptr_t) key; + const struct notification_client *client = caa_container_of(node, + struct notification_client, client_socket_ht_node); - client = caa_container_of(node, struct notification_client, - client_socket_ht_node); + return client->socket == socket; +} + +static +int match_client_id(struct cds_lfht_node *node, const void *key) +{ + /* This double-cast is intended to supress pointer-to-cast warning. */ + const notification_client_id id = *((notification_client_id *) key); + const struct notification_client *client = caa_container_of( + node, struct notification_client, client_id_ht_node); - return !!(client->socket == socket); + return client->id == id; } static @@ -475,6 +493,18 @@ unsigned long hash_channel_key(struct channel_key *key) return key_hash ^ domain_hash; } +static +unsigned long hash_client_socket(int socket) +{ + return hash_key_ulong((void *) (unsigned long) socket, lttng_ht_seed); +} + +static +unsigned long hash_client_id(notification_client_id id) +{ + return hash_key_u64(&id, lttng_ht_seed); +} + /* * Get the type of object to which a given condition applies. Bindings let * the notification system evaluate a trigger's condition when a given @@ -1138,6 +1168,7 @@ void notification_client_destroy(struct notification_client *client, if (client->socket >= 0) { (void) lttcomm_close_unix_sock(client->socket); + client->socket = -1; } lttng_dynamic_buffer_reset(&client->communication.inbound.buffer); lttng_dynamic_buffer_reset(&client->communication.outbound.buffer); @@ -1157,8 +1188,8 @@ struct notification_client *get_client_from_socket(int socket, struct notification_client *client = NULL; cds_lfht_lookup(state->client_socket_ht, - hash_key_ulong((void *) (unsigned long) socket, lttng_ht_seed), - match_client, + hash_client_socket(socket), + match_client_socket, (void *) (unsigned long) socket, &iter); node = cds_lfht_iter_get_node(&iter); @@ -1172,6 +1203,34 @@ end: return client; } +/* + * Call with rcu_read_lock held (and hold for the lifetime of the returned + * client pointer). + */ +static +struct notification_client *get_client_from_id(notification_client_id id, + struct notification_thread_state *state) +{ + struct cds_lfht_iter iter; + struct cds_lfht_node *node; + struct notification_client *client = NULL; + + cds_lfht_lookup(state->client_id_ht, + hash_client_id(id), + match_client_id, + &id, + &iter); + node = cds_lfht_iter_get_node(&iter); + if (!node) { + goto end; + } + + client = caa_container_of(node, struct notification_client, + client_id_ht_node); +end: + return client; +} + static bool buffer_usage_condition_applies_to_channel( const struct lttng_condition *condition, @@ -2347,12 +2406,6 @@ error: return -1; } -static -unsigned long hash_client_socket(int socket) -{ - return hash_key_ulong((void *) (unsigned long) socket, lttng_ht_seed); -} - static int socket_set_non_blocking(int socket) { @@ -2411,6 +2464,7 @@ int handle_notification_thread_client_connect( ret = -1; goto error; } + client->id = state->next_notification_client_id++; CDS_INIT_LIST_HEAD(&client->condition_list); lttng_dynamic_buffer_init(&client->communication.inbound.buffer); lttng_dynamic_buffer_init(&client->communication.outbound.buffer); @@ -2459,6 +2513,9 @@ int handle_notification_thread_client_connect( cds_lfht_add(state->client_socket_ht, hash_client_socket(client->socket), &client->client_socket_ht_node); + cds_lfht_add(state->client_id_ht, + hash_client_id(client->id), + &client->client_id_ht_node); rcu_read_unlock(); return ret; @@ -2492,6 +2549,8 @@ int handle_notification_thread_client_disconnect( } cds_lfht_del(state->client_socket_ht, &client->client_socket_ht_node); + cds_lfht_del(state->client_id_ht, + &client->client_id_ht_node); notification_client_destroy(client, state); end: rcu_read_unlock(); @@ -2784,6 +2843,7 @@ int client_dispatch_message(struct notification_client *client, goto end; } client->validated = true; + client->communication.active = true; break; } case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE: @@ -3094,6 +3154,39 @@ int client_enqueue_dropped_notification(struct notification_client *client) return ret; } +/* + * Permission checks relative to notification channel clients are performed + * here. Notice how object, client, and trigger credentials are involved in + * this check. + * + * The `object` credentials are the credentials associated with the "subject" + * of a condition. For instance, a `rotation completed` condition applies + * to a session. When that condition is met, it will produce an evaluation + * against a session. Hence, in this case, the `object` credentials are the + * credentials of the "subject" session. + * + * The `trigger` credentials are the credentials of the user that registered the + * trigger. + * + * The `client` credentials are the credentials of the user that created a given + * notification channel. + * + * In terms of visibility, it is expected that non-privilieged users can only + * register triggers against "their" objects (their own sessions and + * applications they are allowed to interact with). They can then open a + * notification channel and subscribe to notifications associated with those + * triggers. + * + * As for privilieged users, they can register triggers against the objects of + * other users. They can then subscribe to the notifications associated to their + * triggers. Privilieged users _can't_ subscribe to the notifications of + * triggers owned by other users; they must create their own triggers. + * + * This is more a concern of usability than security. It would be difficult for + * a root user reliably subscribe to a specific set of conditions without + * interference from external users (those could, for instance, unregister + * their triggers). + */ static int send_evaluation_to_clients(const struct lttng_trigger *trigger, const struct lttng_evaluation *evaluation,