aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Topi Miettinen <toiwoton@gmail.com>2020-04-06 21:24:16 +0300
committerLibravatar Topi Miettinen <toiwoton@gmail.com>2021-02-08 19:19:09 +0200
commit1c7ea15b30d49d32a0e3cb79152514f1aeb19397 (patch)
tree73d5d0f553e08d6d9a64f85c29a5c6df5433cda7 /src
parentuse ${DOWNLOADS} in lutris.profile (#3955) (diff)
downloadfirejail-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.c18
-rw-r--r--src/firejail/checkcfg.c6
-rw-r--r--src/firejail/chroot.c4
-rw-r--r--src/firejail/dbus.c30
-rw-r--r--src/firejail/env.c164
-rw-r--r--src/firejail/firejail.h11
-rw-r--r--src/firejail/fs.c2
-rw-r--r--src/firejail/fs_whitelist.c2
-rw-r--r--src/firejail/join.c2
-rw-r--r--src/firejail/main.c53
-rw-r--r--src/firejail/no_sandbox.c2
-rw-r--r--src/firejail/output.c7
-rw-r--r--src/firejail/paths.c10
-rw-r--r--src/firejail/profile.c10
-rw-r--r--src/firejail/pulseaudio.c5
-rw-r--r--src/firejail/run_symlink.c7
-rw-r--r--src/firejail/sandbox.c7
-rw-r--r--src/firejail/sbox.c2
-rw-r--r--src/firejail/x11.c61
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
438static char *get_socket_env(const char *name) { 438static 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
448void dbus_set_session_bus_env(void) { 448void 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
457void dbus_set_system_bus_env(void) { 453void 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
466static void disable_socket_dir(void) { 458static 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
26typedef struct env_t { 26typedef 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;
32static Env *envlist = NULL; 32static Env *envlist = NULL;
@@ -117,45 +117,35 @@ void env_ibus_load(void) {
117// default sandbox env variables 117// default sandbox env variables
118void env_defaults(void) { 118void 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
172void env_store(const char *str, ENV_OP op) { 162void 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
203void 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
235errexit:
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
214void env_apply(void) { 241void 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
257const 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
273static const char * const env_whitelist[] = {
274 "LANG",
275 "LANGUAGE",
276 "LC_MESSAGES",
277 "PATH"
278};
279
280static 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
290static 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().
317void 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
328void 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
85typedef struct bridge_t { 87typedef struct bridge_t {
86 // on the host 88 // on the host
@@ -655,16 +657,21 @@ int check_kernel_procs(void);
655void run_no_sandbox(int argc, char **argv) __attribute__((noreturn)); 657void 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
660typedef enum { 662typedef enum {
661 SETENV = 0, 663 SETENV = 0,
664 SETENV_ALLOW_EMPTY,
662 RMENV 665 RMENV
663} ENV_OP; 666} ENV_OP;
664 667
665void env_store(const char *str, ENV_OP op); 668void env_store(const char *str, ENV_OP op);
666void env_apply(void); 669void env_store_name_val(const char *name, const char *val, ENV_OP op);
670void env_apply_all(void);
671void env_apply_whitelist(void);
672void env_apply_whitelist_sbox(void);
667void env_defaults(void); 673void env_defaults(void);
674const char *env_get(const char *name);
668void env_ibus_load(void); 675void 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
863char *guess_shell(void) { 863char *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
27static char *elt = NULL; // moved from inside init_paths in order to get rid of scan-build warning 27static char *elt = NULL; // moved from inside init_paths in order to get rid of scan-build warning
28static void init_paths(void) { 28static 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
160static int check_x11(void) { 160static 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
164static int check_disable_u2f(void) { 164static 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
78static void pulseaudio_fallback(const char *path) { 78static 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
269static void chk_chroot(void) { 269static 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.
43int x11_display(void) { 43int 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,
1072void x11_start_xpra(int argc, char **argv) { 1110void 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)