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