X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fnotification-thread-events.c;h=51b95ee6da2e85b2501eda2b839cd39629ff760c;hb=ac1889bfdcb77622bbc818352d65634209d9829f;hp=c650c974fa09489dcb8e27614d22c92f7f7476d9;hpb=90843f49fd95847b3b16e78a19879e123841d76f;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/notification-thread-events.c b/src/bin/lttng-sessiond/notification-thread-events.c index c650c974f..51b95ee6d 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,6 +149,7 @@ 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 { struct { /* @@ -262,16 +264,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 +486,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 +1161,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 +1181,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 +1196,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 +2399,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 +2457,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 +2506,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 +2542,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(); @@ -3094,6 +3146,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,