From 3f883a5ecf3e76acfae0f2e306348421ab68d7e9 Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Thu, 23 Nov 2023 14:16:21 -0500 Subject: [PATCH] sessiond: exit early if it's possible to self-trace with blocking mode set MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Kienan Stewart Signed-off-by: Jérémie Galarneau Change-Id: I13e76160135e1cd9f0cb7d5ebe16e9662c1aee56 --- src/bin/lttng-sessiond/main.cpp | 106 ++++++++++++++++++++++++++++++++ src/common/defaults.hpp | 1 + src/common/path.cpp | 2 +- src/common/path.hpp | 1 + 4 files changed, 109 insertions(+), 1 deletion(-) diff --git a/src/bin/lttng-sessiond/main.cpp b/src/bin/lttng-sessiond/main.cpp index 0902969e7..cb3896e27 100644 --- a/src/bin/lttng-sessiond/main.cpp +++ b/src/bin/lttng-sessiond/main.cpp @@ -49,11 +49,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -64,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -939,6 +942,97 @@ end: return ret; } +namespace { +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); + } + + return std::string(dirname(dir_copy.get())); +} + +/* + * Check to see if there the settings of LTTNG_UST_APP_PATH and LTTNG_UST_CTL_PATH + * are such that the sessiond could potentially trace itself while blocking mode + * can be enabled for any of the sessions. + * + * Throws lttng::unsupported_error is the configuration is illegal. + */ +void check_trace_self_blocking() +{ + const auto *allow_blocking = lttng_secure_getenv("LTTNG_UST_ALLOW_BLOCKING"); + if (!allow_blocking) { + return; + } + + const auto *ust_app_path = lttng_secure_getenv(DEFAULT_LTTNG_UST_APP_PATH_ENV_VAR); + const auto *ust_ctl_path = lttng_secure_getenv(DEFAULT_LTTNG_UST_CTL_PATH_ENV_VAR); + if (ust_app_path == nullptr && ust_ctl_path == nullptr) { + /* Session daemon could block, disallow this configuration. */ + LTTNG_THROW_UNSUPPORTED_ERROR( + "Cannot launch session daemon with LTTNG_UST_ALLOW_BLOCKING set using default application and control paths"); + } + + /* Use the resolved ctl path from the configuration. */ + ust_ctl_path = the_config.apps_unix_sock_path.value; + LTTNG_ASSERT(ust_ctl_path); + + std::string canonical_ust_app_path; + const auto canonical_ust_ctl_path = lttng::make_unique_wrapper( + utils_partial_realpath(dirname_str(ust_ctl_path).c_str())); + if (!canonical_ust_ctl_path) { + LTTNG_THROW_ERROR("Failed to determine canonical ust-ctl path from override"); + } + + /* + * When the environment variable for ust app path isn't set, assume it + * will be in the rundir. This might not actually be correct when root. + */ + if (!ust_app_path) { + ust_app_path = the_config.rundir.value; + LTTNG_ASSERT(the_config.rundir.value); + + auto resolved_app_path = lttng::make_unique_wrapper( + utils_partial_realpath(ust_app_path)); + if (!resolved_app_path) { + LTTNG_THROW_ERROR( + "Failed to determine canonical ust app path from override"); + } + + canonical_ust_app_path = resolved_app_path.get(); + } else { + /* + * Find the position of ':' or the end of the c-string in case the variable is a + * list of values. + */ + const auto end = + std::find(ust_app_path, ust_app_path + std::strlen(ust_app_path), ':'); + + std::string first_entry_of_list; + std::copy(ust_app_path, end, std::back_inserter(first_entry_of_list)); + + auto resolved_app_path = lttng::make_unique_wrapper( + utils_partial_realpath(first_entry_of_list.c_str())); + if (!resolved_app_path) { + LTTNG_THROW_ERROR( + "Failed to determine canonical ust app path from override"); + } + + canonical_ust_app_path = resolved_app_path.get(); + } + + if (canonical_ust_app_path != canonical_ust_ctl_path.get()) { + return; + } + + LTTNG_THROW_UNSUPPORTED_ERROR("Cannot trace self with LTTNG_UST_ALLOW_BLOCKING set"); +} +} /* namespace */ + static void sessiond_cleanup_lock_file() { int ret; @@ -1488,6 +1582,18 @@ static int _main(int argc, char **argv) sessiond_uuid_log(); lttng::logging::log_system_information(PRINT_DBG); + /* + * If the lttng-sessiond may trace itself, stop startup if blocking mode + * is allowed by the LTTNG_UST_ALLOW_BLOCKING environment variable. + */ + try { + check_trace_self_blocking(); + } catch (const std::exception& ex) { + ERR_FMT(ex.what()); + retval = -1; + goto exit_options; + } + if (opt_print_version) { print_version(); retval = 0; diff --git a/src/common/defaults.hpp b/src/common/defaults.hpp index 8fbe819f3..a2664a433 100644 --- a/src/common/defaults.hpp +++ b/src/common/defaults.hpp @@ -106,6 +106,7 @@ #define DEFAULT_LTTNG_HOME_ENV_VAR "LTTNG_HOME" #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 CONFIG_LTTNG_SYSTEM_RUNDIR #define DEFAULT_LTTNG_HOME_RUNDIR "%s/.lttng" #define DEFAULT_LTTNG_SESSIOND_PIDFILE "lttng-sessiond.pid" diff --git a/src/common/path.cpp b/src/common/path.cpp index 14611c216..c4fb41e23 100644 --- a/src/common/path.cpp +++ b/src/common/path.cpp @@ -21,7 +21,7 @@ * * Return a newly-allocated string. */ -static char *utils_partial_realpath(const char *path) +char *utils_partial_realpath(const char *path) { char *cut_path = nullptr, *try_path = nullptr, *try_path_prev = nullptr; const char *next, *prev, *end; diff --git a/src/common/path.hpp b/src/common/path.hpp index 3f81eeb20..19d9e0563 100644 --- a/src/common/path.hpp +++ b/src/common/path.hpp @@ -9,5 +9,6 @@ char *utils_expand_path(const char *path); char *utils_expand_path_keep_symlink(const char *path); +char *utils_partial_realpath(const char *path); #endif /* _COMMON_PATH_H */ -- 2.34.1