7f7b85349fe597654b4a2c4700a0e392478275ed
[lttng-ust.git] / src / common / getenv.c
1 /*
2 * SPDX-License-Identifier: LGPL-2.1-only
3 *
4 * Copyright (C) 2017 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 */
6
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <stdbool.h>
10 #include <stddef.h>
11 #include <sys/types.h>
12 #include <pthread.h>
13 #include <urcu/system.h>
14 #include "common/logging.h"
15 #include "common/macros.h"
16 #include "common/getenv.h"
17
18 enum lttng_env_secure {
19 LTTNG_ENV_SECURE,
20 LTTNG_ENV_NOT_SECURE,
21 };
22
23 struct lttng_env {
24 const char *key;
25 enum lttng_env_secure secure;
26 char *value;
27 };
28
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;
32
33 static struct lttng_env lttng_env[] = {
34 /*
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().
38 */
39 { "LTTNG_UST_DEBUG", LTTNG_ENV_NOT_SECURE, NULL, },
40 { "LTTNG_UST_ABORT_ON_CRITICAL", LTTNG_ENV_NOT_SECURE, NULL, },
41
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, },
45
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, },
53 };
54
55 static
56 int lttng_is_setuid_setgid(void)
57 {
58 return geteuid() != getuid() || getegid() != getgid();
59 }
60
61 /*
62 * Wrapper over getenv that will only return the values of whitelisted
63 * environment variables when the current process is setuid and/or setgid.
64 */
65 char *lttng_ust_getenv(const char *name)
66 {
67 size_t i;
68 struct lttng_env *e;
69 bool found = false;
70
71 /*
72 * Perform lazy initialization of lttng_ust_getenv for early use
73 * by library constructors.
74 */
75 lttng_ust_getenv_init();
76
77 for (i = 0; i < LTTNG_ARRAY_SIZE(lttng_env); i++) {
78 e = &lttng_env[i];
79
80 if (strcmp(e->key, name) == 0) {
81 found = true;
82 break;
83 }
84 }
85 if (!found) {
86 return NULL;
87 }
88 return e->value;
89 }
90
91 void lttng_ust_getenv_init(void)
92 {
93 size_t i;
94
95 /*
96 * Return early if the init has already completed.
97 */
98 if (CMM_LOAD_SHARED(lttng_ust_getenv_is_init)) {
99 /*
100 * Load lttng_ust_getenv_is_init before reading environment cache.
101 */
102 cmm_smp_rmb();
103 return;
104 }
105
106 pthread_mutex_lock(&lttng_ust_getenv_init_mutex);
107
108 /*
109 * Check again if the init has completed in another thread now that we
110 * have acquired the mutex.
111 */
112 if (lttng_ust_getenv_is_init)
113 goto end_init;
114
115 for (i = 0; i < LTTNG_ARRAY_SIZE(lttng_env); i++) {
116 struct lttng_env *e = &lttng_env[i];
117
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.",
120 e->key);
121 continue;
122 }
123 e->value = getenv(e->key);
124 }
125
126 /*
127 * Store environment cache before setting lttng_ust_getenv_is_init to 1.
128 */
129 cmm_smp_wmb();
130 CMM_STORE_SHARED(lttng_ust_getenv_is_init, 1);
131 end_init:
132 pthread_mutex_unlock(&lttng_ust_getenv_init_mutex);
133 }
This page took 0.030911 seconds and 3 git commands to generate.