2 * SPDX-License-Identifier: LGPL-2.1-only
4 * Copyright (C) 2017 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
11 #include <sys/types.h>
13 #include <urcu/system.h>
14 #include "common/logging.h"
15 #include "common/macros.h"
16 #include "common/getenv.h"
18 enum lttng_env_secure
{
25 enum lttng_env_secure secure
;
29 /* lttng_ust_getenv_init_mutex provides mutual exclusion for initialization. */
30 static pthread_mutex_t lttng_ust_getenv_init_mutex
= PTHREAD_MUTEX_INITIALIZER
;
31 static int lttng_ust_getenv_is_init
= 0;
33 static struct lttng_env lttng_env
[] = {
35 * LTTNG_UST_DEBUG and LTTNG_UST_ABORT_ON_CRITICAL are used directly by
36 * the internal logging, because they need to be already set for ERR()
37 * used in lttng_ust_getenv_init().
39 { "LTTNG_UST_DEBUG", LTTNG_ENV_NOT_SECURE
, NULL
, },
40 { "LTTNG_UST_ABORT_ON_CRITICAL", LTTNG_ENV_NOT_SECURE
, NULL
, },
42 /* Env. var. which can be used in setuid/setgid executables. */
43 { "LTTNG_UST_WITHOUT_BADDR_STATEDUMP", LTTNG_ENV_NOT_SECURE
, NULL
, },
44 { "LTTNG_UST_REGISTER_TIMEOUT", LTTNG_ENV_NOT_SECURE
, NULL
, },
46 /* Env. var. which are not fetched in setuid/setgid executables. */
47 { "LTTNG_UST_CLOCK_PLUGIN", LTTNG_ENV_SECURE
, NULL
, },
48 { "LTTNG_UST_GETCPU_PLUGIN", LTTNG_ENV_SECURE
, NULL
, },
49 { "LTTNG_UST_ALLOW_BLOCKING", LTTNG_ENV_SECURE
, NULL
, },
50 { "HOME", LTTNG_ENV_SECURE
, NULL
, },
51 { "LTTNG_HOME", LTTNG_ENV_SECURE
, NULL
, },
52 { "LTTNG_UST_APP_PATH", LTTNG_ENV_SECURE
, NULL
, },
56 int lttng_is_setuid_setgid(void)
58 return geteuid() != getuid() || getegid() != getgid();
62 * Wrapper over getenv that will only return the values of whitelisted
63 * environment variables when the current process is setuid and/or setgid.
65 char *lttng_ust_getenv(const char *name
)
72 * Perform lazy initialization of lttng_ust_getenv for early use
73 * by library constructors.
75 lttng_ust_getenv_init();
77 for (i
= 0; i
< LTTNG_ARRAY_SIZE(lttng_env
); i
++) {
80 if (strcmp(e
->key
, name
) == 0) {
91 void lttng_ust_getenv_init(void)
96 * Return early if the init has already completed.
98 if (CMM_LOAD_SHARED(lttng_ust_getenv_is_init
)) {
100 * Load lttng_ust_getenv_is_init before reading environment cache.
106 pthread_mutex_lock(<tng_ust_getenv_init_mutex
);
109 * Check again if the init has completed in another thread now that we
110 * have acquired the mutex.
112 if (lttng_ust_getenv_is_init
)
115 for (i
= 0; i
< LTTNG_ARRAY_SIZE(lttng_env
); i
++) {
116 struct lttng_env
*e
= <tng_env
[i
];
118 if (e
->secure
== LTTNG_ENV_SECURE
&& lttng_is_setuid_setgid()) {
119 ERR("Getting environment variable '%s' from setuid/setgid binary refused for security reasons.",
123 e
->value
= getenv(e
->key
);
127 * Store environment cache before setting lttng_ust_getenv_is_init to 1.
130 CMM_STORE_SHARED(lttng_ust_getenv_is_init
, 1);
132 pthread_mutex_unlock(<tng_ust_getenv_init_mutex
);