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, }, | |
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, }, | |
b2c5f61a | 49 | { "LTTNG_UST_ALLOW_BLOCKING", LTTNG_ENV_SECURE, NULL, }, |
6f626d28 MD |
50 | { "HOME", LTTNG_ENV_SECURE, NULL, }, |
51 | { "LTTNG_HOME", LTTNG_ENV_SECURE, NULL, }, | |
52 | }; | |
53 | ||
54 | static | |
55 | int lttng_is_setuid_setgid(void) | |
56 | { | |
57 | return geteuid() != getuid() || getegid() != getgid(); | |
58 | } | |
59 | ||
910dcd72 MJ |
60 | /* |
61 | * Wrapper over getenv that will only return the values of whitelisted | |
62 | * environment variables when the current process is setuid and/or setgid. | |
63 | */ | |
4c41b460 | 64 | char *lttng_ust_getenv(const char *name) |
6f626d28 MD |
65 | { |
66 | size_t i; | |
67 | struct lttng_env *e; | |
68 | bool found = false; | |
69 | ||
407937dc MD |
70 | /* |
71 | * Perform lazy initialization of lttng_ust_getenv for early use | |
72 | * by library constructors. | |
73 | */ | |
74 | lttng_ust_getenv_init(); | |
910dcd72 | 75 | |
6f626d28 MD |
76 | for (i = 0; i < LTTNG_ARRAY_SIZE(lttng_env); i++) { |
77 | e = <tng_env[i]; | |
78 | ||
79 | if (strcmp(e->key, name) == 0) { | |
80 | found = true; | |
81 | break; | |
82 | } | |
83 | } | |
84 | if (!found) { | |
85 | return NULL; | |
86 | } | |
87 | return e->value; | |
88 | } | |
89 | ||
90 | void lttng_ust_getenv_init(void) | |
91 | { | |
92 | size_t i; | |
93 | ||
042dbbc8 MD |
94 | /* |
95 | * Return early if the init has already completed. | |
96 | */ | |
97 | if (CMM_LOAD_SHARED(lttng_ust_getenv_is_init)) { | |
98 | /* | |
99 | * Load lttng_ust_getenv_is_init before reading environment cache. | |
100 | */ | |
101 | cmm_smp_rmb(); | |
910dcd72 | 102 | return; |
042dbbc8 MD |
103 | } |
104 | ||
105 | pthread_mutex_lock(<tng_ust_getenv_init_mutex); | |
106 | ||
107 | /* | |
108 | * Check again if the init has completed in another thread now that we | |
109 | * have acquired the mutex. | |
110 | */ | |
111 | if (lttng_ust_getenv_is_init) | |
112 | goto end_init; | |
910dcd72 | 113 | |
6f626d28 MD |
114 | for (i = 0; i < LTTNG_ARRAY_SIZE(lttng_env); i++) { |
115 | struct lttng_env *e = <tng_env[i]; | |
116 | ||
117 | if (e->secure == LTTNG_ENV_SECURE && lttng_is_setuid_setgid()) { | |
118 | ERR("Getting environment variable '%s' from setuid/setgid binary refused for security reasons.", | |
119 | e->key); | |
120 | continue; | |
121 | } | |
122 | e->value = getenv(e->key); | |
123 | } | |
042dbbc8 MD |
124 | |
125 | /* | |
126 | * Store environment cache before setting lttng_ust_getenv_is_init to 1. | |
127 | */ | |
128 | cmm_smp_wmb(); | |
910dcd72 | 129 | CMM_STORE_SHARED(lttng_ust_getenv_is_init, 1); |
042dbbc8 MD |
130 | end_init: |
131 | pthread_mutex_unlock(<tng_ust_getenv_init_mutex); | |
6f626d28 | 132 | } |