From 01ea340e0a3914f12a50875e6477bfd9a9eee099 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Sun, 28 May 2017 13:35:40 -0400 Subject: [PATCH] Fix: explicitly send client credentials during handshake MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The notification client does not send its credentials during the handshake. However, the session daemon will still receive them except in very rare, and hard to reproduce, cases. It appears that the kernel will provide the credential cmsg regardless of whether or not the client has actually sent them. Inspecting the kernel source (af_unix.c) seems to indicate that the credentials will be passed on sendmsg whenever one of the sockets involved has set the SO_PASSCRED flag. It also seems to maintain compatibility with applications that expect write() to pass credentials by default. This explains why the explicit passing didn't seem needed. Signed-off-by: Jérémie Galarneau --- src/bin/lttng-sessiond/notification-thread-events.c | 12 ++++-------- src/lib/lttng-ctl/channel.c | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/bin/lttng-sessiond/notification-thread-events.c b/src/bin/lttng-sessiond/notification-thread-events.c index 8f250dfdd..793499c4e 100644 --- a/src/bin/lttng-sessiond/notification-thread-events.c +++ b/src/bin/lttng-sessiond/notification-thread-events.c @@ -111,7 +111,7 @@ struct notification_client { * Indicates whether or not credentials are expected * from the client. */ - bool receive_creds; + bool expect_creds; /* * Indicates whether or not credentials were received * from the client. @@ -1171,7 +1171,6 @@ int client_reset_inbound_state(struct notification_client *client) sizeof(struct lttng_notification_channel_message); client->communication.inbound.msg_type = LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNKNOWN; - client->communication.inbound.receive_creds = false; LTTNG_SOCK_SET_UID_CRED(&client->communication.inbound.creds, -1); LTTNG_SOCK_SET_GID_CRED(&client->communication.inbound.creds, -1); ret = lttng_dynamic_buffer_set_size( @@ -1197,6 +1196,7 @@ int handle_notification_thread_client_connect( CDS_INIT_LIST_HEAD(&client->condition_list); lttng_dynamic_buffer_init(&client->communication.inbound.buffer); lttng_dynamic_buffer_init(&client->communication.outbound.buffer); + client->communication.inbound.expect_creds = true; ret = client_reset_inbound_state(client); if (ret) { ERR("[notification-thread] Failed to reset client communication's inbound state"); @@ -1491,10 +1491,6 @@ int client_dispatch_message(struct notification_client *client, client->communication.inbound.bytes_to_receive = msg->size; client->communication.inbound.msg_type = (enum lttng_notification_channel_message_type) msg->type; - if (client->communication.inbound.msg_type == - LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE) { - client->communication.inbound.receive_creds = true; - } ret = lttng_dynamic_buffer_set_size( &client->communication.inbound.buffer, msg->size); if (ret) { @@ -1646,13 +1642,13 @@ int handle_notification_thread_client_in( offset = client->communication.inbound.buffer.size - client->communication.inbound.bytes_to_receive; - if (client->communication.inbound.receive_creds) { + if (client->communication.inbound.expect_creds) { recv_ret = lttcomm_recv_creds_unix_sock(socket, client->communication.inbound.buffer.data + offset, client->communication.inbound.bytes_to_receive, &client->communication.inbound.creds); if (recv_ret > 0) { - client->communication.inbound.receive_creds = false; + client->communication.inbound.expect_creds = false; client->communication.inbound.creds_received = true; } } else { diff --git a/src/lib/lttng-ctl/channel.c b/src/lib/lttng-ctl/channel.c index 5bfb75902..3d48babb7 100644 --- a/src/lib/lttng-ctl/channel.c +++ b/src/lib/lttng-ctl/channel.c @@ -444,7 +444,7 @@ int handshake(struct lttng_notification_channel *channel) pthread_mutex_lock(&channel->lock); - ret = lttcomm_send_unix_sock(channel->socket, send_buffer, + ret = lttcomm_send_creds_unix_sock(channel->socket, send_buffer, sizeof(send_buffer)); if (ret < 0) { goto end_unlock; -- 2.34.1