Commit | Line | Data |
---|---|---|
6f626d28 | 1 | /* |
c0c0989a | 2 | * SPDX-License-Identifier: LGPL-2.1-only |
6f626d28 | 3 | * |
c0c0989a | 4 | * Copyright (C) 2017 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
6f626d28 MD |
5 | */ |
6 | ||
7 | #include <stdlib.h> | |
8 | #include <unistd.h> | |
9 | #include <stdbool.h> | |
b4051ad8 | 10 | #include <stddef.h> |
6f626d28 | 11 | #include <sys/types.h> |
042dbbc8 | 12 | #include <pthread.h> |
910dcd72 | 13 | #include <urcu/system.h> |
9d315d6d MJ |
14 | #include "common/logging.h" |
15 | #include "common/macros.h" | |
910dcd72 | 16 | #include "common/getenv.h" |
6f626d28 MD |
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 | ||
042dbbc8 MD |
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; | |
910dcd72 | 32 | |
6f626d28 MD |
33 | static struct lttng_env lttng_env[] = { |
34 | /* | |
9ff107a9 MJ |
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(). | |
6f626d28 MD |
38 | */ |
39 | { "LTTNG_UST_DEBUG", LTTNG_ENV_NOT_SECURE, NULL, }, | |
9ff107a9 | 40 | { "LTTNG_UST_ABORT_ON_CRITICAL", LTTNG_ENV_NOT_SECURE, NULL, }, |
6f626d28 MD |
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, }, | |
97572c04 | 45 | { "LTTNG_UST_MAP_POPULATE_POLICY", LTTNG_ENV_NOT_SECURE, NULL, }, |
6f626d28 MD |
46 | |
47 | /* Env. var. which are not fetched in setuid/setgid executables. */ | |
48 | { "LTTNG_UST_CLOCK_PLUGIN", LTTNG_ENV_SECURE, NULL, }, | |
49 | { "LTTNG_UST_GETCPU_PLUGIN", LTTNG_ENV_SECURE, NULL, }, | |
b2c5f61a | 50 | { "LTTNG_UST_ALLOW_BLOCKING", LTTNG_ENV_SECURE, NULL, }, |
6f626d28 MD |
51 | { "HOME", LTTNG_ENV_SECURE, NULL, }, |
52 | { "LTTNG_HOME", LTTNG_ENV_SECURE, NULL, }, | |
c0f6fb05 | 53 | { "LTTNG_UST_APP_PATH", LTTNG_ENV_SECURE, NULL, }, |
6f626d28 MD |
54 | }; |
55 | ||
56 | static | |
57 | int lttng_is_setuid_setgid(void) | |
58 | { | |
59 | return geteuid() != getuid() || getegid() != getgid(); | |
60 | } | |
61 | ||
910dcd72 MJ |
62 | /* |
63 | * Wrapper over getenv that will only return the values of whitelisted | |
64 | * environment variables when the current process is setuid and/or setgid. | |
65 | */ | |
4c41b460 | 66 | char *lttng_ust_getenv(const char *name) |
6f626d28 MD |
67 | { |
68 | size_t i; | |
69 | struct lttng_env *e; | |
70 | bool found = false; | |
71 | ||
407937dc MD |
72 | /* |
73 | * Perform lazy initialization of lttng_ust_getenv for early use | |
74 | * by library constructors. | |
75 | */ | |
76 | lttng_ust_getenv_init(); | |
910dcd72 | 77 | |
6f626d28 MD |
78 | for (i = 0; i < LTTNG_ARRAY_SIZE(lttng_env); i++) { |
79 | e = <tng_env[i]; | |
80 | ||
81 | if (strcmp(e->key, name) == 0) { | |
82 | found = true; | |
83 | break; | |
84 | } | |
85 | } | |
86 | if (!found) { | |
87 | return NULL; | |
88 | } | |
89 | return e->value; | |
90 | } | |
91 | ||
92 | void lttng_ust_getenv_init(void) | |
93 | { | |
94 | size_t i; | |
95 | ||
042dbbc8 MD |
96 | /* |
97 | * Return early if the init has already completed. | |
98 | */ | |
99 | if (CMM_LOAD_SHARED(lttng_ust_getenv_is_init)) { | |
100 | /* | |
101 | * Load lttng_ust_getenv_is_init before reading environment cache. | |
102 | */ | |
103 | cmm_smp_rmb(); | |
910dcd72 | 104 | return; |
042dbbc8 MD |
105 | } |
106 | ||
107 | pthread_mutex_lock(<tng_ust_getenv_init_mutex); | |
108 | ||
109 | /* | |
110 | * Check again if the init has completed in another thread now that we | |
111 | * have acquired the mutex. | |
112 | */ | |
113 | if (lttng_ust_getenv_is_init) | |
114 | goto end_init; | |
910dcd72 | 115 | |
6f626d28 MD |
116 | for (i = 0; i < LTTNG_ARRAY_SIZE(lttng_env); i++) { |
117 | struct lttng_env *e = <tng_env[i]; | |
118 | ||
119 | if (e->secure == LTTNG_ENV_SECURE && lttng_is_setuid_setgid()) { | |
120 | ERR("Getting environment variable '%s' from setuid/setgid binary refused for security reasons.", | |
121 | e->key); | |
122 | continue; | |
123 | } | |
124 | e->value = getenv(e->key); | |
125 | } | |
042dbbc8 MD |
126 | |
127 | /* | |
128 | * Store environment cache before setting lttng_ust_getenv_is_init to 1. | |
129 | */ | |
130 | cmm_smp_wmb(); | |
910dcd72 | 131 | CMM_STORE_SHARED(lttng_ust_getenv_is_init, 1); |
042dbbc8 MD |
132 | end_init: |
133 | pthread_mutex_unlock(<tng_ust_getenv_init_mutex); | |
6f626d28 | 134 | } |