From: Jérémie Galarneau Date: Tue, 26 Jan 2021 23:13:11 +0000 (-0500) Subject: sessiond: trigger: decouple reception of triggers from commands X-Git-Tag: v2.13.0-rc1~366 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=746e08d773ef6c7bbbae1334350b8a2c46aaeb0e;p=lttng-tools.git sessiond: trigger: decouple reception of triggers from commands The trigger to register/unregister is received in the body of the register and unregister commands. Isolate the reception of the trigger from the command payload in a util in client.c (receive_lttng_trigger()) which allows the commands to only operate on fully-formed objects. Signed-off-by: Jérémie Galarneau Change-Id: Iaee6c54590e259ce053d368494ff0c8b356a36a1 --- diff --git a/src/bin/lttng-sessiond/client.c b/src/bin/lttng-sessiond/client.c index 3ccc29efc..6c17ea2c1 100644 --- a/src/bin/lttng-sessiond/client.c +++ b/src/bin/lttng-sessiond/client.c @@ -694,6 +694,77 @@ error: return ret; } +static enum lttng_error_code receive_lttng_trigger(struct command_ctx *cmd_ctx, + int sock, + int *sock_error, + struct lttng_trigger **_trigger) +{ + int ret; + size_t trigger_len; + ssize_t sock_recv_len; + enum lttng_error_code ret_code; + struct lttng_payload trigger_payload; + struct lttng_trigger *trigger; + + lttng_payload_init(&trigger_payload); + trigger_len = (size_t) cmd_ctx->lsm.u.trigger.length; + ret = lttng_dynamic_buffer_set_size( + &trigger_payload.buffer, trigger_len); + if (ret) { + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + + sock_recv_len = lttcomm_recv_unix_sock( + sock, trigger_payload.buffer.data, trigger_len); + if (sock_recv_len < 0 || sock_recv_len != trigger_len) { + ERR("Failed to receive trigger in command payload"); + *sock_error = 1; + ret_code = LTTNG_ERR_INVALID_PROTOCOL; + goto end; + } + + /* Receive fds, if any. */ + if (cmd_ctx->lsm.fd_count > 0) { + sock_recv_len = lttcomm_recv_payload_fds_unix_sock( + sock, cmd_ctx->lsm.fd_count, &trigger_payload); + if (sock_recv_len > 0 && + sock_recv_len != cmd_ctx->lsm.fd_count * sizeof(int)) { + ERR("Failed to receive all file descriptors for trigger in command payload: expected fd count = %u, ret = %d", + cmd_ctx->lsm.fd_count, (int) ret); + ret_code = LTTNG_ERR_INVALID_PROTOCOL; + *sock_error = 1; + goto end; + } else if (sock_recv_len <= 0) { + ERR("Failed to receive file descriptors for trigger in command payload: expected fd count = %u, ret = %d", + cmd_ctx->lsm.fd_count, (int) ret); + ret_code = LTTNG_ERR_FATAL; + *sock_error = 1; + goto end; + } + } + + /* Deserialize trigger. */ + { + struct lttng_payload_view view = + lttng_payload_view_from_payload( + &trigger_payload, 0, -1); + + if (lttng_trigger_create_from_payload(&view, &trigger) != + trigger_len) { + ERR("Invalid trigger received as part of command payload"); + ret_code = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + } + + *_trigger = trigger; + ret_code = LTTNG_OK; + +end: + return ret_code; +} + /* * Version of setup_lttng_msg() without command header. */ @@ -2055,9 +2126,14 @@ error_add_context: } case LTTNG_REGISTER_TRIGGER: { + struct lttng_trigger *payload_trigger; struct lttng_trigger *return_trigger; - size_t original_payload_size; - size_t payload_size; + size_t original_reply_payload_size; + size_t reply_payload_size; + const struct lttng_credentials cmd_creds = { + .uid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.uid), + .gid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.gid), + }; ret = setup_empty_lttng_msg(cmd_ctx); if (ret) { @@ -2065,37 +2141,55 @@ error_add_context: goto setup_error; } - original_payload_size = cmd_ctx->reply_payload.buffer.size; + ret = receive_lttng_trigger( + cmd_ctx, *sock, sock_error, &payload_trigger); + if (ret != LTTNG_OK) { + goto error; + } - ret = cmd_register_trigger(cmd_ctx, *sock, + original_reply_payload_size = cmd_ctx->reply_payload.buffer.size; + + ret = cmd_register_trigger(&cmd_creds, payload_trigger, notification_thread_handle, &return_trigger); if (ret != LTTNG_OK) { + lttng_trigger_put(payload_trigger); goto error; } ret = lttng_trigger_serialize(return_trigger, &cmd_ctx->reply_payload); + lttng_trigger_put(payload_trigger); + lttng_trigger_put(return_trigger); if (ret) { ERR("Failed to serialize trigger in reply to \"register trigger\" command"); ret = LTTNG_ERR_NOMEM; - lttng_trigger_destroy(return_trigger); goto error; } - lttng_trigger_destroy(return_trigger); - return_trigger = NULL; - - payload_size = cmd_ctx->reply_payload.buffer.size - - original_payload_size; + reply_payload_size = cmd_ctx->reply_payload.buffer.size - + original_reply_payload_size; - update_lttng_msg(cmd_ctx, 0, payload_size); + update_lttng_msg(cmd_ctx, 0, reply_payload_size); ret = LTTNG_OK; break; } case LTTNG_UNREGISTER_TRIGGER: { - ret = cmd_unregister_trigger(cmd_ctx, *sock, + struct lttng_trigger *payload_trigger; + const struct lttng_credentials cmd_creds = { + .uid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.uid), + .gid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.gid), + }; + + ret = receive_lttng_trigger( + cmd_ctx, *sock, sock_error, &payload_trigger); + if (ret != LTTNG_OK) { + goto error; + } + + ret = cmd_unregister_trigger(&cmd_creds, payload_trigger, notification_thread_handle); + lttng_trigger_put(payload_trigger); break; } case LTTNG_ROTATE_SESSION: diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 96f7433a6..061629d11 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -4288,63 +4288,12 @@ end: return ret; } -int cmd_register_trigger(struct command_ctx *cmd_ctx, int sock, +int cmd_register_trigger(const struct lttng_credentials *cmd_creds, + struct lttng_trigger *trigger, struct notification_thread_handle *notification_thread, struct lttng_trigger **return_trigger) { int ret; - size_t trigger_len; - ssize_t sock_recv_len; - struct lttng_trigger *trigger = NULL; - struct lttng_payload trigger_payload; - struct lttng_credentials cmd_creds = { - .uid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.uid), - .gid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.gid), - }; - - lttng_payload_init(&trigger_payload); - trigger_len = (size_t) cmd_ctx->lsm.u.trigger.length; - ret = lttng_dynamic_buffer_set_size( - &trigger_payload.buffer, trigger_len); - if (ret) { - ret = LTTNG_ERR_NOMEM; - goto end; - } - - sock_recv_len = lttcomm_recv_unix_sock( - sock, trigger_payload.buffer.data, trigger_len); - if (sock_recv_len < 0 || sock_recv_len != trigger_len) { - ERR("Failed to receive \"register trigger\" command payload"); - ret = LTTNG_ERR_INVALID_PROTOCOL; - goto end; - } - - /* Receive fds, if any. */ - if (cmd_ctx->lsm.fd_count > 0) { - ret = lttcomm_recv_payload_fds_unix_sock( - sock, cmd_ctx->lsm.fd_count, &trigger_payload); - if (ret > 0 && ret != cmd_ctx->lsm.fd_count * sizeof(int)) { - ret = LTTNG_ERR_INVALID_PROTOCOL; - goto end; - } else if (ret <= 0) { - ret = LTTNG_ERR_FATAL; - goto end; - } - } - - /* Deserialize trigger. */ - { - struct lttng_payload_view view = - lttng_payload_view_from_payload( - &trigger_payload, 0, -1); - - if (lttng_trigger_create_from_payload(&view, &trigger) != - trigger_len) { - ERR("Invalid trigger payload received in \"register trigger\" command"); - ret = LTTNG_ERR_INVALID_TRIGGER; - goto end; - } - } /* * Validate the trigger credentials against the command credentials. @@ -4353,8 +4302,8 @@ int cmd_register_trigger(struct command_ctx *cmd_ctx, int sock, */ if (!lttng_credentials_is_equal_uid( lttng_trigger_get_credentials(trigger), - &cmd_creds)) { - if (lttng_credentials_get_uid(&cmd_creds) != 0) { + 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; @@ -4365,7 +4314,7 @@ int cmd_register_trigger(struct command_ctx *cmd_ctx, int sock, * The bytecode generation also serves as a validation step for the * bytecode expressions. */ - ret = lttng_trigger_generate_bytecode(trigger, &cmd_creds); + ret = lttng_trigger_generate_bytecode(trigger, cmd_creds); if (ret != LTTNG_OK) { goto end; } @@ -4386,74 +4335,28 @@ int cmd_register_trigger(struct command_ctx *cmd_ctx, int sock, goto end_notification_thread; } - /* Return an updated trigger to the client. */ + /* + * Return an updated trigger to the client. + * + * Since a modified version of the same trigger is returned, acquire a + * reference to the trigger so the caller doesn't have to care if those + * are distinct instances or not. + */ + lttng_trigger_get(trigger); *return_trigger = trigger; end_notification_thread: /* Ownership of trigger was transferred. */ trigger = NULL; end: - lttng_trigger_destroy(trigger); - lttng_payload_reset(&trigger_payload); return ret; } -int cmd_unregister_trigger(struct command_ctx *cmd_ctx, int sock, +int cmd_unregister_trigger(const struct lttng_credentials *cmd_creds, + const struct lttng_trigger *trigger, struct notification_thread_handle *notification_thread) { int ret; - size_t trigger_len; - ssize_t sock_recv_len; - struct lttng_trigger *trigger = NULL; - struct lttng_payload trigger_payload; - struct lttng_credentials cmd_creds = { - .uid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.uid), - .gid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.gid), - }; - - lttng_payload_init(&trigger_payload); - trigger_len = (size_t) cmd_ctx->lsm.u.trigger.length; - ret = lttng_dynamic_buffer_set_size( - &trigger_payload.buffer, trigger_len); - if (ret) { - ret = LTTNG_ERR_NOMEM; - goto end; - } - - sock_recv_len = lttcomm_recv_unix_sock( - sock, trigger_payload.buffer.data, trigger_len); - if (sock_recv_len < 0 || sock_recv_len != trigger_len) { - ERR("Failed to receive \"unregister trigger\" command payload"); - /* TODO: should this be a new error enum ? */ - ret = LTTNG_ERR_INVALID_TRIGGER; - goto end; - } - - /* Receive fds, if any. */ - if (cmd_ctx->lsm.fd_count > 0) { - ret = lttcomm_recv_payload_fds_unix_sock( - sock, cmd_ctx->lsm.fd_count, &trigger_payload); - if (ret > 0 && ret != cmd_ctx->lsm.fd_count * sizeof(int)) { - ret = LTTNG_ERR_INVALID_PROTOCOL; - goto end; - } else if (ret <= 0) { - ret = LTTNG_ERR_FATAL; - goto end; - } - } - - { - struct lttng_payload_view view = - lttng_payload_view_from_payload( - &trigger_payload, 0, -1); - - if (lttng_trigger_create_from_payload(&view, &trigger) != - trigger_len) { - ERR("Invalid trigger payload received in \"unregister trigger\" command"); - ret = LTTNG_ERR_INVALID_TRIGGER; - goto end; - } - } /* * Validate the trigger credentials against the command credentials. @@ -4462,8 +4365,8 @@ int cmd_unregister_trigger(struct command_ctx *cmd_ctx, int sock, */ if (!lttng_credentials_is_equal_uid( lttng_trigger_get_credentials(trigger), - &cmd_creds)) { - if (lttng_credentials_get_uid(&cmd_creds) != 0) { + 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; @@ -4473,8 +4376,6 @@ int cmd_unregister_trigger(struct command_ctx *cmd_ctx, int sock, ret = notification_thread_command_unregister_trigger(notification_thread, trigger); end: - lttng_trigger_destroy(trigger); - lttng_payload_reset(&trigger_payload); return ret; } diff --git a/src/bin/lttng-sessiond/cmd.h b/src/bin/lttng-sessiond/cmd.h index d376aee1e..a162a9a07 100644 --- a/src/bin/lttng-sessiond/cmd.h +++ b/src/bin/lttng-sessiond/cmd.h @@ -141,10 +141,12 @@ int cmd_set_session_shm_path(struct ltt_session *session, int cmd_regenerate_metadata(struct ltt_session *session); int cmd_regenerate_statedump(struct ltt_session *session); -int cmd_register_trigger(struct command_ctx *cmd_ctx, int sock, +int cmd_register_trigger(const struct lttng_credentials *cmd_creds, + struct lttng_trigger *trigger, struct notification_thread_handle *notification_thread_handle, struct lttng_trigger **return_trigger); -int cmd_unregister_trigger(struct command_ctx *cmd_ctx, int sock, +int cmd_unregister_trigger(const struct lttng_credentials *cmd_creds, + const struct lttng_trigger *trigger, struct notification_thread_handle *notification_thread_handle); int cmd_list_triggers(struct command_ctx *cmd_ctx,