aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@protonmail.com>2021-02-09 08:30:41 -0500
committerLibravatar GitHub <noreply@github.com>2021-02-09 08:30:41 -0500
commit06e6dfe31ab23f0ed4e56799efffc03dfb1e2c0e (patch)
tree846e6bc2ed2deac9f5b38a12af720fb2f2ad4bff
parentbump RELNOTES date to fix CI (diff)
parentFilter environment variables (diff)
downloadfirejail-06e6dfe31ab23f0ed4e56799efffc03dfb1e2c0e.tar.gz
firejail-06e6dfe31ab23f0ed4e56799efffc03dfb1e2c0e.tar.zst
firejail-06e6dfe31ab23f0ed4e56799efffc03dfb1e2c0e.zip
Merge pull request #3322 from topimiettinen/filter-environment-variables
Filter environment variables
-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)