diff options
author | 2020-04-06 21:24:16 +0300 | |
---|---|---|
committer | 2021-02-08 19:19:09 +0200 | |
commit | 1c7ea15b30d49d32a0e3cb79152514f1aeb19397 (patch) | |
tree | 73d5d0f553e08d6d9a64f85c29a5c6df5433cda7 /src | |
parent | use ${DOWNLOADS} in lutris.profile (#3955) (diff) | |
download | firejail-1c7ea15b30d49d32a0e3cb79152514f1aeb19397.tar.gz firejail-1c7ea15b30d49d32a0e3cb79152514f1aeb19397.tar.zst firejail-1c7ea15b30d49d32a0e3cb79152514f1aeb19397.zip |
Filter environment variables
Save all environment variables for later use in the application, clear
environment and re-apply only whitelisted variables for the main
firejail process. The whitelisted environment is only used by C
library. Sandboxed tools will get further variables used
internally (FIREJAIL_*).
All variables will be reapplied for the firejailed application.
This also lifts the length restriction for environment variables,
except for the variables used by Firejail itself or the sandboxed
tools.
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/appimage.c | 18 | ||||
-rw-r--r-- | src/firejail/checkcfg.c | 6 | ||||
-rw-r--r-- | src/firejail/chroot.c | 4 | ||||
-rw-r--r-- | src/firejail/dbus.c | 30 | ||||
-rw-r--r-- | src/firejail/env.c | 164 | ||||
-rw-r--r-- | src/firejail/firejail.h | 11 | ||||
-rw-r--r-- | src/firejail/fs.c | 2 | ||||
-rw-r--r-- | src/firejail/fs_whitelist.c | 2 | ||||
-rw-r--r-- | src/firejail/join.c | 2 | ||||
-rw-r--r-- | src/firejail/main.c | 53 | ||||
-rw-r--r-- | src/firejail/no_sandbox.c | 2 | ||||
-rw-r--r-- | src/firejail/output.c | 7 | ||||
-rw-r--r-- | src/firejail/paths.c | 10 | ||||
-rw-r--r-- | src/firejail/profile.c | 10 | ||||
-rw-r--r-- | src/firejail/pulseaudio.c | 5 | ||||
-rw-r--r-- | src/firejail/run_symlink.c | 7 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 7 | ||||
-rw-r--r-- | src/firejail/sbox.c | 2 | ||||
-rw-r--r-- | src/firejail/x11.c | 61 |
19 files changed, 284 insertions, 119 deletions
diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c index 6190b6f01..dd94b9921 100644 --- a/src/firejail/appimage.c +++ b/src/firejail/appimage.c | |||
@@ -131,14 +131,16 @@ void appimage_set(const char *appimage) { | |||
131 | errExit("Failed to obtain absolute path"); | 131 | errExit("Failed to obtain absolute path"); |
132 | 132 | ||
133 | // set environment | 133 | // set environment |
134 | if (setenv("APPIMAGE", abspath, 1) < 0) | 134 | env_store_name_val("APPIMAGE", abspath, SETENV); |
135 | errExit("setenv"); | 135 | |
136 | if (mntdir && setenv("APPDIR", mntdir, 1) < 0) | 136 | if (mntdir) |
137 | errExit("setenv"); | 137 | env_store_name_val("APPDIR", mntdir, SETENV); |
138 | if (size != 0 && setenv("ARGV0", appimage, 1) < 0) | 138 | |
139 | errExit("setenv"); | 139 | if (size != 0) |
140 | if (cfg.cwd && setenv("OWD", cfg.cwd, 1) < 0) | 140 | env_store_name_val("ARGV0", appimage, SETENV); |
141 | errExit("setenv"); | 141 | |
142 | if (cfg.cwd) | ||
143 | env_store_name_val("OWD", cfg.cwd, SETENV); | ||
142 | 144 | ||
143 | // build new command line | 145 | // build new command line |
144 | if (asprintf(&cfg.command_line, "%s/AppRun", mntdir) == -1) | 146 | if (asprintf(&cfg.command_line, "%s/AppRun", mntdir) == -1) |
diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c index 085221464..fb2171a55 100644 --- a/src/firejail/checkcfg.c +++ b/src/firejail/checkcfg.c | |||
@@ -215,10 +215,8 @@ int checkcfg(int val) { | |||
215 | } | 215 | } |
216 | 216 | ||
217 | // file copy limit | 217 | // file copy limit |
218 | else if (strncmp(ptr, "file-copy-limit ", 16) == 0) { | 218 | else if (strncmp(ptr, "file-copy-limit ", 16) == 0) |
219 | if (setenv("FIREJAIL_FILE_COPY_LIMIT", ptr + 16, 1) == -1) | 219 | env_store_name_val("FIREJAIL_FILE_COPY_LIMIT", ptr + 16, SETENV); |
220 | errExit("setenv"); | ||
221 | } | ||
222 | 220 | ||
223 | // timeout for join option | 221 | // timeout for join option |
224 | else if (strncmp(ptr, "join-timeout ", 13) == 0) | 222 | else if (strncmp(ptr, "join-timeout ", 13) == 0) |
diff --git a/src/firejail/chroot.c b/src/firejail/chroot.c index cfa32d1d3..6de4b819c 100644 --- a/src/firejail/chroot.c +++ b/src/firejail/chroot.c | |||
@@ -173,7 +173,7 @@ void fs_chroot(const char *rootdir) { | |||
173 | 173 | ||
174 | // x11 | 174 | // x11 |
175 | // if users want this mount, they should set FIREJAIL_CHROOT_X11 | 175 | // if users want this mount, they should set FIREJAIL_CHROOT_X11 |
176 | if (getenv("FIREJAIL_X11") || getenv("FIREJAIL_CHROOT_X11")) { | 176 | if (env_get("FIREJAIL_X11") || env_get("FIREJAIL_CHROOT_X11")) { |
177 | if (arg_debug) | 177 | if (arg_debug) |
178 | printf("Mounting /tmp/.X11-unix on chroot /tmp/.X11-unix\n"); | 178 | printf("Mounting /tmp/.X11-unix on chroot /tmp/.X11-unix\n"); |
179 | check_subdir(parentfd, "tmp/.X11-unix", 0); | 179 | check_subdir(parentfd, "tmp/.X11-unix", 0); |
@@ -194,7 +194,7 @@ void fs_chroot(const char *rootdir) { | |||
194 | check_subdir(parentfd, "run", 1); | 194 | check_subdir(parentfd, "run", 1); |
195 | 195 | ||
196 | // pulseaudio; only support for default directory /run/user/$UID/pulse | 196 | // pulseaudio; only support for default directory /run/user/$UID/pulse |
197 | if (getenv("FIREJAIL_CHROOT_PULSE")) { | 197 | if (env_get("FIREJAIL_CHROOT_PULSE")) { |
198 | char *pulse; | 198 | char *pulse; |
199 | if (asprintf(&pulse, "%s/run/user/%d/pulse", cfg.chrootdir, getuid()) == -1) | 199 | if (asprintf(&pulse, "%s/run/user/%d/pulse", cfg.chrootdir, getuid()) == -1) |
200 | errExit("asprintf"); | 200 | errExit("asprintf"); |
diff --git a/src/firejail/dbus.c b/src/firejail/dbus.c index 3cf75ed84..1d0f07089 100644 --- a/src/firejail/dbus.c +++ b/src/firejail/dbus.c | |||
@@ -329,7 +329,7 @@ void dbus_proxy_start(void) { | |||
329 | errExit("close"); | 329 | errExit("close"); |
330 | 330 | ||
331 | if (arg_dbus_user == DBUS_POLICY_FILTER) { | 331 | if (arg_dbus_user == DBUS_POLICY_FILTER) { |
332 | char *user_env = getenv(DBUS_SESSION_BUS_ADDRESS_ENV); | 332 | const char *user_env = env_get(DBUS_SESSION_BUS_ADDRESS_ENV); |
333 | if (user_env == NULL) { | 333 | if (user_env == NULL) { |
334 | char *dbus_user_socket = find_user_socket(); | 334 | char *dbus_user_socket = find_user_socket(); |
335 | write_arg(args_pipe[1], DBUS_SOCKET_PATH_PREFIX "%s", | 335 | write_arg(args_pipe[1], DBUS_SOCKET_PATH_PREFIX "%s", |
@@ -350,7 +350,7 @@ void dbus_proxy_start(void) { | |||
350 | } | 350 | } |
351 | 351 | ||
352 | if (arg_dbus_system == DBUS_POLICY_FILTER) { | 352 | if (arg_dbus_system == DBUS_POLICY_FILTER) { |
353 | char *system_env = getenv(DBUS_SYSTEM_BUS_ADDRESS_ENV); | 353 | const char *system_env = env_get(DBUS_SYSTEM_BUS_ADDRESS_ENV); |
354 | if (system_env == NULL) { | 354 | if (system_env == NULL) { |
355 | write_arg(args_pipe[1], | 355 | write_arg(args_pipe[1], |
356 | DBUS_SOCKET_PATH_PREFIX DBUS_SYSTEM_SOCKET); | 356 | DBUS_SOCKET_PATH_PREFIX DBUS_SYSTEM_SOCKET); |
@@ -435,8 +435,8 @@ static void socket_overlay(char *socket_path, char *proxy_path) { | |||
435 | close(fd); | 435 | close(fd); |
436 | } | 436 | } |
437 | 437 | ||
438 | static char *get_socket_env(const char *name) { | 438 | static const char *get_socket_env(const char *name) { |
439 | char *value = getenv(name); | 439 | const char *value = env_get(name); |
440 | if (value == NULL) | 440 | if (value == NULL) |
441 | return NULL; | 441 | return NULL; |
442 | if (strncmp(value, DBUS_SOCKET_PATH_PREFIX, | 442 | if (strncmp(value, DBUS_SOCKET_PATH_PREFIX, |
@@ -446,21 +446,13 @@ static char *get_socket_env(const char *name) { | |||
446 | } | 446 | } |
447 | 447 | ||
448 | void dbus_set_session_bus_env(void) { | 448 | void dbus_set_session_bus_env(void) { |
449 | if (setenv(DBUS_SESSION_BUS_ADDRESS_ENV, | 449 | env_store_name_val(DBUS_SESSION_BUS_ADDRESS_ENV, |
450 | DBUS_SOCKET_PATH_PREFIX RUN_DBUS_USER_SOCKET, 1) == -1) { | 450 | DBUS_SOCKET_PATH_PREFIX RUN_DBUS_USER_SOCKET, SETENV); |
451 | fprintf(stderr, "Error: cannot modify " DBUS_SESSION_BUS_ADDRESS_ENV | ||
452 | " required by --dbus-user\n"); | ||
453 | exit(1); | ||
454 | } | ||
455 | } | 451 | } |
456 | 452 | ||
457 | void dbus_set_system_bus_env(void) { | 453 | void dbus_set_system_bus_env(void) { |
458 | if (setenv(DBUS_SYSTEM_BUS_ADDRESS_ENV, | 454 | env_store_name_val(DBUS_SYSTEM_BUS_ADDRESS_ENV, |
459 | DBUS_SOCKET_PATH_PREFIX RUN_DBUS_SYSTEM_SOCKET, 1) == -1) { | 455 | DBUS_SOCKET_PATH_PREFIX RUN_DBUS_SYSTEM_SOCKET, SETENV); |
460 | fprintf(stderr, "Error: cannot modify " DBUS_SYSTEM_BUS_ADDRESS_ENV | ||
461 | " required by --dbus-system\n"); | ||
462 | exit(1); | ||
463 | } | ||
464 | } | 456 | } |
465 | 457 | ||
466 | static void disable_socket_dir(void) { | 458 | static void disable_socket_dir(void) { |
@@ -506,7 +498,7 @@ void dbus_apply_policy(void) { | |||
506 | errExit("asprintf"); | 498 | errExit("asprintf"); |
507 | disable_file_or_dir(dbus_user_socket2); | 499 | disable_file_or_dir(dbus_user_socket2); |
508 | 500 | ||
509 | char *user_env = get_socket_env(DBUS_SESSION_BUS_ADDRESS_ENV); | 501 | const char *user_env = get_socket_env(DBUS_SESSION_BUS_ADDRESS_ENV); |
510 | if (user_env != NULL && strcmp(user_env, dbus_user_socket) != 0 && | 502 | if (user_env != NULL && strcmp(user_env, dbus_user_socket) != 0 && |
511 | strcmp(user_env, dbus_user_socket2) != 0) | 503 | strcmp(user_env, dbus_user_socket2) != 0) |
512 | disable_file_or_dir(user_env); | 504 | disable_file_or_dir(user_env); |
@@ -535,7 +527,7 @@ void dbus_apply_policy(void) { | |||
535 | 527 | ||
536 | disable_file_or_dir(DBUS_SYSTEM_SOCKET); | 528 | disable_file_or_dir(DBUS_SYSTEM_SOCKET); |
537 | 529 | ||
538 | char *system_env = get_socket_env(DBUS_SYSTEM_BUS_ADDRESS_ENV); | 530 | const char *system_env = get_socket_env(DBUS_SYSTEM_BUS_ADDRESS_ENV); |
539 | if (system_env != NULL && strcmp(system_env, DBUS_SYSTEM_SOCKET) != 0) | 531 | if (system_env != NULL && strcmp(system_env, DBUS_SYSTEM_SOCKET) != 0) |
540 | disable_file_or_dir(system_env); | 532 | disable_file_or_dir(system_env); |
541 | 533 | ||
@@ -561,4 +553,4 @@ void dbus_apply_policy(void) { | |||
561 | 553 | ||
562 | fwarning("An abstract unix socket for session D-BUS might still be available. Use --net or remove unix from --protocol set.\n"); | 554 | fwarning("An abstract unix socket for session D-BUS might still be available. Use --net or remove unix from --protocol set.\n"); |
563 | } | 555 | } |
564 | #endif // HAVE_DBUSPROXY \ No newline at end of file | 556 | #endif // HAVE_DBUSPROXY |
diff --git a/src/firejail/env.c b/src/firejail/env.c index d74cebb39..2d5042100 100644 --- a/src/firejail/env.c +++ b/src/firejail/env.c | |||
@@ -25,8 +25,8 @@ | |||
25 | 25 | ||
26 | typedef struct env_t { | 26 | typedef struct env_t { |
27 | struct env_t *next; | 27 | struct env_t *next; |
28 | char *name; | 28 | const char *name; |
29 | char *value; | 29 | const char *value; |
30 | ENV_OP op; | 30 | ENV_OP op; |
31 | } Env; | 31 | } Env; |
32 | static Env *envlist = NULL; | 32 | static Env *envlist = NULL; |
@@ -117,45 +117,35 @@ void env_ibus_load(void) { | |||
117 | // default sandbox env variables | 117 | // default sandbox env variables |
118 | void env_defaults(void) { | 118 | void env_defaults(void) { |
119 | // Qt fixes | 119 | // Qt fixes |
120 | if (setenv("QT_X11_NO_MITSHM", "1", 1) < 0) | 120 | env_store_name_val("QT_X11_NO_MITSHM", "1", SETENV); |
121 | errExit("setenv"); | 121 | env_store_name_val("QML_DISABLE_DISK_CACHE", "1", SETENV); |
122 | if (setenv("QML_DISABLE_DISK_CACHE", "1", 1) < 0) | 122 | // env_store_name_val("QTWEBENGINE_DISABLE_SANDBOX", "1", SETENV); |
123 | errExit("setenv"); | 123 | // env_store_name_val("MOZ_NO_REMOTE, "1", SETENV); |
124 | // if (setenv("QTWEBENGINE_DISABLE_SANDBOX", "1", 1) < 0) | 124 | env_store_name_val("container", "firejail", SETENV); // LXC sets container=lxc, |
125 | // errExit("setenv"); | ||
126 | // if (setenv("MOZ_NO_REMOTE, "1", 1) < 0) | ||
127 | // errExit("setenv"); | ||
128 | if (setenv("container", "firejail", 1) < 0) // LXC sets container=lxc, | ||
129 | errExit("setenv"); | ||
130 | if (!cfg.shell) | 125 | if (!cfg.shell) |
131 | cfg.shell = guess_shell(); | 126 | cfg.shell = guess_shell(); |
132 | if (cfg.shell && setenv("SHELL", cfg.shell, 1) < 0) | 127 | if (cfg.shell) |
133 | errExit("setenv"); | 128 | env_store_name_val("SHELL", cfg.shell, SETENV); |
134 | 129 | ||
135 | // spawn KIO slaves inside the sandbox | 130 | // spawn KIO slaves inside the sandbox |
136 | if (setenv("KDE_FORK_SLAVES", "1", 1) < 0) | 131 | env_store_name_val("KDE_FORK_SLAVES", "1", SETENV); |
137 | errExit("setenv"); | ||
138 | 132 | ||
139 | // set prompt color to green | 133 | // set prompt color to green |
140 | int set_prompt = 0; | 134 | int set_prompt = 0; |
141 | if (checkcfg(CFG_FIREJAIL_PROMPT)) | 135 | if (checkcfg(CFG_FIREJAIL_PROMPT)) |
142 | set_prompt = 1; | 136 | set_prompt = 1; |
143 | else { // check FIREJAIL_PROMPT="yes" environment variable | 137 | else { // check FIREJAIL_PROMPT="yes" environment variable |
144 | char *prompt = getenv("FIREJAIL_PROMPT"); | 138 | const char *prompt = env_get("FIREJAIL_PROMPT"); |
145 | if (prompt && strcmp(prompt, "yes") == 0) | 139 | if (prompt && strcmp(prompt, "yes") == 0) |
146 | set_prompt = 1; | 140 | set_prompt = 1; |
147 | } | 141 | } |
148 | 142 | ||
149 | if (set_prompt) { | 143 | if (set_prompt) |
150 | //export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] ' | 144 | //export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] ' |
151 | if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0) | 145 | env_store_name_val("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", SETENV); |
152 | errExit("setenv"); | 146 | else |
153 | } | ||
154 | else { | ||
155 | // remove PROMPT_COMMAND | 147 | // remove PROMPT_COMMAND |
156 | if (setenv("PROMPT_COMMAND", ":", 1) < 0) // unsetenv() will not work here, bash still picks it up from somewhere | 148 | env_store_name_val("PROMPT_COMMAND", ":", SETENV); // unsetenv() will not work here, bash still picks it up from somewhere |
157 | errExit("setenv"); | ||
158 | } | ||
159 | 149 | ||
160 | // set the window title | 150 | // set the window title |
161 | if (!arg_quiet && isatty(STDOUT_FILENO)) | 151 | if (!arg_quiet && isatty(STDOUT_FILENO)) |
@@ -163,26 +153,26 @@ void env_defaults(void) { | |||
163 | 153 | ||
164 | // pass --quiet as an environment variable, in case the command calls further firejailed commands | 154 | // pass --quiet as an environment variable, in case the command calls further firejailed commands |
165 | if (arg_quiet) | 155 | if (arg_quiet) |
166 | setenv("FIREJAIL_QUIET", "yes", 1); | 156 | env_store_name_val("FIREJAIL_QUIET", "yes", SETENV); |
167 | 157 | ||
168 | fflush(0); | 158 | fflush(0); |
169 | } | 159 | } |
170 | 160 | ||
171 | // parse and store the environment setting | 161 | // parse and store the environment setting |
172 | void env_store(const char *str, ENV_OP op) { | 162 | void env_store(const char *str, ENV_OP op) { |
173 | EUID_ASSERT(); | ||
174 | assert(str); | 163 | assert(str); |
175 | 164 | ||
176 | // some basic checking | 165 | // some basic checking |
177 | if (*str == '\0') | 166 | if (*str == '\0') |
178 | goto errexit; | 167 | goto errexit; |
179 | char *ptr = strchr(str, '='); | 168 | char *ptr = strchr(str, '='); |
180 | if (op == SETENV) { | 169 | if (op == SETENV || op == SETENV_ALLOW_EMPTY) { |
181 | if (!ptr) | 170 | if (!ptr) |
182 | goto errexit; | 171 | goto errexit; |
183 | ptr++; | 172 | ptr++; |
184 | if (*ptr == '\0') | 173 | if (*ptr == '\0' && op != SETENV_ALLOW_EMPTY) |
185 | goto errexit; | 174 | goto errexit; |
175 | op = SETENV; | ||
186 | } | 176 | } |
187 | 177 | ||
188 | // build list entry | 178 | // build list entry |
@@ -210,8 +200,45 @@ errexit: | |||
210 | exit(1); | 200 | exit(1); |
211 | } | 201 | } |
212 | 202 | ||
203 | void env_store_name_val(const char *name, const char *val, ENV_OP op) { | ||
204 | assert(name); | ||
205 | |||
206 | // some basic checking | ||
207 | if (*name == '\0') | ||
208 | goto errexit; | ||
209 | if (*val == '\0' && op != SETENV_ALLOW_EMPTY) | ||
210 | goto errexit; | ||
211 | |||
212 | if (op == SETENV_ALLOW_EMPTY) | ||
213 | op = SETENV; | ||
214 | |||
215 | // build list entry | ||
216 | Env *env = calloc(1, sizeof(Env)); | ||
217 | if (!env) | ||
218 | errExit("calloc"); | ||
219 | |||
220 | env->name = strdup(name); | ||
221 | if (env->name == NULL) | ||
222 | errExit("strdup"); | ||
223 | |||
224 | if (op == SETENV) { | ||
225 | env->value = strdup(val); | ||
226 | if (env->value == NULL) | ||
227 | errExit("strdup"); | ||
228 | } | ||
229 | env->op = op; | ||
230 | |||
231 | // add entry to the list | ||
232 | env_add(env); | ||
233 | return; | ||
234 | |||
235 | errexit: | ||
236 | fprintf(stderr, "Error: invalid --env setting\n"); | ||
237 | exit(1); | ||
238 | } | ||
239 | |||
213 | // set env variables in the new sandbox process | 240 | // set env variables in the new sandbox process |
214 | void env_apply(void) { | 241 | void env_apply_all(void) { |
215 | Env *env = envlist; | 242 | Env *env = envlist; |
216 | 243 | ||
217 | while (env) { | 244 | while (env) { |
@@ -225,3 +252,80 @@ void env_apply(void) { | |||
225 | env = env->next; | 252 | env = env->next; |
226 | } | 253 | } |
227 | } | 254 | } |
255 | |||
256 | // get env variable | ||
257 | const char *env_get(const char *name) { | ||
258 | Env *env = envlist; | ||
259 | const char *r = NULL; | ||
260 | |||
261 | while (env) { | ||
262 | if (strcmp(env->name, name) == 0) { | ||
263 | if (env->op == SETENV) | ||
264 | r = env->value; | ||
265 | else if (env->op == RMENV) | ||
266 | r = NULL; | ||
267 | } | ||
268 | env = env->next; | ||
269 | } | ||
270 | return r; | ||
271 | } | ||
272 | |||
273 | static const char * const env_whitelist[] = { | ||
274 | "LANG", | ||
275 | "LANGUAGE", | ||
276 | "LC_MESSAGES", | ||
277 | "PATH" | ||
278 | }; | ||
279 | |||
280 | static const char * const env_whitelist_sbox[] = { | ||
281 | "FIREJAIL_DEBUG", | ||
282 | "FIREJAIL_FILE_COPY_LIMIT", | ||
283 | "FIREJAIL_PLUGIN", | ||
284 | "FIREJAIL_QUIET", | ||
285 | "FIREJAIL_SECCOMP_ERROR_ACTION", | ||
286 | "FIREJAIL_TEST_ARGUMENTS", | ||
287 | "FIREJAIL_TRACEFILE" | ||
288 | }; | ||
289 | |||
290 | static void env_apply_list(const char * const *list, unsigned int num_items) { | ||
291 | Env *env = envlist; | ||
292 | |||
293 | while (env) { | ||
294 | if (env->op == SETENV) { | ||
295 | for (unsigned int i = 0; i < num_items; i++) | ||
296 | if (strcmp(env->name, list[i]) == 0) { | ||
297 | // sanity check for whitelisted environment variables | ||
298 | if (strlen(env->name) + strlen(env->value) >= MAX_ENV_LEN) { | ||
299 | fprintf(stderr, "Error: too long environment variable %s, please use --rmenv\n", env->name); | ||
300 | exit(1); | ||
301 | } | ||
302 | |||
303 | //fprintf(stderr, "whitelisted env var %s=%s\n", env->name, env->value); | ||
304 | if (setenv(env->name, env->value, 1) < 0) | ||
305 | errExit("setenv"); | ||
306 | break; | ||
307 | } | ||
308 | } else if (env->op == RMENV) | ||
309 | unsetenv(env->name); | ||
310 | |||
311 | env = env->next; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | // Filter env variables in main firejail process. All variables will | ||
316 | // be reapplied for the sandboxed app by env_apply_all(). | ||
317 | void env_apply_whitelist(void) { | ||
318 | int r; | ||
319 | |||
320 | r = clearenv(); | ||
321 | if (r != 0) | ||
322 | errExit("clearenv"); | ||
323 | |||
324 | env_apply_list(env_whitelist, ARRAY_SIZE(env_whitelist)); | ||
325 | } | ||
326 | |||
327 | // Filter env variables for a sbox app | ||
328 | void env_apply_whitelist_sbox(void) { | ||
329 | env_apply_whitelist(); | ||
330 | env_apply_list(env_whitelist_sbox, ARRAY_SIZE(env_whitelist_sbox)); | ||
331 | } | ||
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 9ea3edcd0..c6e0fed2a 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -81,6 +81,8 @@ | |||
81 | (void) rv;\ | 81 | (void) rv;\ |
82 | } while (0) | 82 | } while (0) |
83 | 83 | ||
84 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | ||
85 | |||
84 | // main.c | 86 | // main.c |
85 | typedef struct bridge_t { | 87 | typedef struct bridge_t { |
86 | // on the host | 88 | // on the host |
@@ -655,16 +657,21 @@ int check_kernel_procs(void); | |||
655 | void run_no_sandbox(int argc, char **argv) __attribute__((noreturn)); | 657 | void run_no_sandbox(int argc, char **argv) __attribute__((noreturn)); |
656 | 658 | ||
657 | #define MAX_ENVS 256 // some sane maximum number of environment variables | 659 | #define MAX_ENVS 256 // some sane maximum number of environment variables |
658 | #define MAX_ENV_LEN (PATH_MAX + 32) // FOOBAR=SOME_PATH | 660 | #define MAX_ENV_LEN (PATH_MAX + 32) // FOOBAR=SOME_PATH, only applied to Firejail's own sandboxed apps |
659 | // env.c | 661 | // env.c |
660 | typedef enum { | 662 | typedef enum { |
661 | SETENV = 0, | 663 | SETENV = 0, |
664 | SETENV_ALLOW_EMPTY, | ||
662 | RMENV | 665 | RMENV |
663 | } ENV_OP; | 666 | } ENV_OP; |
664 | 667 | ||
665 | void env_store(const char *str, ENV_OP op); | 668 | void env_store(const char *str, ENV_OP op); |
666 | void env_apply(void); | 669 | void env_store_name_val(const char *name, const char *val, ENV_OP op); |
670 | void env_apply_all(void); | ||
671 | void env_apply_whitelist(void); | ||
672 | void env_apply_whitelist_sbox(void); | ||
667 | void env_defaults(void); | 673 | void env_defaults(void); |
674 | const char *env_get(const char *name); | ||
668 | void env_ibus_load(void); | 675 | void env_ibus_load(void); |
669 | 676 | ||
670 | // fs_whitelist.c | 677 | // fs_whitelist.c |
diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 4e6c1adc3..b1c509b30 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c | |||
@@ -1221,7 +1221,7 @@ void fs_private_tmp(void) { | |||
1221 | printf("Generate private-tmp whitelist commands\n"); | 1221 | printf("Generate private-tmp whitelist commands\n"); |
1222 | 1222 | ||
1223 | // check XAUTHORITY file, KDE keeps it under /tmp | 1223 | // check XAUTHORITY file, KDE keeps it under /tmp |
1224 | char *xauth = getenv("XAUTHORITY"); | 1224 | const char *xauth = env_get("XAUTHORITY"); |
1225 | if (xauth) { | 1225 | if (xauth) { |
1226 | char *rp = realpath(xauth, NULL); | 1226 | char *rp = realpath(xauth, NULL); |
1227 | if (rp && strncmp(rp, "/tmp/", 5) == 0) { | 1227 | if (rp && strncmp(rp, "/tmp/", 5) == 0) { |
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index 1d7552339..d60c57fec 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c | |||
@@ -778,7 +778,7 @@ void fs_whitelist(void) { | |||
778 | fs_logger("tmpfs /tmp"); | 778 | fs_logger("tmpfs /tmp"); |
779 | 779 | ||
780 | // pam-tmpdir - issue #2685 | 780 | // pam-tmpdir - issue #2685 |
781 | char *env = getenv("TMP"); | 781 | const char *env = env_get("TMP"); |
782 | if (env) { | 782 | if (env) { |
783 | char *pamtmpdir; | 783 | char *pamtmpdir; |
784 | if (asprintf(&pamtmpdir, "/tmp/user/%u", getuid()) == -1) | 784 | if (asprintf(&pamtmpdir, "/tmp/user/%u", getuid()) == -1) |
diff --git a/src/firejail/join.c b/src/firejail/join.c index 4f0210f95..bdd0f286c 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c | |||
@@ -561,7 +561,7 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
561 | char *display_str; | 561 | char *display_str; |
562 | if (asprintf(&display_str, ":%d", display) == -1) | 562 | if (asprintf(&display_str, ":%d", display) == -1) |
563 | errExit("asprintf"); | 563 | errExit("asprintf"); |
564 | setenv("DISPLAY", display_str, 1); | 564 | env_store_name_val("DISPLAY", display_str, SETENV); |
565 | free(display_str); | 565 | free(display_str); |
566 | } | 566 | } |
567 | 567 | ||
diff --git a/src/firejail/main.c b/src/firejail/main.c index 0f0086a6e..7a9521e42 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -861,19 +861,20 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
861 | } | 861 | } |
862 | 862 | ||
863 | char *guess_shell(void) { | 863 | char *guess_shell(void) { |
864 | char *shell = NULL; | 864 | const char *shell; |
865 | char *retval; | ||
865 | struct stat s; | 866 | struct stat s; |
866 | 867 | ||
867 | shell = getenv("SHELL"); | 868 | shell = env_get("SHELL"); |
868 | if (shell) { | 869 | if (shell) { |
869 | invalid_filename(shell, 0); // no globbing | 870 | invalid_filename(shell, 0); // no globbing |
870 | if (!is_dir(shell) && strstr(shell, "..") == NULL && stat(shell, &s) == 0 && access(shell, X_OK) == 0 && | 871 | if (!is_dir(shell) && strstr(shell, "..") == NULL && stat(shell, &s) == 0 && access(shell, X_OK) == 0 && |
871 | strcmp(shell, PATH_FIREJAIL) != 0) | 872 | strcmp(shell, PATH_FIREJAIL) != 0) |
872 | return shell; | 873 | goto found; |
873 | } | 874 | } |
874 | 875 | ||
875 | // shells in order of preference | 876 | // shells in order of preference |
876 | char *shells[] = {"/bin/bash", "/bin/csh", "/usr/bin/zsh", "/bin/sh", "/bin/ash", NULL }; | 877 | static const char * const shells[] = {"/bin/bash", "/bin/csh", "/usr/bin/zsh", "/bin/sh", "/bin/ash", NULL }; |
877 | 878 | ||
878 | int i = 0; | 879 | int i = 0; |
879 | while (shells[i] != NULL) { | 880 | while (shells[i] != NULL) { |
@@ -884,8 +885,11 @@ char *guess_shell(void) { | |||
884 | } | 885 | } |
885 | i++; | 886 | i++; |
886 | } | 887 | } |
887 | 888 | found: | |
888 | return shell; | 889 | retval = strdup(shell); |
890 | if (!retval) | ||
891 | errExit("strdup"); | ||
892 | return retval; | ||
889 | } | 893 | } |
890 | 894 | ||
891 | // return argument index | 895 | // return argument index |
@@ -926,9 +930,13 @@ static void run_builder(int argc, char **argv) { | |||
926 | if (setresuid(-1, getuid(), getuid()) != 0) | 930 | if (setresuid(-1, getuid(), getuid()) != 0) |
927 | errExit("setresuid"); | 931 | errExit("setresuid"); |
928 | 932 | ||
933 | assert(env_get("LD_PRELOAD") == NULL); | ||
929 | assert(getenv("LD_PRELOAD") == NULL); | 934 | assert(getenv("LD_PRELOAD") == NULL); |
930 | umask(orig_umask); | 935 | umask(orig_umask); |
931 | 936 | ||
937 | // restore some environment variables | ||
938 | env_apply_whitelist_sbox(); | ||
939 | |||
932 | argv[0] = LIBDIR "/firejail/fbuilder"; | 940 | argv[0] = LIBDIR "/firejail/fbuilder"; |
933 | execvp(argv[0], argv); | 941 | execvp(argv[0], argv); |
934 | 942 | ||
@@ -994,6 +1002,16 @@ int main(int argc, char **argv, char **envp) { | |||
994 | exit(1); | 1002 | exit(1); |
995 | } | 1003 | } |
996 | 1004 | ||
1005 | // Stash environment variables | ||
1006 | for (i = 0, ptr = envp; ptr && *ptr && i < MAX_ENVS; i++, ptr++) | ||
1007 | env_store(*ptr, SETENV_ALLOW_EMPTY); | ||
1008 | |||
1009 | // sanity check for environment variables | ||
1010 | if (i >= MAX_ENVS) { | ||
1011 | fprintf(stderr, "Error: too many environment variables, please use --rmenv\n"); | ||
1012 | exit(1); | ||
1013 | } | ||
1014 | |||
997 | // sanity check for arguments | 1015 | // sanity check for arguments |
998 | for (i = 0; i < argc; i++) { | 1016 | for (i = 0; i < argc; i++) { |
999 | if (*argv[i] == 0) { | 1017 | if (*argv[i] == 0) { |
@@ -1005,29 +1023,19 @@ int main(int argc, char **argv, char **envp) { | |||
1005 | exit(1); | 1023 | exit(1); |
1006 | } | 1024 | } |
1007 | // Also remove requested environment variables | 1025 | // Also remove requested environment variables |
1008 | // entirely to avoid tripping the length check below | ||
1009 | if (strncmp(argv[i], "--rmenv=", 8) == 0) | 1026 | if (strncmp(argv[i], "--rmenv=", 8) == 0) |
1010 | unsetenv(argv[i] + 8); | 1027 | env_store(argv[i] + 8, RMENV); |
1011 | } | 1028 | } |
1012 | 1029 | ||
1013 | // sanity check for environment variables | 1030 | // Reapply a minimal set of environment variables |
1014 | for (i = 0, ptr = envp; ptr && *ptr && i < MAX_ENVS; i++, ptr++) { | 1031 | env_apply_whitelist(); |
1015 | if (strlen(*ptr) >= MAX_ENV_LEN) { | ||
1016 | fprintf(stderr, "Error: too long environment variables, please use --rmenv\n"); | ||
1017 | exit(1); | ||
1018 | } | ||
1019 | } | ||
1020 | if (i >= MAX_ENVS) { | ||
1021 | fprintf(stderr, "Error: too many environment variables, please use --rmenv\n"); | ||
1022 | exit(1); | ||
1023 | } | ||
1024 | 1032 | ||
1025 | // check if the user is allowed to use firejail | 1033 | // check if the user is allowed to use firejail |
1026 | init_cfg(argc, argv); | 1034 | init_cfg(argc, argv); |
1027 | 1035 | ||
1028 | // get starting timestamp, process --quiet | 1036 | // get starting timestamp, process --quiet |
1029 | timetrace_start(); | 1037 | timetrace_start(); |
1030 | char *env_quiet = getenv("FIREJAIL_QUIET"); | 1038 | const char *env_quiet = env_get("FIREJAIL_QUIET"); |
1031 | if (check_arg(argc, argv, "--quiet", 1) || (env_quiet && strcmp(env_quiet, "yes") == 0)) | 1039 | if (check_arg(argc, argv, "--quiet", 1) || (env_quiet && strcmp(env_quiet, "yes") == 0)) |
1032 | arg_quiet = 1; | 1040 | arg_quiet = 1; |
1033 | 1041 | ||
@@ -1037,7 +1045,7 @@ int main(int argc, char **argv, char **envp) { | |||
1037 | 1045 | ||
1038 | // build /run/firejail directory structure | 1046 | // build /run/firejail directory structure |
1039 | preproc_build_firejail_dir(); | 1047 | preproc_build_firejail_dir(); |
1040 | char *container_name = getenv("container"); | 1048 | const char *container_name = env_get("container"); |
1041 | if (!container_name || strcmp(container_name, "firejail")) { | 1049 | if (!container_name || strcmp(container_name, "firejail")) { |
1042 | lockfd_directory = open(RUN_DIRECTORY_LOCK_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); | 1050 | lockfd_directory = open(RUN_DIRECTORY_LOCK_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); |
1043 | if (lockfd_directory != -1) { | 1051 | if (lockfd_directory != -1) { |
@@ -1170,6 +1178,9 @@ int main(int argc, char **argv, char **envp) { | |||
1170 | 1178 | ||
1171 | drop_privs(1); | 1179 | drop_privs(1); |
1172 | umask(orig_umask); | 1180 | umask(orig_umask); |
1181 | |||
1182 | // restore original environment variables | ||
1183 | env_apply_all(); | ||
1173 | int rv = system(argv[2]); | 1184 | int rv = system(argv[2]); |
1174 | exit(rv); | 1185 | exit(rv); |
1175 | } | 1186 | } |
diff --git a/src/firejail/no_sandbox.c b/src/firejail/no_sandbox.c index 6c7803602..111d94333 100644 --- a/src/firejail/no_sandbox.c +++ b/src/firejail/no_sandbox.c | |||
@@ -41,7 +41,7 @@ int check_namespace_virt(void) { | |||
41 | EUID_ASSERT(); | 41 | EUID_ASSERT(); |
42 | 42 | ||
43 | // check container environment variable | 43 | // check container environment variable |
44 | char *str = getenv("container"); | 44 | const char *str = env_get("container"); |
45 | if (str && is_container(str)) | 45 | if (str && is_container(str)) |
46 | return 1; | 46 | return 1; |
47 | 47 | ||
diff --git a/src/firejail/output.c b/src/firejail/output.c index 36cb905cb..1682ee025 100644 --- a/src/firejail/output.c +++ b/src/firejail/output.c | |||
@@ -95,6 +95,9 @@ void check_output(int argc, char **argv) { | |||
95 | close(pipefd[0]); | 95 | close(pipefd[0]); |
96 | } | 96 | } |
97 | 97 | ||
98 | // restore some environment variables | ||
99 | env_apply_whitelist_sbox(); | ||
100 | |||
98 | char *args[3]; | 101 | char *args[3]; |
99 | args[0] = LIBDIR "/firejail/ftee"; | 102 | args[0] = LIBDIR "/firejail/ftee"; |
100 | args[1] = outfile; | 103 | args[1] = outfile; |
@@ -137,6 +140,10 @@ void check_output(int argc, char **argv) { | |||
137 | } | 140 | } |
138 | args[j++] = argv[i]; | 141 | args[j++] = argv[i]; |
139 | } | 142 | } |
143 | |||
144 | // restore original environment variables | ||
145 | env_apply_all(); | ||
146 | |||
140 | execvp(args[0], args); | 147 | execvp(args[0], args); |
141 | 148 | ||
142 | perror("execvp"); | 149 | perror("execvp"); |
diff --git a/src/firejail/paths.c b/src/firejail/paths.c index 5de704bef..981a6bc71 100644 --- a/src/firejail/paths.c +++ b/src/firejail/paths.c | |||
@@ -26,13 +26,13 @@ static unsigned int longest_path_elt = 0; | |||
26 | 26 | ||
27 | static char *elt = NULL; // moved from inside init_paths in order to get rid of scan-build warning | 27 | static char *elt = NULL; // moved from inside init_paths in order to get rid of scan-build warning |
28 | static void init_paths(void) { | 28 | static void init_paths(void) { |
29 | char *path = getenv("PATH"); | 29 | const char *env_path = env_get("PATH"); |
30 | char *p; | 30 | char *p; |
31 | if (!path) { | 31 | if (!env_path) { |
32 | path = "/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"; | 32 | env_path = "/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"; |
33 | setenv("PATH", path, 1); | 33 | env_store_name_val("PATH", env_path, SETENV); |
34 | } | 34 | } |
35 | path = strdup(path); | 35 | char *path = strdup(env_path); |
36 | if (!path) | 36 | if (!path) |
37 | errExit("strdup"); | 37 | errExit("strdup"); |
38 | 38 | ||
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 1ee8cdfcb..3766ba8f0 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -158,7 +158,7 @@ static int check_nosound(void) { | |||
158 | } | 158 | } |
159 | 159 | ||
160 | static int check_x11(void) { | 160 | static int check_x11(void) { |
161 | return (arg_x11_block || arg_x11_xorg || getenv("FIREJAIL_X11")); | 161 | return (arg_x11_block || arg_x11_xorg || env_get("FIREJAIL_X11")); |
162 | } | 162 | } |
163 | 163 | ||
164 | static int check_disable_u2f(void) { | 164 | static int check_disable_u2f(void) { |
@@ -1181,7 +1181,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
1181 | if (strcmp(ptr, "x11 xephyr") == 0) { | 1181 | if (strcmp(ptr, "x11 xephyr") == 0) { |
1182 | #ifdef HAVE_X11 | 1182 | #ifdef HAVE_X11 |
1183 | if (checkcfg(CFG_X11)) { | 1183 | if (checkcfg(CFG_X11)) { |
1184 | char *x11env = getenv("FIREJAIL_X11"); | 1184 | const char *x11env = env_get("FIREJAIL_X11"); |
1185 | if (x11env && strcmp(x11env, "yes") == 0) { | 1185 | if (x11env && strcmp(x11env, "yes") == 0) { |
1186 | return 0; | 1186 | return 0; |
1187 | } | 1187 | } |
@@ -1210,7 +1210,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
1210 | if (strcmp(ptr, "x11 xpra") == 0) { | 1210 | if (strcmp(ptr, "x11 xpra") == 0) { |
1211 | #ifdef HAVE_X11 | 1211 | #ifdef HAVE_X11 |
1212 | if (checkcfg(CFG_X11)) { | 1212 | if (checkcfg(CFG_X11)) { |
1213 | char *x11env = getenv("FIREJAIL_X11"); | 1213 | const char *x11env = env_get("FIREJAIL_X11"); |
1214 | if (x11env && strcmp(x11env, "yes") == 0) { | 1214 | if (x11env && strcmp(x11env, "yes") == 0) { |
1215 | return 0; | 1215 | return 0; |
1216 | } | 1216 | } |
@@ -1229,7 +1229,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
1229 | if (strcmp(ptr, "x11 xvfb") == 0) { | 1229 | if (strcmp(ptr, "x11 xvfb") == 0) { |
1230 | #ifdef HAVE_X11 | 1230 | #ifdef HAVE_X11 |
1231 | if (checkcfg(CFG_X11)) { | 1231 | if (checkcfg(CFG_X11)) { |
1232 | char *x11env = getenv("FIREJAIL_X11"); | 1232 | const char *x11env = env_get("FIREJAIL_X11"); |
1233 | if (x11env && strcmp(x11env, "yes") == 0) { | 1233 | if (x11env && strcmp(x11env, "yes") == 0) { |
1234 | return 0; | 1234 | return 0; |
1235 | } | 1235 | } |
@@ -1248,7 +1248,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
1248 | if (strcmp(ptr, "x11") == 0) { | 1248 | if (strcmp(ptr, "x11") == 0) { |
1249 | #ifdef HAVE_X11 | 1249 | #ifdef HAVE_X11 |
1250 | if (checkcfg(CFG_X11)) { | 1250 | if (checkcfg(CFG_X11)) { |
1251 | char *x11env = getenv("FIREJAIL_X11"); | 1251 | const char *x11env = env_get("FIREJAIL_X11"); |
1252 | if (x11env && strcmp(x11env, "yes") == 0) { | 1252 | if (x11env && strcmp(x11env, "yes") == 0) { |
1253 | return 0; | 1253 | return 0; |
1254 | } | 1254 | } |
diff --git a/src/firejail/pulseaudio.c b/src/firejail/pulseaudio.c index a5c924a70..5df3d9cd3 100644 --- a/src/firejail/pulseaudio.c +++ b/src/firejail/pulseaudio.c | |||
@@ -42,7 +42,7 @@ void pulseaudio_disable(void) { | |||
42 | 42 | ||
43 | 43 | ||
44 | // blacklist pulseaudio socket in XDG_RUNTIME_DIR | 44 | // blacklist pulseaudio socket in XDG_RUNTIME_DIR |
45 | char *name = getenv("XDG_RUNTIME_DIR"); | 45 | const char *name = env_get("XDG_RUNTIME_DIR"); |
46 | if (name) | 46 | if (name) |
47 | disable_file_path(name, "pulse/native"); | 47 | disable_file_path(name, "pulse/native"); |
48 | 48 | ||
@@ -76,7 +76,10 @@ void pulseaudio_disable(void) { | |||
76 | } | 76 | } |
77 | 77 | ||
78 | static void pulseaudio_fallback(const char *path) { | 78 | static void pulseaudio_fallback(const char *path) { |
79 | assert(path); | ||
80 | |||
79 | fmessage("Cannot mount tmpfs on %s/.config/pulse\n", cfg.homedir); | 81 | fmessage("Cannot mount tmpfs on %s/.config/pulse\n", cfg.homedir); |
82 | env_store_name_val("PULSE_CLIENTCONFIG", path, SETENV); | ||
80 | if (setenv("PULSE_CLIENTCONFIG", path, 1) < 0) | 83 | if (setenv("PULSE_CLIENTCONFIG", path, 1) < 0) |
81 | errExit("setenv"); | 84 | errExit("setenv"); |
82 | } | 85 | } |
diff --git a/src/firejail/run_symlink.c b/src/firejail/run_symlink.c index b38cc0ca6..5bf27fc6d 100644 --- a/src/firejail/run_symlink.c +++ b/src/firejail/run_symlink.c | |||
@@ -42,7 +42,8 @@ void run_symlink(int argc, char **argv, int run_as_is) { | |||
42 | errExit("setresuid"); | 42 | errExit("setresuid"); |
43 | 43 | ||
44 | // find the real program by looking in PATH | 44 | // find the real program by looking in PATH |
45 | if (!getenv("PATH")) { | 45 | const char *path = env_get("PATH"); |
46 | if (!path) { | ||
46 | fprintf(stderr, "Error: PATH environment variable not set\n"); | 47 | fprintf(stderr, "Error: PATH environment variable not set\n"); |
47 | exit(1); | 48 | exit(1); |
48 | } | 49 | } |
@@ -57,6 +58,9 @@ void run_symlink(int argc, char **argv, int run_as_is) { | |||
57 | // restore original umask | 58 | // restore original umask |
58 | umask(orig_umask); | 59 | umask(orig_umask); |
59 | 60 | ||
61 | // restore original environment variables | ||
62 | env_apply_all(); | ||
63 | |||
60 | // desktop integration is not supported for root user; instead, the original program is started | 64 | // desktop integration is not supported for root user; instead, the original program is started |
61 | if (getuid() == 0 || run_as_is) { | 65 | if (getuid() == 0 || run_as_is) { |
62 | argv[0] = program; | 66 | argv[0] = program; |
@@ -73,6 +77,7 @@ void run_symlink(int argc, char **argv, int run_as_is) { | |||
73 | a[i + 2] = argv[i + 1]; | 77 | a[i + 2] = argv[i + 1]; |
74 | } | 78 | } |
75 | a[i + 2] = NULL; | 79 | a[i + 2] = NULL; |
80 | assert(env_get("LD_PRELOAD") == NULL); | ||
76 | assert(getenv("LD_PRELOAD") == NULL); | 81 | assert(getenv("LD_PRELOAD") == NULL); |
77 | execvp(a[0], a); | 82 | execvp(a[0], a); |
78 | 83 | ||
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index d811fe45a..1f94d86cd 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -268,8 +268,7 @@ static void sandbox_if_up(Bridge *br) { | |||
268 | 268 | ||
269 | static void chk_chroot(void) { | 269 | static void chk_chroot(void) { |
270 | // if we are starting firejail inside some other container technology, we don't care about this | 270 | // if we are starting firejail inside some other container technology, we don't care about this |
271 | char *mycont = getenv("container"); | 271 | if (env_get("container")) |
272 | if (mycont) | ||
273 | return; | 272 | return; |
274 | 273 | ||
275 | // check if this is a regular chroot | 274 | // check if this is a regular chroot |
@@ -419,7 +418,7 @@ static int ok_to_run(const char *program) { | |||
419 | return 1; | 418 | return 1; |
420 | } | 419 | } |
421 | else { // search $PATH | 420 | else { // search $PATH |
422 | char *path1 = getenv("PATH"); | 421 | const char *path1 = env_get("PATH"); |
423 | if (path1) { | 422 | if (path1) { |
424 | if (arg_debug) | 423 | if (arg_debug) |
425 | printf("Searching $PATH for %s\n", program); | 424 | printf("Searching $PATH for %s\n", program); |
@@ -465,7 +464,7 @@ void start_application(int no_sandbox, int fd, char *set_sandbox_status) { | |||
465 | // set environment | 464 | // set environment |
466 | if (no_sandbox == 0) { | 465 | if (no_sandbox == 0) { |
467 | env_defaults(); | 466 | env_defaults(); |
468 | env_apply(); | 467 | env_apply_all(); |
469 | } | 468 | } |
470 | // restore original umask | 469 | // restore original umask |
471 | umask(orig_umask); | 470 | umask(orig_umask); |
diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c index c3d3bd72c..baf99c5b9 100644 --- a/src/firejail/sbox.c +++ b/src/firejail/sbox.c | |||
@@ -36,7 +36,7 @@ static int __attribute__((noreturn)) sbox_do_exec_v(unsigned filtermask, char * | |||
36 | int env_index = 0; | 36 | int env_index = 0; |
37 | char *new_environment[256] = { NULL }; | 37 | char *new_environment[256] = { NULL }; |
38 | // preserve firejail-specific env vars | 38 | // preserve firejail-specific env vars |
39 | char *cl = getenv("FIREJAIL_FILE_COPY_LIMIT"); | 39 | const char *cl = env_get("FIREJAIL_FILE_COPY_LIMIT"); |
40 | if (cl) { | 40 | if (cl) { |
41 | if (asprintf(&new_environment[env_index++], "FIREJAIL_FILE_COPY_LIMIT=%s", cl) == -1) | 41 | if (asprintf(&new_environment[env_index++], "FIREJAIL_FILE_COPY_LIMIT=%s", cl) == -1) |
42 | errExit("asprintf"); | 42 | errExit("asprintf"); |
diff --git a/src/firejail/x11.c b/src/firejail/x11.c index 4872a5207..1121ec84e 100644 --- a/src/firejail/x11.c +++ b/src/firejail/x11.c | |||
@@ -41,7 +41,7 @@ | |||
41 | // Parse the DISPLAY environment variable and return a display number. | 41 | // Parse the DISPLAY environment variable and return a display number. |
42 | // Returns -1 if DISPLAY is not set, or is set to anything other than :ddd. | 42 | // Returns -1 if DISPLAY is not set, or is set to anything other than :ddd. |
43 | int x11_display(void) { | 43 | int x11_display(void) { |
44 | const char *display_str = getenv("DISPLAY"); | 44 | const char *display_str = env_get("DISPLAY"); |
45 | char *endp; | 45 | char *endp; |
46 | unsigned long display; | 46 | unsigned long display; |
47 | 47 | ||
@@ -208,7 +208,7 @@ void x11_start_xvfb(int argc, char **argv) { | |||
208 | pid_t jail = 0; | 208 | pid_t jail = 0; |
209 | pid_t server = 0; | 209 | pid_t server = 0; |
210 | 210 | ||
211 | setenv("FIREJAIL_X11", "yes", 1); | 211 | env_store_name_val("FIREJAIL_X11", "yes", SETENV); |
212 | 212 | ||
213 | // never try to run X servers as root!!! | 213 | // never try to run X servers as root!!! |
214 | if (getuid() == 0) { | 214 | if (getuid() == 0) { |
@@ -326,7 +326,11 @@ void x11_start_xvfb(int argc, char **argv) { | |||
326 | if (arg_debug) | 326 | if (arg_debug) |
327 | printf("Starting xvfb...\n"); | 327 | printf("Starting xvfb...\n"); |
328 | 328 | ||
329 | // restore original environment variables | ||
330 | env_apply_all(); | ||
331 | |||
329 | // running without privileges - see drop_privs call above | 332 | // running without privileges - see drop_privs call above |
333 | assert(env_get("LD_PRELOAD") == NULL); | ||
330 | assert(getenv("LD_PRELOAD") == NULL); | 334 | assert(getenv("LD_PRELOAD") == NULL); |
331 | execvp(server_argv[0], server_argv); | 335 | execvp(server_argv[0], server_argv); |
332 | perror("execvp"); | 336 | perror("execvp"); |
@@ -355,7 +359,7 @@ void x11_start_xvfb(int argc, char **argv) { | |||
355 | free(fname); | 359 | free(fname); |
356 | 360 | ||
357 | assert(display_str); | 361 | assert(display_str); |
358 | setenv("DISPLAY", display_str, 1); | 362 | env_store_name_val("DISPLAY", display_str, SETENV); |
359 | // run attach command | 363 | // run attach command |
360 | jail = fork(); | 364 | jail = fork(); |
361 | if (jail < 0) | 365 | if (jail < 0) |
@@ -363,7 +367,11 @@ void x11_start_xvfb(int argc, char **argv) { | |||
363 | if (jail == 0) { | 367 | if (jail == 0) { |
364 | fmessage("\n*** Attaching to Xvfb display %d ***\n\n", display); | 368 | fmessage("\n*** Attaching to Xvfb display %d ***\n\n", display); |
365 | 369 | ||
370 | // restore original environment variables | ||
371 | env_apply_all(); | ||
372 | |||
366 | // running without privileges - see drop_privs call above | 373 | // running without privileges - see drop_privs call above |
374 | assert(env_get("LD_PRELOAD") == NULL); | ||
367 | assert(getenv("LD_PRELOAD") == NULL); | 375 | assert(getenv("LD_PRELOAD") == NULL); |
368 | execvp(jail_argv[0], jail_argv); | 376 | execvp(jail_argv[0], jail_argv); |
369 | perror("execvp"); | 377 | perror("execvp"); |
@@ -428,7 +436,7 @@ void x11_start_xephyr(int argc, char **argv) { | |||
428 | if (newscreen) | 436 | if (newscreen) |
429 | xephyr_screen = newscreen; | 437 | xephyr_screen = newscreen; |
430 | 438 | ||
431 | setenv("FIREJAIL_X11", "yes", 1); | 439 | env_store_name_val("FIREJAIL_X11", "yes", SETENV); |
432 | 440 | ||
433 | // unfortunately, xephyr does a number of weird things when started by root user!!! | 441 | // unfortunately, xephyr does a number of weird things when started by root user!!! |
434 | if (getuid() == 0) { | 442 | if (getuid() == 0) { |
@@ -556,7 +564,11 @@ void x11_start_xephyr(int argc, char **argv) { | |||
556 | if (arg_debug) | 564 | if (arg_debug) |
557 | printf("Starting xephyr...\n"); | 565 | printf("Starting xephyr...\n"); |
558 | 566 | ||
567 | // restore original environment variables | ||
568 | env_apply_all(); | ||
569 | |||
559 | // running without privileges - see drop_privs call above | 570 | // running without privileges - see drop_privs call above |
571 | assert(env_get("LD_PRELOAD") == NULL); | ||
560 | assert(getenv("LD_PRELOAD") == NULL); | 572 | assert(getenv("LD_PRELOAD") == NULL); |
561 | execvp(server_argv[0], server_argv); | 573 | execvp(server_argv[0], server_argv); |
562 | perror("execvp"); | 574 | perror("execvp"); |
@@ -585,7 +597,7 @@ void x11_start_xephyr(int argc, char **argv) { | |||
585 | free(fname); | 597 | free(fname); |
586 | 598 | ||
587 | assert(display_str); | 599 | assert(display_str); |
588 | setenv("DISPLAY", display_str, 1); | 600 | env_store_name_val("DISPLAY", display_str, SETENV); |
589 | // run attach command | 601 | // run attach command |
590 | jail = fork(); | 602 | jail = fork(); |
591 | if (jail < 0) | 603 | if (jail < 0) |
@@ -594,8 +606,12 @@ void x11_start_xephyr(int argc, char **argv) { | |||
594 | if (!arg_quiet) | 606 | if (!arg_quiet) |
595 | printf("\n*** Attaching to Xephyr display %d ***\n\n", display); | 607 | printf("\n*** Attaching to Xephyr display %d ***\n\n", display); |
596 | 608 | ||
609 | // restore original environment variables | ||
610 | env_apply_all(); | ||
611 | |||
597 | // running without privileges - see drop_privs call above | 612 | // running without privileges - see drop_privs call above |
598 | assert(getenv("LD_PRELOAD") == NULL); | 613 | assert(getenv("LD_PRELOAD") == NULL); |
614 | assert(env_get("LD_PRELOAD") == NULL); | ||
599 | execvp(jail_argv[0], jail_argv); | 615 | execvp(jail_argv[0], jail_argv); |
600 | perror("execvp"); | 616 | perror("execvp"); |
601 | _exit(1); | 617 | _exit(1); |
@@ -780,8 +796,12 @@ static void __attribute__((noreturn)) x11_start_xpra_old(int argc, char **argv, | |||
780 | dup2(fd_null,2); | 796 | dup2(fd_null,2); |
781 | } | 797 | } |
782 | 798 | ||
799 | // restore original environment variables | ||
800 | env_apply_all(); | ||
801 | |||
783 | // running without privileges - see drop_privs call above | 802 | // running without privileges - see drop_privs call above |
784 | assert(getenv("LD_PRELOAD") == NULL); | 803 | assert(getenv("LD_PRELOAD") == NULL); |
804 | assert(env_get("LD_PRELOAD") == NULL); | ||
785 | execvp(server_argv[0], server_argv); | 805 | execvp(server_argv[0], server_argv); |
786 | perror("execvp"); | 806 | perror("execvp"); |
787 | _exit(1); | 807 | _exit(1); |
@@ -827,7 +847,11 @@ static void __attribute__((noreturn)) x11_start_xpra_old(int argc, char **argv, | |||
827 | 847 | ||
828 | fmessage("\n*** Attaching to xpra display %d ***\n\n", display); | 848 | fmessage("\n*** Attaching to xpra display %d ***\n\n", display); |
829 | 849 | ||
850 | // restore original environment variables | ||
851 | env_apply_all(); | ||
852 | |||
830 | // running without privileges - see drop_privs call above | 853 | // running without privileges - see drop_privs call above |
854 | assert(env_get("LD_PRELOAD") == NULL); | ||
831 | assert(getenv("LD_PRELOAD") == NULL); | 855 | assert(getenv("LD_PRELOAD") == NULL); |
832 | execvp(attach_argv[0], attach_argv); | 856 | execvp(attach_argv[0], attach_argv); |
833 | perror("execvp"); | 857 | perror("execvp"); |
@@ -835,7 +859,7 @@ static void __attribute__((noreturn)) x11_start_xpra_old(int argc, char **argv, | |||
835 | } | 859 | } |
836 | 860 | ||
837 | assert(display_str); | 861 | assert(display_str); |
838 | setenv("DISPLAY", display_str, 1); | 862 | env_store_name_val("DISPLAY", display_str, SETENV); |
839 | 863 | ||
840 | // build jail command | 864 | // build jail command |
841 | char *firejail_argv[argc+2]; | 865 | char *firejail_argv[argc+2]; |
@@ -857,7 +881,12 @@ static void __attribute__((noreturn)) x11_start_xpra_old(int argc, char **argv, | |||
857 | errExit("fork"); | 881 | errExit("fork"); |
858 | if (jail == 0) { | 882 | if (jail == 0) { |
859 | // running without privileges - see drop_privs call above | 883 | // running without privileges - see drop_privs call above |
884 | assert(env_get("LD_PRELOAD") == NULL); | ||
860 | assert(getenv("LD_PRELOAD") == NULL); | 885 | assert(getenv("LD_PRELOAD") == NULL); |
886 | |||
887 | // restore original environment variables | ||
888 | env_apply_all(); | ||
889 | |||
861 | if (firejail_argv[0]) // shut up llvm scan-build | 890 | if (firejail_argv[0]) // shut up llvm scan-build |
862 | execvp(firejail_argv[0], firejail_argv); | 891 | execvp(firejail_argv[0], firejail_argv); |
863 | perror("execvp"); | 892 | perror("execvp"); |
@@ -883,7 +912,12 @@ static void __attribute__((noreturn)) x11_start_xpra_old(int argc, char **argv, | |||
883 | dup2(fd_null,1); | 912 | dup2(fd_null,1); |
884 | dup2(fd_null,2); | 913 | dup2(fd_null,2); |
885 | } | 914 | } |
915 | |||
916 | // restore original environment variables | ||
917 | env_apply_all(); | ||
918 | |||
886 | // running without privileges - see drop_privs call above | 919 | // running without privileges - see drop_privs call above |
920 | assert(env_get("LD_PRELOAD") == NULL); | ||
887 | assert(getenv("LD_PRELOAD") == NULL); | 921 | assert(getenv("LD_PRELOAD") == NULL); |
888 | execvp(stop_argv[0], stop_argv); | 922 | execvp(stop_argv[0], stop_argv); |
889 | perror("execvp"); | 923 | perror("execvp"); |
@@ -1051,7 +1085,11 @@ static void __attribute__((noreturn)) x11_start_xpra_new(int argc, char **argv, | |||
1051 | dup2(fd_null,2); | 1085 | dup2(fd_null,2); |
1052 | } | 1086 | } |
1053 | 1087 | ||
1088 | // restore original environment variables | ||
1089 | env_apply_all(); | ||
1090 | |||
1054 | // running without privileges - see drop_privs call above | 1091 | // running without privileges - see drop_privs call above |
1092 | assert(env_get("LD_PRELOAD") == NULL); | ||
1055 | assert(getenv("LD_PRELOAD") == NULL); | 1093 | assert(getenv("LD_PRELOAD") == NULL); |
1056 | execvp(server_argv[0], server_argv); | 1094 | execvp(server_argv[0], server_argv); |
1057 | perror("execvp"); | 1095 | perror("execvp"); |
@@ -1072,7 +1110,7 @@ static void __attribute__((noreturn)) x11_start_xpra_new(int argc, char **argv, | |||
1072 | void x11_start_xpra(int argc, char **argv) { | 1110 | void x11_start_xpra(int argc, char **argv) { |
1073 | EUID_ASSERT(); | 1111 | EUID_ASSERT(); |
1074 | 1112 | ||
1075 | setenv("FIREJAIL_X11", "yes", 1); | 1113 | env_store_name_val("FIREJAIL_X11", "yes", SETENV); |
1076 | 1114 | ||
1077 | // unfortunately, xpra does a number of weird things when started by root user!!! | 1115 | // unfortunately, xpra does a number of weird things when started by root user!!! |
1078 | if (getuid() == 0) { | 1116 | if (getuid() == 0) { |
@@ -1134,7 +1172,7 @@ void x11_xorg(void) { | |||
1134 | #ifdef HAVE_X11 | 1172 | #ifdef HAVE_X11 |
1135 | 1173 | ||
1136 | // get DISPLAY env | 1174 | // get DISPLAY env |
1137 | char *display = getenv("DISPLAY"); | 1175 | const char *display = env_get("DISPLAY"); |
1138 | if (!display) { | 1176 | if (!display) { |
1139 | fputs("Error: --x11=xorg requires an 'outer' X11 server to use.\n", stderr); | 1177 | fputs("Error: --x11=xorg requires an 'outer' X11 server to use.\n", stderr); |
1140 | exit(1); | 1178 | exit(1); |
@@ -1259,7 +1297,7 @@ void x11_xorg(void) { | |||
1259 | ASSERT_PERMS(dest, getuid(), getgid(), 0600); | 1297 | ASSERT_PERMS(dest, getuid(), getgid(), 0600); |
1260 | 1298 | ||
1261 | // blacklist user .Xauthority file if it is not masked already | 1299 | // blacklist user .Xauthority file if it is not masked already |
1262 | char *envar = getenv("XAUTHORITY"); | 1300 | const char *envar = env_get("XAUTHORITY"); |
1263 | if (envar) { | 1301 | if (envar) { |
1264 | char *rp = realpath(envar, NULL); | 1302 | char *rp = realpath(envar, NULL); |
1265 | if (rp) { | 1303 | if (rp) { |
@@ -1269,8 +1307,7 @@ void x11_xorg(void) { | |||
1269 | } | 1307 | } |
1270 | } | 1308 | } |
1271 | // set environment variable | 1309 | // set environment variable |
1272 | if (setenv("XAUTHORITY", dest, 1) < 0) | 1310 | env_store_name_val("XAUTHORITY", dest, SETENV); |
1273 | errExit("setenv"); | ||
1274 | free(dest); | 1311 | free(dest); |
1275 | 1312 | ||
1276 | // mask RUN_XAUTHORITY_SEC_DIR | 1313 | // mask RUN_XAUTHORITY_SEC_DIR |
@@ -1391,7 +1428,7 @@ void x11_block(void) { | |||
1391 | errExit("strdup"); | 1428 | errExit("strdup"); |
1392 | profile_check_line(cmd, 0, NULL); | 1429 | profile_check_line(cmd, 0, NULL); |
1393 | profile_add(cmd); | 1430 | profile_add(cmd); |
1394 | char *xauthority = getenv("XAUTHORITY"); | 1431 | const char *xauthority = env_get("XAUTHORITY"); |
1395 | if (xauthority) { | 1432 | if (xauthority) { |
1396 | char *line; | 1433 | char *line; |
1397 | if (asprintf(&line, "blacklist %s", xauthority) == -1) | 1434 | if (asprintf(&line, "blacklist %s", xauthority) == -1) |