From 1fa11e2f48f15ba299133841d28a59662f61bb75 Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Thu, 18 Apr 2024 16:35:40 -0400 Subject: [PATCH] sessiond/lttng-ctl: Introduce LTTNG_RUNDIR MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Observed issue ============== Starting multiple instances of lttng-sessiond as the root user isn't possible, even with setting different values for the `LTTNG_HOME` environment variable. Cause ===== When starting `lttng-sessiond` the `apps_unix_sock_path`, `client_unix_sock_path`, and `health_unix_sock_path` are set to configure time static defines under `CONFIG_LTTNG_SYSTEM_RUNDIR`, e.g. `/var/lib/lttng`. Solution ======== A new environment variable `LTTNG_RUNDIR` is introduced to control the base directory used by applications to find communication sockets. The default behaviour is to emulate the existing divide: if `LTTNG_RUNDIR` is not set the root `lttng-sessiond` will continue to use `CONFIG_LTTNG_SYSTEM_RUNDIR`, and a non-root user `lttng-sessiond` will use `LTTNG_HOME/.lttng`. When `LTTNG_RUNDIR` is set, it takes priority over `LTTNG_HOME` for determining the base directory. The output directory for traces is not affected by `LTTNG_RUNDIR`, it continues to respect `LTTNG_HOME`. Example with starting multiple root `lttng-sessiond`s: ``` DIR_A=$(mktemp -d) DIR_B=$(mktemp -d) LTTNG_RUNDIR="${DIR_A}" lttng-sessiond -b LTTNG_RUNDIR="${DIR_B}" lttng-sessiond -b LTTNG_RUNDIR="${DIR_A}" lttng list LTTNG_RUNDIR="${DIR_B}" lttng list ``` In the example above, as `LTTNG_HOME` is not set, the default output directory for traces by both over the `lttng-sessiond` instances will be `$HOME/lttng-traces`. The following will also work: ``` DIR_A=$(mktemp -d) LTTNG_RUNDIR="${DIR_A}" lttng create LTTNG_RUNDIR="${DIR_A}" lttng enable-event -u --all LTTNG_RUNDIR="${DIR_A}" lttng start LTTNG_UST_APP_PATH="${DIR_A}" test-application ``` The `LTTNG_UST_CTL_PATH` can be set to a location other than the rundir as follows; ``` DIR_A=$(mktemp -d) DIR_B=$(mktemp -d) LTTNG_UST_CTL_PATH="${DIR_B}" LTTNG_RUNDIR="${DIR_A}" lttng create LTTNG_RUNDIR="${DIR_A}" lttng enable-event -u -all LTTNG_RUNDIR="${DIR_A}" lttng start LTTNG_UST_APP_PATH="${DIR_B}" test-application LTTNG_UST_APP_PATH="${DIR_A}" test-application ``` Known drawbacks =============== None. Change-Id: I371c2c72644277b7dcafaf970ee7b75d9bfbaedc Signed-off-by: Kienan Stewart Signed-off-by: Jérémie Galarneau --- doc/man/lttng-sessiond.8.txt | 9 + src/bin/lttng-consumerd/health-consumerd.cpp | 130 ++++++------ src/bin/lttng-relayd/health-relayd.cpp | 197 +++++++----------- src/bin/lttng-sessiond/client.cpp | 10 +- src/bin/lttng-sessiond/main.cpp | 4 +- .../lttng-sessiond/notification-thread.cpp | 48 ++--- src/bin/lttng-sessiond/sessiond-config.cpp | 118 +++++------ src/common/config/session-config.cpp | 46 ++-- src/common/consumer/consumer.hpp | 33 +++ src/common/defaults.hpp | 41 ++-- src/common/exception.cpp | 6 + src/common/exception.hpp | 10 +- src/common/format.hpp | 1 + src/common/utils.cpp | 54 +++++ src/common/utils.hpp | 1 + src/lib/lttng-ctl/channel.cpp | 62 +++--- src/lib/lttng-ctl/lttng-ctl-health.cpp | 40 ++-- src/lib/lttng-ctl/lttng-ctl.cpp | 25 ++- .../tools/config-directory/test_config.py.in | 46 +++- .../ust/ust-app-ctl-paths/test_blocking | 4 +- .../ust-app-ctl-paths/test_ust_app_ctl_paths | 42 ++-- tests/utils/lttngtest/lttng.py | 3 + 22 files changed, 502 insertions(+), 428 deletions(-) diff --git a/doc/man/lttng-sessiond.8.txt b/doc/man/lttng-sessiond.8.txt index 60382d59d..a987ba58d 100644 --- a/doc/man/lttng-sessiond.8.txt +++ b/doc/man/lttng-sessiond.8.txt @@ -379,6 +379,15 @@ variable. + Set to `0` or `-1` to use the timeout of the operating system (default). +`LTTNG_RUN_DIR`:: + The directory for the session daemon's control files. For session + daemons running as the root user, this path defaults to the configured + `LTTNG_SYSTEM_RUNDIR` (e.g. `/var/run/lttng`). For session daemons + running as non-root users, this defaults to `$LTTNG_HOME/.lttng`. ++ +This environment variable is particularly useful for running multiple +session daemons as the root user. + `LTTNG_SESSION_CONFIG_XSD_PATH`:: Recording session configuration XML schema definition (XSD) path. diff --git a/src/bin/lttng-consumerd/health-consumerd.cpp b/src/bin/lttng-consumerd/health-consumerd.cpp index d0a6ce14f..16e9a19de 100644 --- a/src/bin/lttng-consumerd/health-consumerd.cpp +++ b/src/bin/lttng-consumerd/health-consumerd.cpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include @@ -40,17 +42,18 @@ #include #include -/* Global health check unix path */ -static char health_unix_sock_path[PATH_MAX]; - int health_quit_pipe[2] = { -1, -1 }; +namespace { +/* Global health check unix path */ +char health_unix_sock_path[PATH_MAX]; + /* * Send data on a unix socket using the liblttsessiondcomm API. * * Return lttcomm error code. */ -static int send_unix_sock(int sock, void *buf, size_t len) +int send_unix_sock(int sock, void *buf, size_t len) { /* Check valid length */ if (len == 0) { @@ -60,79 +63,56 @@ static int send_unix_sock(int sock, void *buf, size_t len) return lttcomm_send_unix_sock(sock, buf, len); } -static int setup_health_path() +void setup_health_path() { - int is_root, ret = 0; - enum lttng_consumer_type type; - const char *home_path; + if (strlen(health_unix_sock_path) != 0) { + return; + } - type = lttng_consumer_get_type(); - is_root = !getuid(); + const char *consumer_health_socket_fmt_string; + const auto consumer_type = lttng_consumer_get_type(); + switch (consumer_type) { + case LTTNG_CONSUMER_KERNEL: + { + consumer_health_socket_fmt_string = DEFAULT_KCONSUMER_HEALTH_UNIX_SOCK; + break; + } + case LTTNG_CONSUMER64_UST: + { + consumer_health_socket_fmt_string = DEFAULT_USTCONSUMER64_HEALTH_UNIX_SOCK; + break; + } + case LTTNG_CONSUMER32_UST: + { + consumer_health_socket_fmt_string = DEFAULT_USTCONSUMER32_HEALTH_UNIX_SOCK; + break; + } + default: + LTTNG_THROW_INVALID_ARGUMENT_ERROR( + "Invalid consumer type encountered while setting up consumerd health socket path"); + } - if (is_root) { - if (strlen(health_unix_sock_path) != 0) { - goto end; - } - switch (type) { - case LTTNG_CONSUMER_KERNEL: - snprintf(health_unix_sock_path, - sizeof(health_unix_sock_path), - DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK); - break; - case LTTNG_CONSUMER64_UST: - snprintf(health_unix_sock_path, - sizeof(health_unix_sock_path), - DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK); - break; - case LTTNG_CONSUMER32_UST: - snprintf(health_unix_sock_path, - sizeof(health_unix_sock_path), - DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK); - break; - default: - ret = -EINVAL; - goto end; - } - } else { - home_path = utils_get_home_dir(); - if (home_path == nullptr) { - /* TODO: Add --socket PATH option */ - ERR("Can't get HOME directory for sockets creation."); - ret = -EPERM; - goto end; - } + const auto rundir_path = + lttng::make_unique_wrapper(utils_get_rundir(0)); + if (!rundir_path) { + LTTNG_THROW_ALLOCATION_FAILURE_ERROR( + "Failed to determine RUNDIR for health socket creation"); + } - /* Set health check Unix path */ - if (strlen(health_unix_sock_path) != 0) { - goto end; - } - switch (type) { - case LTTNG_CONSUMER_KERNEL: - snprintf(health_unix_sock_path, - sizeof(health_unix_sock_path), - DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK, - home_path); - break; - case LTTNG_CONSUMER64_UST: - snprintf(health_unix_sock_path, - sizeof(health_unix_sock_path), - DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK, - home_path); - break; - case LTTNG_CONSUMER32_UST: - snprintf(health_unix_sock_path, - sizeof(health_unix_sock_path), - DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK, - home_path); - break; - default: - ret = -EINVAL; - goto end; - } + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL + const auto fmt_ret = snprintf(health_unix_sock_path, + sizeof(health_unix_sock_path), + consumer_health_socket_fmt_string, + rundir_path.get()); + DIAGNOSTIC_POP + if (fmt_ret < 0) { + LTTNG_THROW_POSIX(fmt::format("Failed to format {} health socket path", + consumer_type), + errno); } -end: - return ret; } +} /* namespace */ /* * Thread managing health check socket. @@ -148,7 +128,13 @@ void *thread_manage_health_consumerd(void *data __attribute__((unused))) DBG("[thread] Manage health check started"); - setup_health_path(); + try { + setup_health_path(); + } catch (const lttng::runtime_error& ex) { + ERR("Failed to setup health path: %s", ex.what()); + err = -1; + goto error; + } rcu_register_thread(); diff --git a/src/bin/lttng-relayd/health-relayd.cpp b/src/bin/lttng-relayd/health-relayd.cpp index 614c7f7d9..c7bd0ed6a 100644 --- a/src/bin/lttng-relayd/health-relayd.cpp +++ b/src/bin/lttng-relayd/health-relayd.cpp @@ -15,7 +15,9 @@ #include #include #include +#include #include +#include #include #include @@ -41,17 +43,18 @@ #include #include -/* Global health check unix path */ -static char health_unix_sock_path[PATH_MAX]; - int health_quit_pipe[2] = { -1, -1 }; +namespace { +/* Global health check unix path */ +char health_unix_sock_path[PATH_MAX]; + /* * Send data on a unix socket using the liblttsessiondcomm API. * * Return lttcomm error code. */ -static int send_unix_sock(int sock, void *buf, size_t len) +int send_unix_sock(int sock, void *buf, size_t len) { /* Check valid length */ if (len == 0) { @@ -61,57 +64,54 @@ static int send_unix_sock(int sock, void *buf, size_t len) return lttcomm_send_unix_sock(sock, buf, len); } -static int create_lttng_rundir_with_perm(const char *rundir) +void create_lttng_rundir_with_perm(const char *rundir) { - int ret; - - DBG3("Creating LTTng run directory: %s", rundir); + DBG_FMT("Creating LTTng run directory: `%s`", rundir); - ret = mkdir(rundir, S_IRWXU); - if (ret < 0) { + const auto mkdir_ret = mkdir(rundir, S_IRWXU); + if (mkdir_ret < 0) { if (errno != EEXIST) { - ERR("Unable to create %s", rundir); - goto error; - } else { - ret = 0; + LTTNG_THROW_POSIX(fmt::format("Failed to create rundir: path=`{}`", rundir), + errno); } - } else if (ret == 0) { - const int is_root = !getuid(); - - if (is_root) { - gid_t gid; + } - ret = utils_get_group_id(tracing_group_name, true, &gid); - if (ret) { - /* Default to root group. */ - gid = 0; - } + const auto is_root = !getuid(); + if (!is_root) { + /* Nothing more to do. */ + return; + } - ret = chown(rundir, 0, gid); - if (ret < 0) { - ERR("Unable to set group on %s", rundir); - PERROR("chown"); - ret = -1; - goto error; - } + gid_t gid; + const auto get_group_id_ret = utils_get_group_id(tracing_group_name, true, &gid); + if (get_group_id_ret) { + /* Default to root group. */ + gid = 0; + } - ret = chmod(rundir, - S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | - S_IXOTH); - if (ret < 0) { - ERR("Unable to set permissions on %s", rundir); - PERROR("chmod"); - ret = -1; - goto error; - } - } + const auto chown_ret = chown(rundir, 0, gid); + if (chown_ret < 0) { + LTTNG_THROW_POSIX( + fmt::format("Failed to set group on rundir: path=`{}`, group_id={}", + rundir, + gid), + errno); } -error: - return ret; + const auto permission_mask = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | + S_IXOTH; + const auto chmod_ret = chmod(rundir, permission_mask); + if (chmod_ret < 0) { + LTTNG_THROW_POSIX( + fmt::format( + "Failed to set permissions on rundir: path=`{}`, permission={:o}", + rundir, + permission_mask), + errno); + } } -static int parse_health_env() +void parse_health_env() { const char *health_path; @@ -120,94 +120,45 @@ static int parse_health_env() strncpy(health_unix_sock_path, health_path, PATH_MAX); health_unix_sock_path[PATH_MAX - 1] = '\0'; } - - return 0; } -static int setup_health_path() +void setup_health_path() { - int is_root, ret = 0; - const char *home_path = nullptr; - char *rundir = nullptr, *relayd_path = nullptr; + parse_health_env(); - ret = parse_health_env(); - if (ret) { - return ret; + const auto rundir_path = + lttng::make_unique_wrapper(utils_get_rundir(0)); + if (!rundir_path) { + LTTNG_THROW_ALLOCATION_FAILURE_ERROR( + "Failed to determine RUNDIR for health socket creation"); } - is_root = !getuid(); - - if (is_root) { - rundir = strdup(DEFAULT_LTTNG_RUNDIR); - if (!rundir) { - ret = -ENOMEM; - goto end; - } - } else { - /* - * Create rundir from home path. This will create something like - * $HOME/.lttng - */ - home_path = utils_get_home_dir(); - - if (home_path == nullptr) { - /* TODO: Add --socket PATH option */ - ERR("Can't get HOME directory for sockets creation."); - ret = -EPERM; - goto end; + auto relayd_rundir_path = [&rundir_path]() { + char *raw_relayd_path = nullptr; + const auto fmt_ret = + asprintf(&raw_relayd_path, DEFAULT_RELAYD_PATH, rundir_path.get()); + if (fmt_ret < 0) { + LTTNG_THROW_POSIX("Failed to fomat relayd rundir path", errno); } - ret = asprintf(&rundir, DEFAULT_LTTNG_HOME_RUNDIR, home_path); - if (ret < 0) { - ret = -ENOMEM; - goto end; - } - } + return lttng::make_unique_wrapper(raw_relayd_path); + }(); - ret = asprintf(&relayd_path, DEFAULT_RELAYD_PATH, rundir); - if (ret < 0) { - ret = -ENOMEM; - goto end; - } + create_lttng_rundir_with_perm(rundir_path.get()); + create_lttng_rundir_with_perm(relayd_rundir_path.get()); - ret = create_lttng_rundir_with_perm(rundir); - if (ret < 0) { - goto end; + if (strlen(health_unix_sock_path) != 0) { + return; } - ret = create_lttng_rundir_with_perm(relayd_path); - if (ret < 0) { - goto end; - } - - if (is_root) { - if (strlen(health_unix_sock_path) != 0) { - goto end; - } - snprintf(health_unix_sock_path, - sizeof(health_unix_sock_path), - DEFAULT_GLOBAL_RELAY_HEALTH_UNIX_SOCK, - (int) getpid()); - } else { - /* Set health check Unix path */ - if (strlen(health_unix_sock_path) != 0) { - goto end; - } - - snprintf(health_unix_sock_path, - sizeof(health_unix_sock_path), - DEFAULT_HOME_RELAY_HEALTH_UNIX_SOCK, - home_path, - (int) getpid()); - } - -end: - free(rundir); - free(relayd_path); - return ret; + snprintf(health_unix_sock_path, + sizeof(health_unix_sock_path), + DEFAULT_RELAY_HEALTH_UNIX_SOCK, + rundir_path.get(), + (int) getpid()); } -static int accept_unix_socket(void *data, int *out_fd) +int accept_unix_socket(void *data, int *out_fd) { int ret; const int accepting_sock = *((int *) data); @@ -223,7 +174,7 @@ end: return ret; } -static int open_unix_socket(void *data, int *out_fd) +int open_unix_socket(void *data, int *out_fd) { int ret; const char *path = (const char *) data; @@ -238,6 +189,7 @@ static int open_unix_socket(void *data, int *out_fd) end: return ret; } +} /* namespace */ /* * Thread managing health check socket. @@ -254,7 +206,12 @@ void *thread_manage_health_relayd(void *data __attribute__((unused))) DBG("[thread] Manage health check started"); - setup_health_path(); + try { + setup_health_path(); + } catch (const lttng::runtime_error& ex) { + ERR_FMT("Failed to setup health socket path of relay daemon: {}", ex.what()); + goto error; + } rcu_register_thread(); diff --git a/src/bin/lttng-sessiond/client.cpp b/src/bin/lttng-sessiond/client.cpp index 310b79f8b..536e26714 100644 --- a/src/bin/lttng-sessiond/client.cpp +++ b/src/bin/lttng-sessiond/client.cpp @@ -111,7 +111,7 @@ static void setup_lttng_msg(struct command_ctx *cmd_ctx, /* Append reply header. */ if (lttng_dynamic_buffer_append(&cmd_ctx->reply_payload.buffer, &llm, sizeof(llm))) { - LTTNG_THROW_ALLOCATION_FAILURE_ERROR( + LTTNG_THROW_ALLOCATION_FAILURE_WITH_SIZE_ERROR( "Failed to append the reply header to a client reply", sizeof(llm)); } @@ -119,7 +119,7 @@ static void setup_lttng_msg(struct command_ctx *cmd_ctx, if (cmd_header_len) { if (lttng_dynamic_buffer_append( &cmd_ctx->reply_payload.buffer, cmd_header_buf, cmd_header_len)) { - LTTNG_THROW_ALLOCATION_FAILURE_ERROR( + LTTNG_THROW_ALLOCATION_FAILURE_WITH_SIZE_ERROR( "Failed to append the command header to a client reply", cmd_header_len); } @@ -129,7 +129,7 @@ static void setup_lttng_msg(struct command_ctx *cmd_ctx, if (payload_len) { if (lttng_dynamic_buffer_append( &cmd_ctx->reply_payload.buffer, payload_buf, payload_len)) { - LTTNG_THROW_ALLOCATION_FAILURE_ERROR( + LTTNG_THROW_ALLOCATION_FAILURE_WITH_SIZE_ERROR( "Failed to append the payload to a client reply", payload_len); } } @@ -144,7 +144,7 @@ static void setup_empty_lttng_msg(struct command_ctx *cmd_ctx) /* Append place-holder reply header. */ if (lttng_dynamic_buffer_append(&cmd_ctx->reply_payload.buffer, &llm, sizeof(llm))) { - LTTNG_THROW_ALLOCATION_FAILURE_ERROR( + LTTNG_THROW_ALLOCATION_FAILURE_WITH_SIZE_ERROR( "Failed to append the reply header to a client reply", sizeof(llm)); } @@ -1890,7 +1890,7 @@ skip_domain: (sizeof(struct lttng_session_extended) * nr_sessions); sessions_payload = zmalloc(payload_len); if (!sessions_payload) { - LTTNG_THROW_ALLOCATION_FAILURE_ERROR( + LTTNG_THROW_ALLOCATION_FAILURE_WITH_SIZE_ERROR( "Failed to allocate session list reply payload", payload_len); } diff --git a/src/bin/lttng-sessiond/main.cpp b/src/bin/lttng-sessiond/main.cpp index cb3896e27..a7920a541 100644 --- a/src/bin/lttng-sessiond/main.cpp +++ b/src/bin/lttng-sessiond/main.cpp @@ -948,8 +948,8 @@ std::string dirname_str(const char *dir) auto dir_copy = lttng::make_unique_wrapper(strdup(dir)); if (!dir_copy) { - LTTNG_THROW_ALLOCATION_FAILURE_ERROR("Failed to copy path before use of dirname", - strlen(dir) + 1); + LTTNG_THROW_ALLOCATION_FAILURE_WITH_SIZE_ERROR( + "Failed to copy path before use of dirname", strlen(dir) + 1); } return std::string(dirname(dir_copy.get())); diff --git a/src/bin/lttng-sessiond/notification-thread.cpp b/src/bin/lttng-sessiond/notification-thread.cpp index 82272fedc..76165a96e 100644 --- a/src/bin/lttng-sessiond/notification-thread.cpp +++ b/src/bin/lttng-sessiond/notification-thread.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -155,42 +156,29 @@ error: static char *get_notification_channel_sock_path() { - int ret; - const bool is_root = !getuid(); - char *sock_path; - - sock_path = calloc(LTTNG_PATH_MAX); + auto sock_path = lttng::make_unique_wrapper( + zmalloc(LTTNG_PATH_MAX)); if (!sock_path) { - goto error; + ERR("Failed to allocate notification channel socket path"); + return nullptr; } - if (is_root) { - ret = snprintf( - sock_path, LTTNG_PATH_MAX, DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK); - if (ret < 0) { - goto error; - } - } else { - const char *home_path = utils_get_home_dir(); - - if (!home_path) { - ERR("Can't get HOME directory for socket creation"); - goto error; - } + auto rundir_path = + lttng::make_unique_wrapper(utils_get_rundir(0)); + if (!rundir_path) { + ERR("Can't get RUNDIR directory for socket creation"); + return nullptr; + } - ret = snprintf(sock_path, - LTTNG_PATH_MAX, - DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK, - home_path); - if (ret < 0) { - goto error; - } + const auto fmt_ret = snprintf(sock_path.get(), + LTTNG_PATH_MAX, + DEFAULT_NOTIFICATION_CHANNEL_UNIX_SOCK, + rundir_path.get()); + if (fmt_ret < 0) { + return nullptr; } - return sock_path; -error: - free(sock_path); - return nullptr; + return sock_path.release(); } static void notification_channel_socket_destroy(int fd) diff --git a/src/bin/lttng-sessiond/sessiond-config.cpp b/src/bin/lttng-sessiond/sessiond-config.cpp index 0a12d9d7f..7923dbf23 100644 --- a/src/bin/lttng-sessiond/sessiond-config.cpp +++ b/src/bin/lttng-sessiond/sessiond-config.cpp @@ -189,91 +189,77 @@ static int config_set_ust_ctl_paths(struct sessiond_config *config, return 0; } -static int config_set_paths_root(struct sessiond_config *config) +static int config_set_paths(struct sessiond_config *config) { - int ret = 0; - - config_string_set(&config->rundir, strdup(DEFAULT_LTTNG_RUNDIR)); + config_string_set(&config->rundir, utils_get_rundir(0)); if (!config->rundir.value) { - ERR("Failed to set rundir"); - ret = -1; - goto end; + ERR("Failed to set rundir in session daemon's configuration"); + return -1; } - config_string_set_static(&config->apps_unix_sock_path, DEFAULT_GLOBAL_APPS_UNIX_SOCK); - config_string_set_static(&config->wait_shm.path, DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH); - config_string_set_static(&config->client_unix_sock_path, DEFAULT_GLOBAL_CLIENT_UNIX_SOCK); - config_string_set_static(&config->health_unix_sock_path, DEFAULT_GLOBAL_HEALTH_UNIX_SOCK); -end: - return ret; -} + { + char *app_sock_path; -static int config_set_paths_non_root(struct sessiond_config *config) -{ - int ret = 0; - const char *home_path = utils_get_home_dir(); - char *str; + const auto fmt_ret = + asprintf(&app_sock_path, DEFAULT_APPS_UNIX_SOCK, config->rundir.value); + if (fmt_ret < 0) { + ERR("Failed to format apps unix socket path"); + return -1; + } - if (home_path == nullptr) { - ERR("Can't get HOME directory for sockets creation."); - ret = -1; - goto end; + /* Ownership of app_sock_path transfered to config. */ + config_string_set(&config->apps_unix_sock_path, app_sock_path); } - /* - * Create rundir from home path. This will create something like - * $HOME/.lttng - */ - ret = asprintf(&str, DEFAULT_LTTNG_HOME_RUNDIR, home_path); - if (ret < 0) { - ERR("Failed to set rundir"); - goto end; - } - config_string_set(&config->rundir, str); - str = nullptr; + const auto current_uid = getuid(); + if (current_uid == 0) { + config_string_set_static(&config->wait_shm.path, DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH); + } else { + char *home_apps_wait_shm_path; - ret = asprintf(&str, DEFAULT_HOME_APPS_UNIX_SOCK, home_path); - if (ret < 0) { - ERR("Failed to set default home apps unix socket path"); - goto end; - } + const auto fmt_ret = asprintf( + &home_apps_wait_shm_path, DEFAULT_HOME_APPS_WAIT_SHM_PATH, current_uid); + if (fmt_ret < 0) { + ERR("Failed to set default home apps wait shm path"); + return -1; + } - config_string_set(&config->apps_unix_sock_path, str); - str = nullptr; - ret = asprintf(&str, DEFAULT_HOME_APPS_WAIT_SHM_PATH, getuid()); - if (ret < 0) { - ERR("Failed to set default home apps wait shm path"); - goto end; + /* Ownership of home_apps_wait_shm_path transfered to config. */ + config_string_set(&config->wait_shm.path, home_apps_wait_shm_path); } - config_string_set(&config->wait_shm.path, str); - str = nullptr; + { + char *client_unix_sock_path; - ret = asprintf(&str, DEFAULT_HOME_CLIENT_UNIX_SOCK, home_path); - if (ret < 0) { - ERR("Failed to set default home client unix socket path"); - goto end; + const auto fmt_ret = asprintf( + &client_unix_sock_path, DEFAULT_CLIENT_UNIX_SOCK, config->rundir.value); + if (fmt_ret < 0) { + ERR("Failed to format client unix sock path"); + return -1; + } + + config_string_set(&config->client_unix_sock_path, client_unix_sock_path); } - config_string_set(&config->client_unix_sock_path, str); - str = nullptr; - ret = asprintf(&str, DEFAULT_HOME_HEALTH_UNIX_SOCK, home_path); - if (ret < 0) { - ERR("Failed to set default home health UNIX socket path"); - goto end; + { + char *health_unix_sock_path; + + const auto fmt_ret = asprintf( + &health_unix_sock_path, DEFAULT_HEALTH_UNIX_SOCK, config->rundir.value); + if (fmt_ret < 0) { + ERR("Failed to format health unix sock path"); + return -1; + } + + config_string_set(&config->health_unix_sock_path, health_unix_sock_path); } - config_string_set(&config->health_unix_sock_path, str); - str = nullptr; - ret = 0; -end: - return ret; + return 0; } int sessiond_config_init(struct sessiond_config *config) { int ret; - const bool is_root = (getuid() == 0); char *str; auto lttng_ust_ctl_path_override = lttng::make_unique_wrapper( utils_get_lttng_ust_ctl_path_override_dir()); @@ -281,11 +267,7 @@ int sessiond_config_init(struct sessiond_config *config) LTTNG_ASSERT(config); memcpy(config, &sessiond_config_build_defaults, sizeof(*config)); - if (is_root) { - ret = config_set_paths_root(config); - } else { - ret = config_set_paths_non_root(config); - } + ret = config_set_paths(config); if (ret < 0) { goto error; } diff --git a/src/common/config/session-config.cpp b/src/common/config/session-config.cpp index 6dddbe41e..608710e97 100644 --- a/src/common/config/session-config.cpp +++ b/src/common/config/session-config.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -1089,7 +1090,7 @@ static int create_snapshot_session(const char *session_name, xmlNodePtr output_node, const struct config_load_session_override_attr *overrides) { - int ret; + int ret = 0; enum lttng_error_code ret_code; xmlNodePtr node = nullptr; xmlNodePtr snapshot_output_list_node; @@ -3097,7 +3098,7 @@ static int process_session_node(xmlNodePtr session_node, int overwrite, const struct config_load_session_override_attr *overrides) { - int ret, started = -1, snapshot_mode = -1; + int ret = -1, started = -1, snapshot_mode = -1; uint64_t live_timer_interval = UINT64_MAX, rotation_timer_interval = 0, rotation_size = 0; xmlChar *name = nullptr; xmlChar *shm_path = nullptr; @@ -3686,6 +3687,8 @@ int config_load_session(const char *path, bool session_loaded = false; const char *path_ptr = nullptr; struct session_config_validation_ctx validation_ctx = {}; + const char *home_path = nullptr; + char path_buf[PATH_MAX]; ret = init_session_config_validation_ctx(&validation_ctx); if (ret) { @@ -3693,14 +3696,9 @@ int config_load_session(const char *path, } if (!path) { - const char *home_path; - const char *sys_path; - /* Try home path */ home_path = utils_get_home_dir(); if (home_path) { - char path_buf[PATH_MAX]; - /* * Try user session configuration path. Ignore error here so we can * continue loading the system wide sessions. @@ -3759,16 +3757,38 @@ int config_load_session(const char *path, path_ptr = nullptr; /* Try system wide configuration directory. */ + const auto sys_path = + lttng::make_unique_wrapper(utils_get_rundir(0)); + if (!sys_path) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + if (autoload) { - sys_path = DEFAULT_SESSION_SYSTEM_CONFIGPATH - "/" DEFAULT_SESSION_CONFIG_AUTOLOAD; - ret = validate_path_creds(sys_path); + ret = snprintf(path_buf, + sizeof(path_buf), + DEFAULT_SESSION_CONFIGPATH + "/" DEFAULT_SESSION_CONFIG_AUTOLOAD, + sys_path.get()); + if (ret < 0) { + PERROR("snprintf session auto sys config path"); + ret = -LTTNG_ERR_INVALID; + goto end; + } + ret = validate_path_creds(sys_path.get()); if (ret) { - path_ptr = sys_path; + path_ptr = sys_path.get(); } } else { - sys_path = DEFAULT_SESSION_SYSTEM_CONFIGPATH; - path_ptr = sys_path; + ret = snprintf(path_buf, + sizeof(path_buf), + DEFAULT_SESSION_CONFIGPATH, + sys_path.get()); + if (ret < 0) { + PERROR("snprintf session sys config path"); + ret = -LTTNG_ERR_INVALID; + goto end; + } } if (path_ptr) { diff --git a/src/common/consumer/consumer.hpp b/src/common/consumer/consumer.hpp index cad2e2c56..ff5a91f8a 100644 --- a/src/common/consumer/consumer.hpp +++ b/src/common/consumer/consumer.hpp @@ -76,6 +76,39 @@ enum lttng_consumer_type { LTTNG_CONSUMER32_UST, }; +/* + * Due to a bug in g++ < 7.1, this specialization must be enclosed in the fmt namespace, + * see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480. + */ +namespace fmt { +template <> +struct formatter : formatter { + template + typename FormatContextType::iterator format(lttng_consumer_type consumer_type, + FormatContextType& ctx) const + { + const char *name; + + switch (consumer_type) { + case LTTNG_CONSUMER_KERNEL: + name = "kernel consumer"; + break; + case LTTNG_CONSUMER64_UST: + name = "64-bit user space consumer"; + break; + case LTTNG_CONSUMER32_UST: + name = "32-bit user space consumer"; + break; + case LTTNG_CONSUMER_UNKNOWN: + name = "unknown consumer"; + break; + } + + return format_to(ctx.out(), name); + } +}; +} /* namespace fmt */ + enum consumer_endpoint_status { CONSUMER_ENDPOINT_ACTIVE, CONSUMER_ENDPOINT_INACTIVE, diff --git a/src/common/defaults.hpp b/src/common/defaults.hpp index a2664a433..8ca8bc026 100644 --- a/src/common/defaults.hpp +++ b/src/common/defaults.hpp @@ -43,10 +43,9 @@ #define DEFAULT_HT_SIZE 4 /* Default session daemon paths */ -#define DEFAULT_HOME_DIR "/tmp" -#define DEFAULT_UST_SOCK_DIR DEFAULT_HOME_DIR "/ust-app-socks" -#define DEFAULT_GLOBAL_APPS_PIPE DEFAULT_UST_SOCK_DIR "/global" -#define DEFAULT_TRACE_OUTPUT DEFAULT_HOME_DIR "/lttng" +#define DEFAULT_HOME_DIR "/tmp" +#define DEFAULT_UST_SOCK_DIR DEFAULT_HOME_DIR "/ust-app-socks" +#define DEFAULT_TRACE_OUTPUT DEFAULT_HOME_DIR "/lttng" /* Default directory where the trace are written in per domain */ #define DEFAULT_KERNEL_TRACE_DIR "kernel" @@ -107,7 +106,9 @@ #define DEFAULT_LTTNG_FALLBACK_HOME_ENV_VAR "HOME" #define DEFAULT_LTTNG_UST_CTL_PATH_ENV_VAR "LTTNG_UST_CTL_PATH" #define DEFAULT_LTTNG_UST_APP_PATH_ENV_VAR "LTTNG_UST_APP_PATH" +#define DEFAULT_LTTNG_RUNDIR_ENV_VAR "LTTNG_RUNDIR" #define DEFAULT_LTTNG_RUNDIR CONFIG_LTTNG_SYSTEM_RUNDIR +#define DEFAULT_LTTNG_EXPLICIT_RUNDIR "%s" #define DEFAULT_LTTNG_HOME_RUNDIR "%s/.lttng" #define DEFAULT_LTTNG_SESSIOND_PIDFILE "lttng-sessiond.pid" #define DEFAULT_LTTNG_SESSIOND_AGENTPORT_FILE "agent.port" @@ -120,27 +121,20 @@ #define DEFAULT_LTTNG_EXTRA_KMOD_PROBES "LTTNG_EXTRA_KMOD_PROBES" /* Default unix socket path */ -#define DEFAULT_GLOBAL_CLIENT_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/client-lttng-sessiond" -#define DEFAULT_HOME_CLIENT_UNIX_SOCK DEFAULT_LTTNG_HOME_RUNDIR "/client-lttng-sessiond" -#define DEFAULT_GLOBAL_HEALTH_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/sessiond-health" -#define DEFAULT_HOME_HEALTH_UNIX_SOCK DEFAULT_LTTNG_HOME_RUNDIR "/sessiond-health" -#define DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/sessiond-notification" -#define DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK \ - DEFAULT_LTTNG_HOME_RUNDIR "/sessiond-notification" +#define DEFAULT_CLIENT_UNIX_SOCK DEFAULT_LTTNG_EXPLICIT_RUNDIR "/client-lttng-sessiond" +#define DEFAULT_HEALTH_UNIX_SOCK DEFAULT_LTTNG_EXPLICIT_RUNDIR "/sessiond-health" +#define DEFAULT_NOTIFICATION_CHANNEL_UNIX_SOCK \ + DEFAULT_LTTNG_EXPLICIT_RUNDIR "/sessiond-notification" /* Default consumer health unix socket path */ -#define DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/ustconsumerd32/health" -#define DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK \ - DEFAULT_LTTNG_HOME_RUNDIR "/ustconsumerd32/health" -#define DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/ustconsumerd64/health" -#define DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK \ - DEFAULT_LTTNG_HOME_RUNDIR "/ustconsumerd64/health" -#define DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/kconsumerd/health" -#define DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK DEFAULT_LTTNG_HOME_RUNDIR "/kconsumerd/health" +#define DEFAULT_USTCONSUMER32_HEALTH_UNIX_SOCK \ + DEFAULT_LTTNG_EXPLICIT_RUNDIR "/ustconsumerd32/health" +#define DEFAULT_USTCONSUMER64_HEALTH_UNIX_SOCK \ + DEFAULT_LTTNG_EXPLICIT_RUNDIR "/ustconsumerd64/health" +#define DEFAULT_KCONSUMER_HEALTH_UNIX_SOCK DEFAULT_LTTNG_EXPLICIT_RUNDIR "/kconsumerd/health" /* Default relay health unix socket path */ -#define DEFAULT_GLOBAL_RELAY_HEALTH_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/relayd/health-%d" -#define DEFAULT_HOME_RELAY_HEALTH_UNIX_SOCK DEFAULT_LTTNG_HOME_RUNDIR "/relayd/health-%d" +#define DEFAULT_RELAY_HEALTH_UNIX_SOCK DEFAULT_LTTNG_EXPLICIT_RUNDIR "/relayd/health-%d" /* Default daemon configuration file path */ #define DEFAULT_SYSTEM_CONFIGPATH \ @@ -150,6 +144,7 @@ #define DEFAULT_DAEMON_CONFIG_FILE "lttng.conf" #define DEFAULT_DAEMON_HOME_CONFIGPATH DEFAULT_LTTNG_HOME_RUNDIR "/" DEFAULT_DAEMON_CONFIG_FILE #define DEFAULT_DAEMON_SYSTEM_CONFIGPATH DEFAULT_SYSTEM_CONFIGPATH "/" DEFAULT_DAEMON_CONFIG_FILE +#define DEFAULT_DAEMON_CONFIGPATH DEFAULT_LTTNG_EXPLICIT_RUNDIR "/" DEFAULT_DAEMON_CONFIG_FILE /* Default session configuration file path */ #define DEFAULT_SESSION_PATH "sessions" @@ -157,13 +152,13 @@ #define DEFAULT_SESSION_CONFIG_AUTOLOAD "auto" #define DEFAULT_SESSION_HOME_CONFIGPATH DEFAULT_LTTNG_HOME_RUNDIR "/" DEFAULT_SESSION_PATH #define DEFAULT_SESSION_SYSTEM_CONFIGPATH DEFAULT_SYSTEM_CONFIGPATH "/" DEFAULT_SESSION_PATH +#define DEFAULT_SESSION_CONFIGPATH DEFAULT_LTTNG_EXPLICIT_RUNDIR "/" DEFAULT_SESSION_PATH #define DEFAULT_SESSION_CONFIG_FILE_EXTENSION ".lttng" #define DEFAULT_SESSION_CONFIG_XSD_FILENAME "session.xsd" #define DEFAULT_SESSION_CONFIG_XSD_PATH CONFIG_LTTNG_SYSTEM_DATADIR "/xml/lttng/" #define DEFAULT_SESSION_CONFIG_XSD_PATH_ENV "LTTNG_SESSION_CONFIG_XSD_PATH" -#define DEFAULT_GLOBAL_APPS_UNIX_SOCK DEFAULT_LTTNG_RUNDIR "/" LTTNG_UST_SOCK_FILENAME -#define DEFAULT_HOME_APPS_UNIX_SOCK DEFAULT_LTTNG_HOME_RUNDIR "/" LTTNG_UST_SOCK_FILENAME +#define DEFAULT_APPS_UNIX_SOCK DEFAULT_LTTNG_EXPLICIT_RUNDIR "/" LTTNG_UST_SOCK_FILENAME #define DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH "/" LTTNG_UST_WAIT_FILENAME #define DEFAULT_HOME_APPS_WAIT_SHM_PATH DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH "-%d" diff --git a/src/common/exception.cpp b/src/common/exception.cpp index 9288aaa07..a41aea16d 100644 --- a/src/common/exception.cpp +++ b/src/common/exception.cpp @@ -31,6 +31,12 @@ lttng::runtime_error::runtime_error(const std::string& msg, { } +lttng::allocation_failure::allocation_failure(const std::string& msg, + const lttng::source_location& location) : + lttng::runtime_error(msg, location) +{ +} + lttng::allocation_failure::allocation_failure(const std::string& msg, std::size_t allocation_size_, const lttng::source_location& location) : diff --git a/src/common/exception.hpp b/src/common/exception.hpp index da6997d42..1d53e6402 100644 --- a/src/common/exception.hpp +++ b/src/common/exception.hpp @@ -12,6 +12,8 @@ #include +#include + #include #include #include @@ -24,7 +26,9 @@ throw lttng::posix_error(msg, errno_code, LTTNG_SOURCE_LOCATION()) #define LTTNG_THROW_ERROR(msg) throw lttng::runtime_error(msg, LTTNG_SOURCE_LOCATION()) #define LTTNG_THROW_OUT_OF_RANGE(msg) throw lttng::out_of_range(msg, LTTNG_SOURCE_LOCATION()) -#define LTTNG_THROW_ALLOCATION_FAILURE_ERROR(msg, allocation_size) \ +#define LTTNG_THROW_ALLOCATION_FAILURE_ERROR(msg) \ + throw lttng::allocation_failure(msg, LTTNG_SOURCE_LOCATION()) +#define LTTNG_THROW_ALLOCATION_FAILURE_WITH_SIZE_ERROR(msg, allocation_size) \ throw lttng::allocation_failure(msg, allocation_size, LTTNG_SOURCE_LOCATION()) #define LTTNG_THROW_UNSUPPORTED_ERROR(msg) \ throw lttng::unsupported_error(msg, LTTNG_SOURCE_LOCATION()) @@ -104,11 +108,13 @@ public: */ class allocation_failure : public lttng::runtime_error { public: + explicit allocation_failure(const std::string& msg, + const lttng::source_location& source_location); explicit allocation_failure(const std::string& msg, std::size_t allocation_size, const lttng::source_location& source_location); - std::size_t allocation_size; + nonstd::optional allocation_size; }; /* diff --git a/src/common/format.hpp b/src/common/format.hpp index 59ed1637c..6334aaecb 100644 --- a/src/common/format.hpp +++ b/src/common/format.hpp @@ -8,6 +8,7 @@ #define LTTNG_FORMAT_H #include +#include #include #include diff --git a/src/common/utils.cpp b/src/common/utils.cpp index 0f9fae763..701a9f275 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -782,6 +782,60 @@ char *utils_get_lttng_ust_ctl_path_override_dir() return new_val; } +/* + * Get configured run directory. Dynamically allocated, must be freed + * by the caller. + */ +char *utils_get_rundir(gid_t tracing_group_id) +{ + char *run_dir = nullptr; + int ret = -1; + + const auto *run_dir_env = lttng_secure_getenv(DEFAULT_LTTNG_RUNDIR_ENV_VAR); + if (run_dir_env) { + run_dir = strdup(run_dir_env); + if (!run_dir) { + PERROR("Failed to duplicate `%s` environment variable contents", + DEFAULT_LTTNG_RUNDIR_ENV_VAR); + return nullptr; + } + } else { + /* + * Legacy behaviour: if the user is root, use the system rundir. + * Else, use the HOME_RUNDIR. + */ + if (getuid() == 0 || tracing_group_id != 0) { + run_dir = strdup(DEFAULT_LTTNG_RUNDIR); + if (!run_dir) { + PERROR("Failed to duplicate default run directory path"); + return nullptr; + } + } else { + const auto *home_dir = utils_get_home_dir(); + if (!home_dir) { + ERR("Failed to get home directory while determining run directory path"); + return nullptr; + } + + ret = asprintf(&run_dir, DEFAULT_LTTNG_HOME_RUNDIR, home_dir); + if (ret < 0) { + /* + * The contents of run_dir during an error may be undefined. Set + * the value to nullptr to avoid a potentially non-pointer from + * being returned. + */ + run_dir = nullptr; + PERROR("Failed to format run directory path: default_home_rundir=`%s`, home_dir=`%s`", + DEFAULT_LTTNG_HOME_RUNDIR, + home_dir); + return nullptr; + } + } + } + + return run_dir; +} + /* * Get user's home directory. Dynamically allocated, must be freed * by the caller. diff --git a/src/common/utils.hpp b/src/common/utils.hpp index ed9cff805..a15aa02a7 100644 --- a/src/common/utils.hpp +++ b/src/common/utils.hpp @@ -42,6 +42,7 @@ int utils_parse_size_suffix(const char *const str, uint64_t *const size); int utils_parse_time_suffix(const char *const str, uint64_t *const time_us); int utils_get_count_order_u32(uint32_t x); int utils_get_count_order_u64(uint64_t x); +char *utils_get_rundir(gid_t tracing_group); const char *utils_get_home_dir(); char *utils_get_user_home_dir(uid_t uid); char *utils_get_lttng_ust_ctl_path_override_dir(); diff --git a/src/lib/lttng-ctl/channel.cpp b/src/lib/lttng-ctl/channel.cpp index a5ad2843c..9e5fc409c 100644 --- a/src/lib/lttng-ctl/channel.cpp +++ b/src/lib/lttng-ctl/channel.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,8 @@ #include #include +#include + static int handshake(struct lttng_notification_channel *channel); /* @@ -134,16 +137,15 @@ struct lttng_notification_channel * lttng_notification_channel_create(struct lttng_endpoint *endpoint) { int fd, ret; - bool is_in_tracing_group = false, is_root = false; - char *sock_path = nullptr; struct lttng_notification_channel *channel = nullptr; - if (!endpoint || endpoint != lttng_session_daemon_notification_endpoint) { - goto end; + const auto rundir_path = + lttng::make_unique_wrapper(utils_get_rundir(0)); + if (!rundir_path) { + goto error; } - sock_path = calloc(LTTNG_PATH_MAX); - if (!sock_path) { + if (!endpoint || endpoint != lttng_session_daemon_notification_endpoint) { goto end; } @@ -151,56 +153,42 @@ lttng_notification_channel_create(struct lttng_endpoint *endpoint) if (!channel) { goto end; } + channel->socket = -1; pthread_mutex_init(&channel->lock, nullptr); lttng_payload_init(&channel->reception_payload); CDS_INIT_LIST_HEAD(&channel->pending_notifications.list); - is_root = (getuid() == 0); - if (!is_root) { - is_in_tracing_group = lttng_check_tracing_group(); - } - - if (is_root || is_in_tracing_group) { - ret = lttng_strncpy( - sock_path, DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK, LTTNG_PATH_MAX); - if (ret) { - ret = -LTTNG_ERR_INVALID; + { + const auto length = std::snprintf( + nullptr, 0, DEFAULT_NOTIFICATION_CHANNEL_UNIX_SOCK, rundir_path.get()) + 1; + + std::vector sock_path; + sock_path.reserve(length); + ret = std::snprintf(sock_path.data(), + length, + DEFAULT_NOTIFICATION_CHANNEL_UNIX_SOCK, + rundir_path.get()); + if (ret < 0 || ret >= LTTNG_PATH_MAX) { goto error; } - ret = lttcomm_connect_unix_sock(sock_path); - if (ret >= 0) { - fd = ret; - goto set_fd; + ret = lttcomm_connect_unix_sock(sock_path.data()); + if (ret < 0) { + goto error; } } - /* Fallback to local session daemon. */ - ret = snprintf(sock_path, - LTTNG_PATH_MAX, - DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK, - utils_get_home_dir()); - if (ret < 0 || ret >= LTTNG_PATH_MAX) { - goto error; - } - - ret = lttcomm_connect_unix_sock(sock_path); - if (ret < 0) { - goto error; - } fd = ret; - -set_fd: channel->socket = fd; - ret = handshake(channel); if (ret) { goto error; } + end: - free(sock_path); return channel; + error: lttng_notification_channel_destroy(channel); channel = nullptr; diff --git a/src/lib/lttng-ctl/lttng-ctl-health.cpp b/src/lib/lttng-ctl/lttng-ctl-health.cpp index c490f8993..41c2cf3ee 100644 --- a/src/lib/lttng-ctl/lttng-ctl-health.cpp +++ b/src/lib/lttng-ctl/lttng-ctl-health.cpp @@ -149,30 +149,23 @@ static const char *get_thread_name(int comp, int nr) */ static int set_health_socket_path(struct lttng_health *lh, int tracing_group) { - uid_t uid; - const char *home; int ret; - /* Global and home format strings */ - const char *global_str, *home_str; + const char *health_unix_sock_fmt_string; switch (lh->component) { case HEALTH_COMPONENT_SESSIOND: - global_str = DEFAULT_GLOBAL_HEALTH_UNIX_SOCK; - home_str = DEFAULT_HOME_HEALTH_UNIX_SOCK; + health_unix_sock_fmt_string = DEFAULT_HEALTH_UNIX_SOCK; break; case HEALTH_COMPONENT_CONSUMERD: switch (lh->consumerd_type) { case LTTNG_HEALTH_CONSUMERD_UST_32: - global_str = DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK; - home_str = DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK; + health_unix_sock_fmt_string = DEFAULT_USTCONSUMER32_HEALTH_UNIX_SOCK; break; case LTTNG_HEALTH_CONSUMERD_UST_64: - global_str = DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK; - home_str = DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK; + health_unix_sock_fmt_string = DEFAULT_USTCONSUMER64_HEALTH_UNIX_SOCK; break; case LTTNG_HEALTH_CONSUMERD_KERNEL: - global_str = DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK; - home_str = DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK; + health_unix_sock_fmt_string = DEFAULT_KCONSUMER_HEALTH_UNIX_SOCK; break; default: return -EINVAL; @@ -189,11 +182,11 @@ static int set_health_socket_path(struct lttng_health *lh, int tracing_group) return -EINVAL; } - uid = getuid(); - - if (uid == 0 || tracing_group) { - ret = lttng_strncpy(lh->health_sock_path, global_str, sizeof(lh->health_sock_path)); - return ret == 0 ? 0 : -EINVAL; + bool use_default_rundir_path = false; + auto rundir_path = lttng::make_unique_wrapper( + utils_get_rundir(tracing_group)); + if (!rundir_path) { + use_default_rundir_path = true; } /* @@ -201,18 +194,15 @@ static int set_health_socket_path(struct lttng_health *lh, int tracing_group) * is too small; With GNU C >= 2.1, snprintf returns the * required size (excluding closing null). */ - home = utils_get_home_dir(); - if (home == nullptr) { - /* Fallback in /tmp */ - home = "/tmp"; - } - DIAGNOSTIC_PUSH DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL - ret = snprintf(lh->health_sock_path, sizeof(lh->health_sock_path), home_str, home); + ret = snprintf(lh->health_sock_path, + sizeof(lh->health_sock_path), + health_unix_sock_fmt_string, + use_default_rundir_path ? DEFAULT_HOME_DIR : rundir_path.get()); DIAGNOSTIC_POP if ((ret < 0) || (ret >= sizeof(lh->health_sock_path))) { - return -ENOMEM; + return -EINVAL; } return 0; diff --git a/src/lib/lttng-ctl/lttng-ctl.cpp b/src/lib/lttng-ctl/lttng-ctl.cpp index c5c04c262..73bfd0db7 100644 --- a/src/lib/lttng-ctl/lttng-ctl.cpp +++ b/src/lib/lttng-ctl/lttng-ctl.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -404,12 +405,19 @@ static int set_session_daemon_path() in_tgroup = lttng_check_tracing_group(); } + auto rundir = lttng::make_unique_wrapper(); if ((uid == 0) || in_tgroup == 1) { - const int ret = lttng_strncpy(sessiond_sock_path, - DEFAULT_GLOBAL_CLIENT_UNIX_SOCK, - sizeof(sessiond_sock_path)); + int ret = -1; - if (ret) { + rundir.reset(utils_get_rundir(in_tgroup)); + if (!rundir) { + goto error; + } + ret = snprintf(sessiond_sock_path, + sizeof(sessiond_sock_path), + DEFAULT_CLIENT_UNIX_SOCK, + rundir.get()); + if ((ret < 0) || (ret >= sizeof(sessiond_sock_path))) { goto error; } } @@ -417,6 +425,11 @@ static int set_session_daemon_path() if (uid != 0) { int ret; + rundir.reset(utils_get_rundir(0)); + if (!rundir) { + goto error; + } + if (in_tgroup) { /* Tracing group. */ ret = try_connect_sessiond(sessiond_sock_path); @@ -435,8 +448,8 @@ static int set_session_daemon_path() */ ret = snprintf(sessiond_sock_path, sizeof(sessiond_sock_path), - DEFAULT_HOME_CLIENT_UNIX_SOCK, - utils_get_home_dir()); + DEFAULT_CLIENT_UNIX_SOCK, + rundir.get()); if ((ret < 0) || (ret >= sizeof(sessiond_sock_path))) { goto error; } diff --git a/tests/regression/tools/config-directory/test_config.py.in b/tests/regression/tools/config-directory/test_config.py.in index 016634713..11b0ad4a1 100755 --- a/tests/regression/tools/config-directory/test_config.py.in +++ b/tests/regression/tools/config-directory/test_config.py.in @@ -141,6 +141,42 @@ tests = { "substitutions": DEFAULT_SUBSTITUTIONS, "expected_paths": _ust_ctl_path_expected_paths, }, + "lttng_rundir": { + "description": "LTTng with LTTNG_RUNDIR set", + "environment_variables": { + "LTTNG_RUNDIR": True, + }, + "substitutions": DEFAULT_SUBSTITUTIONS, + "expected_paths": DEFAULT_EXPECTED_PATHS, + }, + "lttng_home_and_rundir": { + "description": "LTTng with LTTNG_RUNDIR and LTTNG_HOME set", + "environment_variables": { + "LTTNG_RUNDIR": True, + "LTTNG_HOME": True, + }, + "substitutions": DEFAULT_SUBSTITUTIONS, + "expected_paths": DEFAULT_EXPECTED_PATHS, + }, + "lttng_rundir_and_ust_ctl_path": { + "description": "LTTng with LTTNG_RUNDIR and LTTNG_UST_CTL_PATH set", + "environment_variables": { + "LTTNG_RUNDIR": True, + "LTTNG_UST_CTL_PATH": True, + }, + "substitutions": DEFAULT_SUBSTITUTIONS, + "expected_paths": _ust_ctl_path_expected_paths, + }, + "lttng_home_and_rundir_and_ust_ctl_path": { + "description": "LTTng with LTTNG_RUNDIR, LTTNG_HOME, and LTTNG_UST_CTL_PATH set", + "environment_variables": { + "LTTNG_RUNDIR": True, + "LTTNG_HOME": True, + "LTTNG_UST_CTL_PATH": True, + }, + "substitutions": DEFAULT_SUBSTITUTIONS, + "expected_paths": _ust_ctl_path_expected_paths, + }, } @@ -171,7 +207,9 @@ def test_config_and_socket_paths( substitutions["RELAYD_PID"] = test_env._relayd.pid - client = lttngtest.LTTngClient(test_env, log=tap.diagnostic) + client = lttngtest.LTTngClient( + test_env, log=tap.diagnostic, extra_env_vars=environment_variables + ) session_output_location = lttngtest.LocalSessionOutputLocation( test_env.create_temporary_directory("trace") ) @@ -193,6 +231,8 @@ def test_config_and_socket_paths( test_app.wait_for_exit() errors = [] + if "LTTNG_RUNDIR" in environment_variables: + os.system("find {}".format(environment_variables["LTTNG_RUNDIR"])) for path_id, path_conf in expected_paths.items(): path = path_conf["path"] while re.search("\{\w+\}", path) is not None: @@ -267,6 +307,10 @@ if __name__ == "__main__": -1 ].name temp_conf["substitutions"]["LTTNG_UST_CTL_PATH"] = tempfiles[-1].name + if "LTTNG_RUNDIR" in test_configuration["environment_variables"]: + tempfiles.append(tempfile.TemporaryDirectory()) + temp_conf["environment_variables"]["LTTNG_RUNDIR"] = tempfiles[-1].name + temp_conf["substitutions"]["RUNDIR"] = tempfiles[-1].name with lttngtest.test_environment( with_sessiond=True, log=tap.diagnostic, diff --git a/tests/regression/ust/ust-app-ctl-paths/test_blocking b/tests/regression/ust/ust-app-ctl-paths/test_blocking index ed587938f..104352ba9 100755 --- a/tests/regression/ust/ust-app-ctl-paths/test_blocking +++ b/tests/regression/ust/ust-app-ctl-paths/test_blocking @@ -10,7 +10,7 @@ TEST_DESC="Verifies that the sessiond starts (or doesn't start) appropriately de CURDIR="$(dirname "${0}")" TESTDIR="${CURDIR}/../../../" -NUM_TESTS=33 +NUM_TESTS=34 # shellcheck source=../../../utils/utils.sh source "${TESTDIR}/utils/utils.sh" @@ -46,7 +46,7 @@ function test_blocking_mode_app_path() rm -rf "${APP_PATH}" "${TRACE_PATH}" } -function test_blocking_mode_defaults_paths() +function test_blocking_mode_default_paths() { diag "Test starting sessiond in blocking with neither LTTNG_UST_APP_PATH nor LTTNG_UST_CTL_PATH set" env_vars=( diff --git a/tests/regression/ust/ust-app-ctl-paths/test_ust_app_ctl_paths b/tests/regression/ust/ust-app-ctl-paths/test_ust_app_ctl_paths index d5c43870f..d57e9794d 100755 --- a/tests/regression/ust/ust-app-ctl-paths/test_ust_app_ctl_paths +++ b/tests/regression/ust/ust-app-ctl-paths/test_ust_app_ctl_paths @@ -75,12 +75,6 @@ function test_sessiond_started_after_app() function test_multi_sessiond() { - # Multiple root sessionds cannot be started - if [ "${UID}" == "0" ] ; then - skip 0 "Multiple root sessionds aren't supported" 28 - return - fi - N_SESSIOND=3 CTL_PATH_BASE="$(mktemp -d -t "tmp.${FUNCNAME[0]}.ctl.XXXXXX")" TRACE_PATH_BASE="$(mktemp -d -t "tmp.${FUNCNAME[0]}.trace.XXXXXX")" @@ -97,6 +91,9 @@ function test_multi_sessiond() LTTNG_UST_CTL_PATH="${CTL_PATH}" TEST_IGNORE_EXISTING_SESSIOND=1 ) + if [ "${UID}" == "0" ] ; then + env_vars+=(LTTNG_RUNDIR="${LTTNG_HOME_BASE}/$i") + fi # shellcheck disable=SC2119 LTTNG_SESSIOND_ENV_VARS="${env_vars[*]}" start_lttng_sessiond export "${env_vars[@]}" @@ -105,6 +102,7 @@ function test_multi_sessiond() enable_ust_lttng_event_ok "${SESSION_NAME}" "--all" "${CHANNEL_NAME}" start_lttng_tracing_ok "${SESSION_NAME}" unset LTTNG_HOME + unset LTTNG_RUNDIR unset LTTNG_UST_CTL_PATH done for i in $(seq 1 "${N_SESSIOND}") ; do @@ -114,10 +112,13 @@ function test_multi_sessiond() env_vars=( LTTNG_HOME="${LTTNG_HOME_BASE}/$i" ) + if [ "${UID}" == "0" ] ; then + env_vars+=(LTTNG_RUNDIR="${LTTNG_HOME_BASE}/$i") + fi export "${env_vars[@]}" stop_lttng_tracing_ok "${SESSION_NAME}" destroy_lttng_session_ok "${SESSION_NAME}" --no-wait - unset LTTNG_HOME + unset LTTNG_HOME LTTNG_RUNDIR validate_trace_count "${EVENT_NAMES}" "${TRACE_PATH_BASE}/$i" 100 done # shellcheck disable=SC2119 @@ -135,12 +136,6 @@ function test_multi_sessiond_default() { diag "Verifies that the lttng_session_daemon_alive()/set_session_daemon_path() in liblttng is coherent with LTTNG_UST_CTL_PATH" - # Multiple root sessionds cannot be started - if [ "${UID}" == "0" ] ; then - skip 0 "Multiple root sessionds aren't supported" 11 - return - fi - LTTNG_HOME_B="$(mktemp -d -t "tmp.${FUNCNAME[0]}.lttng-home.XXXXXX")" TRACE_PATH="$(mktemp -d -t "tmp.${FUNCNAME[0]}.trace.XXXXXX")" LTTNG_HOME_ORIG="${LTTNG_HOME}" @@ -153,6 +148,10 @@ function test_multi_sessiond_default() LTTNG_HOME="${LTTNG_HOME_B}" TEST_IGNORE_EXISTING_SESSIOND=1 ) + if [ "${UID}" == "0" ] ; then + env_vars_b+=(LTTNG_RUNDIR="${LTTNG_HOME_B}") + LTTNG_UST_APP_PATH="${LTTNG_HOME_B}" + fi export "${env_vars_b[@]}" # shellcheck disable=SC2119 LTTNG_SESSIOND_ENV_VARS="${env_vars_b[*]}" start_lttng_sessiond @@ -170,7 +169,7 @@ function test_multi_sessiond_default() # shellcheck disable=SC2119 stop_lttng_sessiond - unset LTTNG_HOME TEST_IGNORE_EXISTING_SESSIOND + unset LTTNG_HOME LTTNG_RUNDIR TEST_IGNORE_EXISTING_SESSIOND if [ "${LTTNG_HOME_ORIG}" != "" ] ; then export LTTNG_HOME="${LTTNG_HOME_ORIG}" fi @@ -179,11 +178,6 @@ function test_multi_sessiond_default() function test_trace_another_sessiond() { - if [ "${UID}" == "0" ] ; then - skip 0 "Multiple root sessionds aren't supported" 18 - return - fi - CTL_PATH="$(mktemp -d -t "tmp.${FUNCNAME[0]}.ctl.XXXXXX")" TRACE_PATH_A="$(mktemp -d -t "tmp.${FUNCNAME[0]}.trace_a.XXXXXX")" TRACE_PATH_B="$(mktemp -d -t "tmp.${FUNCNAME[0]}.trace_b.XXXXXX")" @@ -196,6 +190,9 @@ function test_trace_another_sessiond() LTTNG_HOME="${LTTNG_HOME_A}" TEST_IGNORE_EXISTING_SESSIOND=1 ) + if [ "${UID}" == "0" ] ; then + env_vars_a+=(LTTNG_RUNDIR="${LTTNG_HOME_A}") + fi export "${env_vars_a[@]}" # shellcheck disable=SC2119 @@ -204,7 +201,7 @@ function test_trace_another_sessiond() enable_ust_lttng_channel_ok "${SESSION_NAME}" "${CHANNEL_NAME}" enable_ust_lttng_event_ok "${SESSION_NAME}" "--all" "${CHANNEL_NAME}" start_lttng_tracing_ok "${SESSION_NAME}" - unset LTTNG_HOME LTTNG_UST_CTL_PATH + unset LTTNG_HOME LTTNG_RUNDIR LTTNG_UST_CTL_PATH if [ "${LTTNG_HOME_ORIG}" != "" ] ; then export LTTNG_HOME="${LTTNG_HOME_ORIG}" @@ -228,9 +225,10 @@ function test_trace_another_sessiond() stop_lttng_tracing_ok "${SESSION_NAME}" destroy_lttng_session_ok "${SESSION_NAME}" --no-wait validate_trace_count "${EVENT_NAMES}" "${TRACE_PATH_B}" 100 + unset LTTNG_HOME LTTNG_RUNDIR LTTNG_UST_CTL_PATH TEST_IGNORE_EXISTING_SESSIOND # Confirm that we get traced data from the subordinate sessiond - export LTTNG_HOME="${LTTNG_HOME_A}" + export "${env_vars_a[@]}" stop_lttng_tracing_ok "${SESSION_NAME}" destroy_lttng_session_ok "${SESSION_NAME}" --no-wait EVENT_COUNT="$("${BABELTRACE_BIN}" "${TRACE_PATH_A}" | wc -l)" @@ -241,7 +239,7 @@ function test_trace_another_sessiond() # Cleanup rm -rf "${TRACE_PATH_A}" "{$TRACE_PATH_B}" "${LTTNG_HOME_A}" "${CTL_PATH}" - unset LTTNG_HOME LTTNG_UST_CTL_PATH TEST_IGNORE_EXISTING_SESSIOND + unset LTTNG_HOME LTTNG_RUNDIR LTTNG_UST_CTL_PATH TEST_IGNORE_EXISTING_SESSIOND if [ "${LTTNG_HOME_ORIG}" != "" ] ; then export LTTNG_HOME="${LTTNG_HOME_ORIG}" fi diff --git a/tests/utils/lttngtest/lttng.py b/tests/utils/lttngtest/lttng.py index 3365cd0d8..31575a68e 100644 --- a/tests/utils/lttngtest/lttng.py +++ b/tests/utils/lttngtest/lttng.py @@ -658,9 +658,11 @@ class LTTngClient(logger._Logger, lttngctl.Controller): self, test_environment, # type: environment._Environment log, # type: Optional[Callable[[str], None]] + extra_env_vars=dict(), # type: dict ): logger._Logger.__init__(self, log) self._environment = test_environment # type: environment._Environment + self._extra_env_vars = extra_env_vars @staticmethod def _namespaced_mi_element(property): @@ -684,6 +686,7 @@ class LTTngClient(logger._Logger, lttngctl.Controller): client_env = os.environ.copy() # type: dict[str, str] if self._environment.lttng_home_location is not None: client_env["LTTNG_HOME"] = str(self._environment.lttng_home_location) + client_env.update(self._extra_env_vars) process = subprocess.Popen( args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=client_env -- 2.34.1