aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fbuilder/build_fs.c4
-rw-r--r--src/fbuilder/build_home.c2
-rw-r--r--src/fbuilder/build_profile.c26
-rw-r--r--src/fcopy/Makefile.in4
-rw-r--r--src/fcopy/main.c33
-rw-r--r--src/firecfg/firecfg.config12
-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.h14
-rw-r--r--src/firejail/fs.c4
-rw-r--r--src/firejail/fs_lib.c88
-rw-r--r--src/firejail/fs_lib2.c10
-rw-r--r--src/firejail/fs_whitelist.c2
-rw-r--r--src/firejail/join.c42
-rw-r--r--src/firejail/main.c60
-rw-r--r--src/firejail/no_sandbox.c17
-rw-r--r--src/firejail/output.c7
-rw-r--r--src/firejail/paths.c10
-rw-r--r--src/firejail/profile.c21
-rw-r--r--src/firejail/pulseaudio.c5
-rw-r--r--src/firejail/run_symlink.c52
-rw-r--r--src/firejail/sandbox.c48
-rw-r--r--src/firejail/sbox.c4
-rw-r--r--src/firejail/seccomp.c46
-rw-r--r--src/firejail/util.c45
-rw-r--r--src/firejail/x11.c61
-rw-r--r--src/fldd/Makefile.in4
-rw-r--r--src/fldd/main.c6
-rw-r--r--src/fnet/Makefile.in4
-rw-r--r--src/fnet/main.c8
-rw-r--r--src/fnetfilter/Makefile.in4
-rw-r--r--src/fnetfilter/main.c8
-rw-r--r--src/fsec-optimize/Makefile.in4
-rw-r--r--src/fsec-optimize/fsec_optimize.h1
-rw-r--r--src/fsec-optimize/main.c23
-rw-r--r--src/fsec-optimize/optimizer.c6
-rw-r--r--src/fsec-print/Makefile.in4
-rw-r--r--src/fsec-print/fsec_print.h1
-rw-r--r--src/fsec-print/main.c5
-rw-r--r--src/fseccomp/Makefile.in4
-rw-r--r--src/fseccomp/fseccomp.h1
-rw-r--r--src/fseccomp/main.c8
-rw-r--r--src/fseccomp/seccomp_secondary.c2
-rw-r--r--src/include/common.h7
-rw-r--r--src/include/seccomp.h10
-rw-r--r--src/lib/common.c34
-rw-r--r--src/lib/syscall.c1
-rw-r--r--src/man/firecfg.txt2
-rw-r--r--src/man/firejail-profile.txt5
-rw-r--r--src/man/firejail.txt14
-rw-r--r--src/profstats/main.c24
54 files changed, 666 insertions, 363 deletions
diff --git a/src/fbuilder/build_fs.c b/src/fbuilder/build_fs.c
index 1b8231033..0bc4a0ee2 100644
--- a/src/fbuilder/build_fs.c
+++ b/src/fbuilder/build_fs.c
@@ -217,6 +217,10 @@ void build_share(const char *fname, FILE *fp) {
217//******************************************* 217//*******************************************
218static FileDB *tmp_out = NULL; 218static FileDB *tmp_out = NULL;
219static void tmp_callback(char *ptr) { 219static void tmp_callback(char *ptr) {
220 // skip strace file
221 if (strncmp(ptr, "/tmp/firejail-strace", 20) == 0)
222 return;
223
220 tmp_out = filedb_add(tmp_out, ptr); 224 tmp_out = filedb_add(tmp_out, ptr);
221} 225}
222 226
diff --git a/src/fbuilder/build_home.c b/src/fbuilder/build_home.c
index fca3396c4..c0f4a3407 100644
--- a/src/fbuilder/build_home.c
+++ b/src/fbuilder/build_home.c
@@ -24,7 +24,7 @@ static FileDB *db_skip = NULL;
24static FileDB *db_out = NULL; 24static FileDB *db_out = NULL;
25 25
26static void load_whitelist_common(void) { 26static void load_whitelist_common(void) {
27 FILE *fp = fopen("/etc/firejail/whitelist-common.inc", "r"); 27 FILE *fp = fopen(SYSCONFDIR "/whitelist-common.inc", "r");
28 if (!fp) { 28 if (!fp) {
29 fprintf(stderr, "Error: cannot open whitelist-common.inc\n"); 29 fprintf(stderr, "Error: cannot open whitelist-common.inc\n");
30 exit(1); 30 exit(1);
diff --git a/src/fbuilder/build_profile.c b/src/fbuilder/build_profile.c
index adc00e67b..09f41a838 100644
--- a/src/fbuilder/build_profile.c
+++ b/src/fbuilder/build_profile.c
@@ -80,10 +80,19 @@ void build_profile(int argc, char **argv, int index, FILE *fp) {
80 stroutput, 80 stroutput,
81 }; 81 };
82 82
83 // detect strace 83 // detect strace and check if Yama LSM allows us to use it
84 int have_strace = 0; 84 int have_strace = 0;
85 if (access("/usr/bin/strace", X_OK) == 0) 85 int have_yama_permission = 1;
86 if (access("/usr/bin/strace", X_OK) == 0) {
86 have_strace = 1; 87 have_strace = 1;
88 FILE *ps = fopen("/proc/sys/kernel/yama/ptrace_scope", "r");
89 if (ps) {
90 unsigned val;
91 if (fscanf(ps, "%u", &val) == 1)
92 have_yama_permission = (val < 2);
93 fclose(ps);
94 }
95 }
87 96
88 // calculate command length 97 // calculate command length
89 unsigned len = (int) sizeof(cmdlist) / sizeof(char*) + argc - index + 1; 98 unsigned len = (int) sizeof(cmdlist) / sizeof(char*) + argc - index + 1;
@@ -93,10 +102,11 @@ void build_profile(int argc, char **argv, int index, FILE *fp) {
93 cmd[0] = cmdlist[0]; // explicit assignment to clean scan-build error 102 cmd[0] = cmdlist[0]; // explicit assignment to clean scan-build error
94 103
95 // build command 104 // build command
105 // skip strace if not installed, or no permission to use it
106 int skip_strace = !(have_strace && have_yama_permission);
96 unsigned i = 0; 107 unsigned i = 0;
97 for (i = 0; i < (int) sizeof(cmdlist) / sizeof(char*); i++) { 108 for (i = 0; i < (int) sizeof(cmdlist) / sizeof(char*); i++) {
98 // skip strace if not installed 109 if (skip_strace && strcmp(cmdlist[i], "/usr/bin/strace") == 0)
99 if (have_strace == 0 && strcmp(cmdlist[i], "/usr/bin/strace") == 0)
100 break; 110 break;
101 cmd[i] = cmdlist[i]; 111 cmd[i] = cmdlist[i];
102 } 112 }
@@ -172,12 +182,14 @@ void build_profile(int argc, char **argv, int index, FILE *fp) {
172 fprintf(fp, "caps.drop all\n"); 182 fprintf(fp, "caps.drop all\n");
173 fprintf(fp, "nonewprivs\n"); 183 fprintf(fp, "nonewprivs\n");
174 fprintf(fp, "seccomp\n"); 184 fprintf(fp, "seccomp\n");
175 if (have_strace) 185 if (!have_strace) {
176 build_seccomp(strace_output, fp);
177 else {
178 fprintf(fp, "# If you install strace on your system, Firejail will also create a\n"); 186 fprintf(fp, "# If you install strace on your system, Firejail will also create a\n");
179 fprintf(fp, "# whitelisted seccomp filter.\n"); 187 fprintf(fp, "# whitelisted seccomp filter.\n");
180 } 188 }
189 else if (!have_yama_permission)
190 fprintf(fp, "# Yama security module prevents creation of a whitelisted seccomp filter\n");
191 else
192 build_seccomp(strace_output, fp);
181 fprintf(fp, "\n"); 193 fprintf(fp, "\n");
182 194
183 fprintf(fp, "### network\n"); 195 fprintf(fp, "### network\n");
diff --git a/src/fcopy/Makefile.in b/src/fcopy/Makefile.in
index 64e277e2d..85f84aa32 100644
--- a/src/fcopy/Makefile.in
+++ b/src/fcopy/Makefile.in
@@ -5,8 +5,8 @@ include ../common.mk
5%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h 5%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h
6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@ 6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@
7 7
8fcopy: $(OBJS) 8fcopy: $(OBJS) ../lib/common.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) 9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS)
10 10
11clean:; rm -fr *.o fcopy *.gcov *.gcda *.gcno *.plist 11clean:; rm -fr *.o fcopy *.gcov *.gcda *.gcno *.plist
12 12
diff --git a/src/fcopy/main.c b/src/fcopy/main.c
index 67237b4ea..e65501d6d 100644
--- a/src/fcopy/main.c
+++ b/src/fcopy/main.c
@@ -23,7 +23,6 @@
23#include <ftw.h> 23#include <ftw.h>
24#include <errno.h> 24#include <errno.h>
25#include <pwd.h> 25#include <pwd.h>
26#include <sys/prctl.h>
27 26
28#if HAVE_SELINUX 27#if HAVE_SELINUX
29#include <sys/stat.h> 28#include <sys/stat.h>
@@ -112,7 +111,7 @@ static void copy_file(const char *srcname, const char *destname, mode_t mode, ui
112 } 111 }
113 112
114 // open destination 113 // open destination
115 int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC, 0755); 114 int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR);
116 if (dst < 0) { 115 if (dst < 0) {
117 if (!arg_quiet) 116 if (!arg_quiet)
118 fprintf(stderr, "Warning fcopy: cannot open %s, file not copied\n", destname); 117 fprintf(stderr, "Warning fcopy: cannot open %s, file not copied\n", destname);
@@ -133,7 +132,8 @@ static void copy_file(const char *srcname, const char *destname, mode_t mode, ui
133 done += rv; 132 done += rv;
134 } 133 }
135 } 134 }
136 fflush(0); 135 if (len < 0)
136 goto errexit;
137 137
138 if (fchown(dst, uid, gid) == -1) 138 if (fchown(dst, uid, gid) == -1)
139 goto errexit; 139 goto errexit;
@@ -180,7 +180,7 @@ void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid,
180 180
181 // if the link is already there, don't create it 181 // if the link is already there, don't create it
182 struct stat s; 182 struct stat s;
183 if (stat(linkpath, &s) == 0) 183 if (lstat(linkpath, &s) == 0)
184 return; 184 return;
185 185
186 char *rp = realpath(target, NULL); 186 char *rp = realpath(target, NULL);
@@ -412,30 +412,21 @@ int main(int argc, char **argv) {
412 exit(1); 412 exit(1);
413 } 413 }
414 414
415#ifdef WARN_DUMPABLE 415 warn_dumpable();
416 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 1 && getuid())
417 fprintf(stderr, "Error fcopy: I am dumpable\n");
418#endif
419
420 // trim trailing chars
421 if (src[strlen(src) - 1] == '/')
422 src[strlen(src) - 1] = '\0';
423 if (dest[strlen(dest) - 1] == '/')
424 dest[strlen(dest) - 1] = '\0';
425 416
426 // check the two files; remove ending / 417 // check the two files; remove ending /
427 int len = strlen(src); 418 size_t len = strlen(src);
428 if (src[len - 1] == '/') 419 while (len > 1 && src[len - 1] == '/')
429 src[len - 1] = '\0'; 420 src[--len] = '\0';
430 if (strcspn(src, "\\*&!?\"'<>%^(){}[];,") != (size_t)len) { 421 if (strcspn(src, "\\*&!?\"'<>%^(){}[];,") != len) {
431 fprintf(stderr, "Error fcopy: invalid source file name %s\n", src); 422 fprintf(stderr, "Error fcopy: invalid source file name %s\n", src);
432 exit(1); 423 exit(1);
433 } 424 }
434 425
435 len = strlen(dest); 426 len = strlen(dest);
436 if (dest[len - 1] == '/') 427 while (len > 1 && dest[len - 1] == '/')
437 dest[len - 1] = '\0'; 428 dest[--len] = '\0';
438 if (strcspn(dest, "\\*&!?\"'<>%^(){}[];,~") != (size_t)len) { 429 if (strcspn(dest, "\\*&!?\"'<>%^(){}[];,~") != len) {
439 fprintf(stderr, "Error fcopy: invalid dest file name %s\n", dest); 430 fprintf(stderr, "Error fcopy: invalid dest file name %s\n", dest);
440 exit(1); 431 exit(1);
441 } 432 }
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config
index eb16a87d8..ad0fdd06a 100644
--- a/src/firecfg/firecfg.config
+++ b/src/firecfg/firecfg.config
@@ -69,6 +69,7 @@ autokey-gtk
69autokey-qt 69autokey-qt
70autokey-run 70autokey-run
71autokey-shell 71autokey-shell
72avidemux3_qt5
72aweather 73aweather
73baloo_file 74baloo_file
74baloo_filemetadata_temp_extractor 75baloo_filemetadata_temp_extractor
@@ -106,6 +107,7 @@ calligra
106calligraauthor 107calligraauthor
107calligraconverter 108calligraconverter
108calligraflow 109calligraflow
110calligragemini
109calligraplan 111calligraplan
110calligraplanwork 112calligraplanwork
111calligrasheets 113calligrasheets
@@ -149,6 +151,7 @@ conkeror
149conky 151conky
150conplay 152conplay
151corebird 153corebird
154coyim
152crawl 155crawl
153crawl-tiles 156crawl-tiles
154crow 157crow
@@ -390,6 +393,7 @@ kazam
390kcalc 393kcalc
391# kdeinit4 394# kdeinit4
392kdenlive 395kdenlive
396kdiff3
393keepass 397keepass
394keepass2 398keepass2
395keepassx 399keepassx
@@ -423,6 +427,7 @@ kwrite
423leafpad 427leafpad
424# less - breaks man 428# less - breaks man
425libreoffice 429libreoffice
430librewolf
426liferea 431liferea
427lightsoff 432lightsoff
428lincity-ng 433lincity-ng
@@ -454,6 +459,7 @@ macrofusion
454magicor 459magicor
455# man 460# man
456manaplus 461manaplus
462marker
457masterpdfeditor 463masterpdfeditor
458masterpdfeditor4 464masterpdfeditor4
459masterpdfeditor5 465masterpdfeditor5
@@ -462,6 +468,7 @@ mate-calculator
462mate-color-select 468mate-color-select
463mate-dictionary 469mate-dictionary
464mathematica 470mathematica
471matrix-mirage
465mattermost-desktop 472mattermost-desktop
466mcabber 473mcabber
467mediainfo 474mediainfo
@@ -473,6 +480,8 @@ mencoder
473mendeleydesktop 480mendeleydesktop
474menulibre 481menulibre
475meteo-qt 482meteo-qt
483microsoft-edge
484microsoft-edge-dev
476midori 485midori
477min 486min
478mindless 487mindless
@@ -618,6 +627,7 @@ qemu-launcher
618qgis 627qgis
619qlipper 628qlipper
620qmmp 629qmmp
630qnapi
621qpdfview 631qpdfview
622qt-faststart 632qt-faststart
623qtox 633qtox
@@ -659,6 +669,7 @@ secret-tool
659shellcheck 669shellcheck
660shortwave 670shortwave
661shotcut 671shotcut
672shotwell
662signal-cli 673signal-cli
663signal-desktop 674signal-desktop
664silentarmy 675silentarmy
@@ -768,6 +779,7 @@ tremulous
768trojita 779trojita
769truecraft 780truecraft
770tshark 781tshark
782tutanota-desktop
771tuxguitar 783tuxguitar
772tvbrowser 784tvbrowser
773twitch 785twitch
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 6c0ebcd43..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
@@ -372,7 +374,7 @@ char *guess_shell(void);
372// sandbox.c 374// sandbox.c
373#define SANDBOX_DONE '1' 375#define SANDBOX_DONE '1'
374int sandbox(void* sandbox_arg); 376int sandbox(void* sandbox_arg);
375void start_application(int no_sandbox, char *set_sandbox_status) __attribute__((noreturn)); 377void start_application(int no_sandbox, int fd, char *set_sandbox_status) __attribute__((noreturn));
376void set_apparmor(void); 378void set_apparmor(void);
377 379
378// network_main.c 380// network_main.c
@@ -513,7 +515,6 @@ void check_private_dir(void);
513void update_map(char *mapping, char *map_file); 515void update_map(char *mapping, char *map_file);
514void wait_for_other(int fd); 516void wait_for_other(int fd);
515void notify_other(int fd); 517void notify_other(int fd);
516const char *gnu_basename(const char *path);
517uid_t pid_get_uid(pid_t pid); 518uid_t pid_get_uid(pid_t pid);
518uid_t get_group_id(const char *group); 519uid_t get_group_id(const char *group);
519int remove_overlay_directory(void); 520int remove_overlay_directory(void);
@@ -656,16 +657,21 @@ int check_kernel_procs(void);
656void run_no_sandbox(int argc, char **argv) __attribute__((noreturn)); 657void run_no_sandbox(int argc, char **argv) __attribute__((noreturn));
657 658
658#define MAX_ENVS 256 // some sane maximum number of environment variables 659#define MAX_ENVS 256 // some sane maximum number of environment variables
659#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
660// env.c 661// env.c
661typedef enum { 662typedef enum {
662 SETENV = 0, 663 SETENV = 0,
664 SETENV_ALLOW_EMPTY,
663 RMENV 665 RMENV
664} ENV_OP; 666} ENV_OP;
665 667
666void env_store(const char *str, ENV_OP op); 668void env_store(const char *str, ENV_OP op);
667void 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);
668void env_defaults(void); 673void env_defaults(void);
674const char *env_get(const char *name);
669void env_ibus_load(void); 675void env_ibus_load(void);
670 676
671// fs_whitelist.c 677// fs_whitelist.c
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index 0d4e496e8..b1c509b30 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -795,6 +795,8 @@ void disable_config(void) {
795 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_PROFILE_DIR); 795 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_PROFILE_DIR);
796 if (stat(RUN_FIREJAIL_X11_DIR, &s) == 0) 796 if (stat(RUN_FIREJAIL_X11_DIR, &s) == 0)
797 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_X11_DIR); 797 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_X11_DIR);
798 if (!arg_appimage && stat(RUN_FIREJAIL_APPIMAGE_DIR, &s) == 0)
799 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_APPIMAGE_DIR);
798} 800}
799 801
800 802
@@ -1219,7 +1221,7 @@ void fs_private_tmp(void) {
1219 printf("Generate private-tmp whitelist commands\n"); 1221 printf("Generate private-tmp whitelist commands\n");
1220 1222
1221 // check XAUTHORITY file, KDE keeps it under /tmp 1223 // check XAUTHORITY file, KDE keeps it under /tmp
1222 char *xauth = getenv("XAUTHORITY"); 1224 const char *xauth = env_get("XAUTHORITY");
1223 if (xauth) { 1225 if (xauth) {
1224 char *rp = realpath(xauth, NULL); 1226 char *rp = realpath(xauth, NULL);
1225 if (rp && strncmp(rp, "/tmp/", 5) == 0) { 1227 if (rp && strncmp(rp, "/tmp/", 5) == 0) {
diff --git a/src/firejail/fs_lib.c b/src/firejail/fs_lib.c
index 5cfd33b42..b8c1b21b1 100644
--- a/src/firejail/fs_lib.c
+++ b/src/firejail/fs_lib.c
@@ -33,6 +33,52 @@ extern void fslib_install_system(void);
33static int lib_cnt = 0; 33static int lib_cnt = 0;
34static int dir_cnt = 0; 34static int dir_cnt = 0;
35 35
36char *find_in_path(const char *program) {
37 EUID_ASSERT();
38 if (arg_debug)
39 printf("Searching $PATH for %s\n", program);
40
41 char self[MAXBUF];
42 ssize_t len = readlink("/proc/self/exe", self, MAXBUF - 1);
43 if (len < 0)
44 errExit("readlink");
45 self[len] = '\0';
46
47 char *path = getenv("PATH");
48 if (!path)
49 return NULL;
50 char *dup = strdup(path);
51 if (!dup)
52 errExit("strdup");
53 char *tok = strtok(dup, ":");
54 while (tok) {
55 char *fname;
56 if (asprintf(&fname, "%s/%s", tok, program) == -1)
57 errExit("asprintf");
58
59 if (arg_debug)
60 printf("trying #%s#\n", fname);
61 struct stat s;
62 if (stat(fname, &s) == 0) {
63 // but skip links created by firecfg
64 char *rp = realpath(fname, NULL);
65 if (!rp)
66 errExit("realpath");
67 if (strcmp(self, rp) != 0) {
68 free(rp);
69 free(dup);
70 return fname;
71 }
72 free(rp);
73 }
74 free(fname);
75 tok = strtok(NULL, ":");
76 }
77
78 free(dup);
79 return NULL;
80}
81
36static void report_duplication(const char *full_path) { 82static void report_duplication(const char *full_path) {
37 char *fname = strrchr(full_path, '/'); 83 char *fname = strrchr(full_path, '/');
38 if (fname && *(++fname) != '\0') { 84 if (fname && *(++fname) != '\0') {
@@ -165,7 +211,7 @@ void fslib_copy_dir(const char *full_path) {
165 mkdir_attr(dest, 0755, 0, 0); 211 mkdir_attr(dest, 0755, 0, 0);
166 212
167 if (mount(full_path, dest, NULL, MS_BIND|MS_REC, NULL) < 0 || 213 if (mount(full_path, dest, NULL, MS_BIND|MS_REC, NULL) < 0 ||
168 mount(NULL, dest, NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0) 214 mount(NULL, dest, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0)
169 errExit("mount bind"); 215 errExit("mount bind");
170 fs_logger2("clone", full_path); 216 fs_logger2("clone", full_path);
171 fs_logger2("mount", full_path); 217 fs_logger2("mount", full_path);
@@ -336,11 +382,40 @@ void fs_private_lib(void) {
336 // start timetrace 382 // start timetrace
337 timetrace_start(); 383 timetrace_start();
338 384
385 // bring in firejail executable libraries in case we are redirected here by a firejail symlink from /usr/local/bin/firejail
386 if (arg_debug || arg_debug_private_lib)
387 printf("Installing Firejail libraries\n");
388 fslib_install_list(PATH_FIREJAIL);
389
390 // bring in firejail directory
391 fslib_install_list(LIBDIR "/firejail");
392
393 // bring in dhclient libraries
394 if (any_dhcp()) {
395 if (arg_debug || arg_debug_private_lib)
396 printf("Installing dhclient libraries\n");
397 fslib_install_list(RUN_MNT_DIR "/dhclient");
398 }
399 fmessage("Firejail libraries installed in %0.2f ms\n", timetrace_end());
400
401 timetrace_start();
402
339 // copy the libs in the new lib directory for the main exe 403 // copy the libs in the new lib directory for the main exe
340 if (cfg.original_program_index > 0) { 404 if (cfg.original_program_index > 0) {
341 if (arg_debug || arg_debug_private_lib) 405 if (arg_debug || arg_debug_private_lib)
342 printf("Installing sandboxed program libraries\n"); 406 printf("Installing sandboxed program libraries\n");
343 fslib_install_list(cfg.original_argv[cfg.original_program_index]); 407
408 if (strchr(cfg.original_argv[cfg.original_program_index], '/'))
409 fslib_install_list(cfg.original_argv[cfg.original_program_index]);
410 else { // search executable in $PATH
411 EUID_USER();
412 char *fname = find_in_path(cfg.original_argv[cfg.original_program_index]);
413 EUID_ROOT();
414 if (fname) {
415 fslib_install_list(fname);
416 free(fname);
417 }
418 }
344 } 419 }
345 420
346 // for the shell 421 // for the shell
@@ -369,18 +444,11 @@ void fs_private_lib(void) {
369 } 444 }
370 fmessage("Program libraries installed in %0.2f ms\n", timetrace_end()); 445 fmessage("Program libraries installed in %0.2f ms\n", timetrace_end());
371 446
372 // install the reset of the system libraries 447 // install the rest of the system libraries
373 if (arg_debug || arg_debug_private_lib) 448 if (arg_debug || arg_debug_private_lib)
374 printf("Installing system libraries\n"); 449 printf("Installing system libraries\n");
375 fslib_install_system(); 450 fslib_install_system();
376 451
377 // bring in firejail directory for --trace and seccomp post exec
378 // bring in firejail executable libraries in case we are redirected here by a firejail symlink from /usr/local/bin/firejail
379 fslib_install_list("/usr/bin/firejail,firejail"); // todo: use the installed path for the executable
380
381 // install libraries needed by fcopy
382 fslib_install_list(PATH_FCOPY);
383
384 fmessage("Installed %d %s and %d %s\n", lib_cnt, (lib_cnt == 1)? "library": "libraries", 452 fmessage("Installed %d %s and %d %s\n", lib_cnt, (lib_cnt == 1)? "library": "libraries",
385 dir_cnt, (dir_cnt == 1)? "directory": "directories"); 453 dir_cnt, (dir_cnt == 1)? "directory": "directories");
386 454
diff --git a/src/firejail/fs_lib2.c b/src/firejail/fs_lib2.c
index b2ae07f3e..95e10ee05 100644
--- a/src/firejail/fs_lib2.c
+++ b/src/firejail/fs_lib2.c
@@ -30,6 +30,7 @@ extern void fslib_copy_dir(const char *full_path);
30//*************************************************************** 30//***************************************************************
31// standard libc libraries based on Debian's libc6 package 31// standard libc libraries based on Debian's libc6 package
32// selinux seems to be linked in most command line utilities 32// selinux seems to be linked in most command line utilities
33// libpcre2 is a dependency of selinux
33// locale (/usr/lib/locale) - without it, the program will default to "C" locale 34// locale (/usr/lib/locale) - without it, the program will default to "C" locale
34typedef struct liblist_t { 35typedef struct liblist_t {
35 const char *name; 36 const char *name;
@@ -38,6 +39,7 @@ typedef struct liblist_t {
38 39
39static LibList libc_list[] = { 40static LibList libc_list[] = {
40 { "libselinux.so.", 0 }, 41 { "libselinux.so.", 0 },
42 { "libpcre2-8.so.", 0 },
41 { "libapparmor.so.", 0}, 43 { "libapparmor.so.", 0},
42 { "ld-linux-x86-64.so.", 0 }, 44 { "ld-linux-x86-64.so.", 0 },
43 { "libanl.so.", 0 }, 45 { "libanl.so.", 0 },
@@ -104,17 +106,15 @@ static void stdc(const char *dirname) {
104 106
105void fslib_install_stdc(void) { 107void fslib_install_stdc(void) {
106 // install standard C libraries 108 // install standard C libraries
109 timetrace_start();
107 struct stat s; 110 struct stat s;
108 char *stdclib = "/lib64"; // CentOS, Fedora, Arch
109
110 if (stat("/lib/x86_64-linux-gnu", &s) == 0) { // Debian & friends 111 if (stat("/lib/x86_64-linux-gnu", &s) == 0) { // Debian & friends
111 mkdir_attr(RUN_LIB_DIR "/x86_64-linux-gnu", 0755, 0, 0); 112 mkdir_attr(RUN_LIB_DIR "/x86_64-linux-gnu", 0755, 0, 0);
112 selinux_relabel_path(RUN_LIB_DIR "/x86_64-linux-gnu", "/lib/x86_64-linux-gnu"); 113 selinux_relabel_path(RUN_LIB_DIR "/x86_64-linux-gnu", "/lib/x86_64-linux-gnu");
113 stdclib = "/lib/x86_64-linux-gnu"; 114 stdc("/lib/x86_64-linux-gnu");
114 } 115 }
115 116
116 timetrace_start(); 117 stdc("/lib64"); // CentOS, Fedora, Arch, ld-linux.so in Debian & friends
117 stdc(stdclib);
118 118
119 // install locale 119 // install locale
120 if (stat("/usr/lib/locale", &s) == 0) 120 if (stat("/usr/lib/locale", &s) == 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 ca8b8c4bf..bdd0f286c 100644
--- a/src/firejail/join.c
+++ b/src/firejail/join.c
@@ -20,10 +20,14 @@
20#include "firejail.h" 20#include "firejail.h"
21#include <sys/stat.h> 21#include <sys/stat.h>
22#include <sys/wait.h> 22#include <sys/wait.h>
23#include <fcntl.h>
24#include <unistd.h> 23#include <unistd.h>
25#include <errno.h> 24#include <errno.h>
26 25
26#include <fcntl.h>
27#ifndef O_PATH
28#define O_PATH 010000000
29#endif
30
27#include <sys/prctl.h> 31#include <sys/prctl.h>
28#ifndef PR_SET_NO_NEW_PRIVS 32#ifndef PR_SET_NO_NEW_PRIVS
29#define PR_SET_NO_NEW_PRIVS 38 33#define PR_SET_NO_NEW_PRIVS 38
@@ -292,13 +296,28 @@ static void extract_umask(pid_t pid) {
292 fprintf(stderr, "Error: cannot open umask file\n"); 296 fprintf(stderr, "Error: cannot open umask file\n");
293 exit(1); 297 exit(1);
294 } 298 }
295 if (fscanf(fp, "%o", &orig_umask) != 1) { 299 if (fscanf(fp, "%3o", &orig_umask) != 1) {
296 fprintf(stderr, "Error: cannot read umask\n"); 300 fprintf(stderr, "Error: cannot read umask\n");
297 exit(1); 301 exit(1);
298 } 302 }
299 fclose(fp); 303 fclose(fp);
300} 304}
301 305
306static int open_shell(void) {
307 EUID_ASSERT();
308 assert(cfg.shell);
309
310 if (arg_debug)
311 printf("Opening shell %s\n", cfg.shell);
312 // file descriptor will leak if not opened with O_CLOEXEC !!
313 int fd = open(cfg.shell, O_PATH|O_CLOEXEC);
314 if (fd == -1) {
315 fprintf(stderr, "Error: cannot open shell %s\n", cfg.shell);
316 exit(1);
317 }
318 return fd;
319}
320
302// return false if the sandbox identified by pid is not fully set up yet or if 321// return false if the sandbox identified by pid is not fully set up yet or if
303// it is no firejail sandbox at all, return true if the sandbox is complete 322// it is no firejail sandbox at all, return true if the sandbox is complete
304bool is_ready_for_join(const pid_t pid) { 323bool is_ready_for_join(const pid_t pid) {
@@ -316,7 +335,7 @@ bool is_ready_for_join(const pid_t pid) {
316 struct stat s; 335 struct stat s;
317 if (fstat(fd, &s) == -1) 336 if (fstat(fd, &s) == -1)
318 errExit("fstat"); 337 errExit("fstat");
319 if (!S_ISREG(s.st_mode) || s.st_uid != 0) { 338 if (!S_ISREG(s.st_mode) || s.st_uid != 0 || s.st_size != 1) {
320 close(fd); 339 close(fd);
321 return false; 340 return false;
322 } 341 }
@@ -391,6 +410,10 @@ void join(pid_t pid, int argc, char **argv, int index) {
391 410
392 extract_x11_display(parent); 411 extract_x11_display(parent);
393 412
413 int shfd = -1;
414 if (!arg_shell_none && !arg_audit)
415 shfd = open_shell();
416
394 EUID_ROOT(); 417 EUID_ROOT();
395 // in user mode set caps seccomp, cpu, cgroup, etc 418 // in user mode set caps seccomp, cpu, cgroup, etc
396 if (getuid() != 0) { 419 if (getuid() != 0) {
@@ -400,6 +423,7 @@ void join(pid_t pid, int argc, char **argv, int index) {
400 extract_cgroup(pid); 423 extract_cgroup(pid);
401 extract_nogroups(pid); 424 extract_nogroups(pid);
402 extract_user_namespace(pid); 425 extract_user_namespace(pid);
426 extract_umask(pid);
403#ifdef HAVE_APPARMOR 427#ifdef HAVE_APPARMOR
404 extract_apparmor(pid); 428 extract_apparmor(pid);
405#endif 429#endif
@@ -409,9 +433,6 @@ void join(pid_t pid, int argc, char **argv, int index) {
409 if (cfg.cgroup) // not available for uid 0 433 if (cfg.cgroup) // not available for uid 0
410 set_cgroup(cfg.cgroup); 434 set_cgroup(cfg.cgroup);
411 435
412 // set umask, also uid 0
413 extract_umask(pid);
414
415 // join namespaces 436 // join namespaces
416 if (arg_join_network) { 437 if (arg_join_network) {
417 if (join_namespace(pid, "net")) 438 if (join_namespace(pid, "net"))
@@ -522,10 +543,9 @@ void join(pid_t pid, int argc, char **argv, int index) {
522 extract_command(argc, argv, index); 543 extract_command(argc, argv, index);
523 if (cfg.command_line == NULL) { 544 if (cfg.command_line == NULL) {
524 assert(cfg.shell); 545 assert(cfg.shell);
525 cfg.command_line = cfg.shell;
526 cfg.window_title = cfg.shell; 546 cfg.window_title = cfg.shell;
527 } 547 }
528 if (arg_debug) 548 else if (arg_debug)
529 printf("Extracted command #%s#\n", cfg.command_line); 549 printf("Extracted command #%s#\n", cfg.command_line);
530 550
531 // set cpu affinity 551 // set cpu affinity
@@ -541,7 +561,7 @@ void join(pid_t pid, int argc, char **argv, int index) {
541 char *display_str; 561 char *display_str;
542 if (asprintf(&display_str, ":%d", display) == -1) 562 if (asprintf(&display_str, ":%d", display) == -1)
543 errExit("asprintf"); 563 errExit("asprintf");
544 setenv("DISPLAY", display_str, 1); 564 env_store_name_val("DISPLAY", display_str, SETENV);
545 free(display_str); 565 free(display_str);
546 } 566 }
547 567
@@ -554,11 +574,13 @@ void join(pid_t pid, int argc, char **argv, int index) {
554 dbus_set_system_bus_env(); 574 dbus_set_system_bus_env();
555#endif 575#endif
556 576
557 start_application(0, NULL); 577 start_application(0, shfd, NULL);
558 578
559 __builtin_unreachable(); 579 __builtin_unreachable();
560 } 580 }
561 EUID_USER(); 581 EUID_USER();
582 if (shfd != -1)
583 close(shfd);
562 584
563 int status = 0; 585 int status = 0;
564 //***************************** 586 //*****************************
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 544bfe83a..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 }
@@ -1231,11 +1242,6 @@ int main(int argc, char **argv, char **envp) {
1231 } 1242 }
1232 EUID_ASSERT(); 1243 EUID_ASSERT();
1233 1244
1234#ifdef WARN_DUMPABLE
1235 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 1 && getuid())
1236 fprintf(stderr, "Error: Firejail is dumpable\n");
1237#endif
1238
1239 // check for force-nonewprivs in /etc/firejail/firejail.config file 1245 // check for force-nonewprivs in /etc/firejail/firejail.config file
1240 if (checkcfg(CFG_FORCE_NONEWPRIVS)) 1246 if (checkcfg(CFG_FORCE_NONEWPRIVS))
1241 arg_nonewprivs = 1; 1247 arg_nonewprivs = 1;
@@ -2787,7 +2793,7 @@ int main(int argc, char **argv, char **envp) {
2787 2793
2788 // build the sandbox command 2794 // build the sandbox command
2789 if (prog_index == -1 && cfg.shell) { 2795 if (prog_index == -1 && cfg.shell) {
2790 cfg.command_line = cfg.shell; 2796 assert(cfg.command_line == NULL); // runs cfg.shell
2791 cfg.window_title = cfg.shell; 2797 cfg.window_title = cfg.shell;
2792 cfg.command_name = cfg.shell; 2798 cfg.command_name = cfg.shell;
2793 } 2799 }
diff --git a/src/firejail/no_sandbox.c b/src/firejail/no_sandbox.c
index 01df77ee6..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
@@ -204,14 +204,15 @@ void run_no_sandbox(int argc, char **argv) {
204 break; 204 break;
205 } 205 }
206 } 206 }
207 // if shell is /usr/bin/firejail, replace it with /bin/bash 207
208 if (strcmp(cfg.shell, PATH_FIREJAIL) == 0) { 208// if shell is /usr/bin/firejail, replace it with /bin/bash
209 cfg.shell = "/bin/bash"; 209// if (strcmp(cfg.shell, PATH_FIREJAIL) == 0) {
210 prog_index = 0; 210// cfg.shell = "/bin/bash";
211 } 211// prog_index = 0;
212// }
212 213
213 if (prog_index == 0) { 214 if (prog_index == 0) {
214 cfg.command_line = cfg.shell; 215 assert(cfg.command_line == NULL); // runs cfg.shell
215 cfg.window_title = cfg.shell; 216 cfg.window_title = cfg.shell;
216 } else { 217 } else {
217 build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index); 218 build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index);
@@ -230,5 +231,5 @@ void run_no_sandbox(int argc, char **argv) {
230 231
231 arg_quiet = 1; 232 arg_quiet = 1;
232 233
233 start_application(1, NULL); 234 start_application(1, -1, NULL);
234} 235}
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 4172c96f7..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) {
@@ -619,6 +619,17 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
619#endif 619#endif
620 return 0; 620 return 0;
621 } 621 }
622 else if (strncmp(ptr, "netns ", 6) == 0) {
623#ifdef HAVE_NETWORK
624 if (checkcfg(CFG_NETWORK)) {
625 arg_netns = ptr + 6;
626 check_netns(arg_netns);
627 }
628 else
629 warning_feature_disabled("networking");
630#endif
631 return 0;
632 }
622 else if (strcmp(ptr, "net none") == 0) { 633 else if (strcmp(ptr, "net none") == 0) {
623 arg_nonetwork = 1; 634 arg_nonetwork = 1;
624 cfg.bridge0.configured = 0; 635 cfg.bridge0.configured = 0;
@@ -1170,7 +1181,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
1170 if (strcmp(ptr, "x11 xephyr") == 0) { 1181 if (strcmp(ptr, "x11 xephyr") == 0) {
1171#ifdef HAVE_X11 1182#ifdef HAVE_X11
1172 if (checkcfg(CFG_X11)) { 1183 if (checkcfg(CFG_X11)) {
1173 char *x11env = getenv("FIREJAIL_X11"); 1184 const char *x11env = env_get("FIREJAIL_X11");
1174 if (x11env && strcmp(x11env, "yes") == 0) { 1185 if (x11env && strcmp(x11env, "yes") == 0) {
1175 return 0; 1186 return 0;
1176 } 1187 }
@@ -1199,7 +1210,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
1199 if (strcmp(ptr, "x11 xpra") == 0) { 1210 if (strcmp(ptr, "x11 xpra") == 0) {
1200#ifdef HAVE_X11 1211#ifdef HAVE_X11
1201 if (checkcfg(CFG_X11)) { 1212 if (checkcfg(CFG_X11)) {
1202 char *x11env = getenv("FIREJAIL_X11"); 1213 const char *x11env = env_get("FIREJAIL_X11");
1203 if (x11env && strcmp(x11env, "yes") == 0) { 1214 if (x11env && strcmp(x11env, "yes") == 0) {
1204 return 0; 1215 return 0;
1205 } 1216 }
@@ -1218,7 +1229,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
1218 if (strcmp(ptr, "x11 xvfb") == 0) { 1229 if (strcmp(ptr, "x11 xvfb") == 0) {
1219#ifdef HAVE_X11 1230#ifdef HAVE_X11
1220 if (checkcfg(CFG_X11)) { 1231 if (checkcfg(CFG_X11)) {
1221 char *x11env = getenv("FIREJAIL_X11"); 1232 const char *x11env = env_get("FIREJAIL_X11");
1222 if (x11env && strcmp(x11env, "yes") == 0) { 1233 if (x11env && strcmp(x11env, "yes") == 0) {
1223 return 0; 1234 return 0;
1224 } 1235 }
@@ -1237,7 +1248,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
1237 if (strcmp(ptr, "x11") == 0) { 1248 if (strcmp(ptr, "x11") == 0) {
1238#ifdef HAVE_X11 1249#ifdef HAVE_X11
1239 if (checkcfg(CFG_X11)) { 1250 if (checkcfg(CFG_X11)) {
1240 char *x11env = getenv("FIREJAIL_X11"); 1251 const char *x11env = env_get("FIREJAIL_X11");
1241 if (x11env && strcmp(x11env, "yes") == 0) { 1252 if (x11env && strcmp(x11env, "yes") == 0) {
1242 return 0; 1253 return 0;
1243 } 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 ea3889024..5bf27fc6d 100644
--- a/src/firejail/run_symlink.c
+++ b/src/firejail/run_symlink.c
@@ -22,6 +22,8 @@
22#include <sys/stat.h> 22#include <sys/stat.h>
23#include <unistd.h> 23#include <unistd.h>
24 24
25extern char *find_in_path(const char *program);
26
25void run_symlink(int argc, char **argv, int run_as_is) { 27void run_symlink(int argc, char **argv, int run_as_is) {
26 EUID_ASSERT(); 28 EUID_ASSERT();
27 29
@@ -40,58 +42,25 @@ void run_symlink(int argc, char **argv, int run_as_is) {
40 errExit("setresuid"); 42 errExit("setresuid");
41 43
42 // find the real program by looking in PATH 44 // find the real program by looking in PATH
43 char *p = getenv("PATH"); 45 const char *path = env_get("PATH");
44 if (!p) { 46 if (!path) {
45 fprintf(stderr, "Error: PATH environment variable not set\n"); 47 fprintf(stderr, "Error: PATH environment variable not set\n");
46 exit(1); 48 exit(1);
47 } 49 }
48 50
49 char *path = strdup(p); 51 char *p = find_in_path(program);
50 if (!path) 52 if (!p) {
51 errExit("strdup");
52
53 char *selfpath = realpath("/proc/self/exe", NULL);
54 if (!selfpath)
55 errExit("realpath");
56
57 // look in path for our program
58 char *tok = strtok(path, ":");
59 int found = 0;
60 while (tok) {
61 char *name;
62 if (asprintf(&name, "%s/%s", tok, program) == -1)
63 errExit("asprintf");
64
65 struct stat s;
66 if (stat(name, &s) == 0) {
67 /* coverity[toctou] */
68 char* rp = realpath(name, NULL);
69 if (!rp)
70 errExit("realpath");
71
72 if (strcmp(selfpath, rp) != 0) {
73 program = strdup(name);
74 found = 1;
75 free(rp);
76 break;
77 }
78
79 free(rp);
80 }
81
82 free(name);
83 tok = strtok(NULL, ":");
84 }
85 if (!found) {
86 fprintf(stderr, "Error: cannot find the program in the path\n"); 53 fprintf(stderr, "Error: cannot find the program in the path\n");
87 exit(1); 54 exit(1);
88 } 55 }
89 56 program = p;
90 free(selfpath);
91 57
92 // restore original umask 58 // restore original umask
93 umask(orig_umask); 59 umask(orig_umask);
94 60
61 // restore original environment variables
62 env_apply_all();
63
95 // 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
96 if (getuid() == 0 || run_as_is) { 65 if (getuid() == 0 || run_as_is) {
97 argv[0] = program; 66 argv[0] = program;
@@ -108,6 +77,7 @@ void run_symlink(int argc, char **argv, int run_as_is) {
108 a[i + 2] = argv[i + 1]; 77 a[i + 2] = argv[i + 1];
109 } 78 }
110 a[i + 2] = NULL; 79 a[i + 2] = NULL;
80 assert(env_get("LD_PRELOAD") == NULL);
111 assert(getenv("LD_PRELOAD") == NULL); 81 assert(getenv("LD_PRELOAD") == NULL);
112 execvp(a[0], a); 82 execvp(a[0], a);
113 83
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 5115191ea..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);
@@ -461,17 +460,17 @@ static int ok_to_run(const char *program) {
461 return 0; 460 return 0;
462} 461}
463 462
464void start_application(int no_sandbox, char *set_sandbox_status) { 463void 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);
472 471
473 if (arg_debug) { 472 if (arg_debug) {
474 printf("starting application\n"); 473 printf("Starting application\n");
475 printf("LD_PRELOAD=%s\n", getenv("LD_PRELOAD")); 474 printf("LD_PRELOAD=%s\n", getenv("LD_PRELOAD"));
476 } 475 }
477 476
@@ -488,9 +487,6 @@ void start_application(int no_sandbox, char *set_sandbox_status) {
488 if (set_sandbox_status) 487 if (set_sandbox_status)
489 *set_sandbox_status = SANDBOX_DONE; 488 *set_sandbox_status = SANDBOX_DONE;
490 execl(arg_audit_prog, arg_audit_prog, NULL); 489 execl(arg_audit_prog, arg_audit_prog, NULL);
491
492 perror("execl");
493 exit(1);
494 } 490 }
495 //**************************************** 491 //****************************************
496 // start the program without using a shell 492 // start the program without using a shell
@@ -532,35 +528,37 @@ void start_application(int no_sandbox, char *set_sandbox_status) {
532 //**************************************** 528 //****************************************
533 else { 529 else {
534 assert(cfg.shell); 530 assert(cfg.shell);
535 assert(cfg.command_line);
536 531
537 char *arg[5]; 532 char *arg[5];
538 int index = 0; 533 int index = 0;
539 arg[index++] = cfg.shell; 534 arg[index++] = cfg.shell;
540 if (login_shell) { 535 if (cfg.command_line) {
541 arg[index++] = "-l";
542 if (arg_debug)
543 printf("Starting %s login shell\n", cfg.shell);
544 } else {
545 arg[index++] = "-c";
546 if (arg_debug) 536 if (arg_debug)
547 printf("Running %s command through %s\n", cfg.command_line, cfg.shell); 537 printf("Running %s command through %s\n", cfg.command_line, cfg.shell);
538 arg[index++] = "-c";
548 if (arg_doubledash) 539 if (arg_doubledash)
549 arg[index++] = "--"; 540 arg[index++] = "--";
550 arg[index++] = cfg.command_line; 541 arg[index++] = cfg.command_line;
551 } 542 }
552 arg[index] = NULL; 543 else if (login_shell) {
544 if (arg_debug)
545 printf("Starting %s login shell\n", cfg.shell);
546 arg[index++] = "-l";
547 }
548 else if (arg_debug)
549 printf("Starting %s shell\n", cfg.shell);
550
553 assert(index < 5); 551 assert(index < 5);
552 arg[index] = NULL;
554 553
555 if (arg_debug) { 554 if (arg_debug) {
556 char *msg; 555 char *msg;
557 if (asprintf(&msg, "sandbox %d, execvp into %s", sandbox_pid, cfg.command_line) == -1) 556 if (asprintf(&msg, "sandbox %d, execvp into %s",
557 sandbox_pid, cfg.command_line ? cfg.command_line : cfg.shell) == -1)
558 errExit("asprintf"); 558 errExit("asprintf");
559 logmsg(msg); 559 logmsg(msg);
560 free(msg); 560 free(msg);
561 }
562 561
563 if (arg_debug) {
564 int i; 562 int i;
565 for (i = 0; i < 5; i++) { 563 for (i = 0; i < 5; i++) {
566 if (arg[i] == NULL) 564 if (arg[i] == NULL)
@@ -580,10 +578,14 @@ void start_application(int no_sandbox, char *set_sandbox_status) {
580 if (set_sandbox_status) 578 if (set_sandbox_status)
581 *set_sandbox_status = SANDBOX_DONE; 579 *set_sandbox_status = SANDBOX_DONE;
582 execvp(arg[0], arg); 580 execvp(arg[0], arg);
581
582 // join sandbox without shell in the mount namespace
583 if (fd > -1)
584 fexecve(fd, arg, environ);
583 } 585 }
584 586
585 perror("execvp"); 587 perror("Cannot start application");
586 exit(1); // it should never get here!!! 588 exit(1);
587} 589}
588 590
589static void enforce_filters(void) { 591static void enforce_filters(void) {
@@ -1223,7 +1225,7 @@ int sandbox(void* sandbox_arg) {
1223 set_nice(cfg.nice); 1225 set_nice(cfg.nice);
1224 set_rlimits(); 1226 set_rlimits();
1225 1227
1226 start_application(0, set_sandbox_status); 1228 start_application(0, -1, set_sandbox_status);
1227 } 1229 }
1228 1230
1229 munmap(set_sandbox_status, 1); 1231 munmap(set_sandbox_status, 1);
diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c
index a2aaa86eb..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");
@@ -120,7 +120,7 @@ static int __attribute__((noreturn)) sbox_do_exec_v(unsigned filtermask, char *
120 // handle X32 ABI 120 // handle X32 ABI
121 BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, X32_SYSCALL_BIT, 1, 0), 121 BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, X32_SYSCALL_BIT, 1, 0),
122 BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, 0, 1, 0), 122 BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, 0, 1, 0),
123 RETURN_ERRNO(EPERM), 123 KILL_OR_RETURN_ERRNO,
124#endif 124#endif
125 125
126 // syscall list 126 // syscall list
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c
index e47e6c910..808dd4c37 100644
--- a/src/firejail/seccomp.c
+++ b/src/firejail/seccomp.c
@@ -208,7 +208,7 @@ int seccomp_filter_drop(bool native) {
208 // - seccomp 208 // - seccomp
209 if (cfg.seccomp_list_drop == NULL) { 209 if (cfg.seccomp_list_drop == NULL) {
210 // default seccomp if error action is not changed 210 // default seccomp if error action is not changed
211 if (cfg.seccomp_list == NULL && cfg.seccomp_error_action) { 211 if (cfg.seccomp_list == NULL && arg_seccomp_error_action == DEFAULT_SECCOMP_ERROR_ACTION) {
212 if (arg_seccomp_block_secondary) 212 if (arg_seccomp_block_secondary)
213 seccomp_filter_block_secondary(); 213 seccomp_filter_block_secondary();
214 else { 214 else {
@@ -221,11 +221,29 @@ int seccomp_filter_drop(bool native) {
221 } 221 }
222 // default seccomp filter with additional drop list 222 // default seccomp filter with additional drop list
223 else { // cfg.seccomp_list != NULL 223 else { // cfg.seccomp_list != NULL
224 if (arg_seccomp_block_secondary) 224 int rv;
225
226 if (arg_seccomp_block_secondary) {
227 if (arg_seccomp_error_action != DEFAULT_SECCOMP_ERROR_ACTION) {
228 if (arg_debug)
229 printf("Rebuild secondary block seccomp filter\n");
230 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4,
231 PATH_FSECCOMP, "secondary", "block", RUN_SECCOMP_BLOCK_SECONDARY);
232 if (rv)
233 exit(rv);
234 }
225 seccomp_filter_block_secondary(); 235 seccomp_filter_block_secondary();
226 else { 236 } else {
227#if defined(__x86_64__) 237#if defined(__x86_64__)
228#if defined(__LP64__) 238#if defined(__LP64__)
239 if (arg_seccomp_error_action != DEFAULT_SECCOMP_ERROR_ACTION) {
240 if (arg_debug)
241 printf("Rebuild 32 bit seccomp filter\n");
242 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4,
243 PATH_FSECCOMP, "secondary", "32", RUN_SECCOMP_32);
244 if (rv)
245 exit(rv);
246 }
229 seccomp_filter_32(); 247 seccomp_filter_32();
230#endif 248#endif
231#endif 249#endif
@@ -242,16 +260,22 @@ int seccomp_filter_drop(bool native) {
242 list = cfg.seccomp_list32; 260 list = cfg.seccomp_list32;
243 } 261 }
244 262
245 if (list == NULL)
246 list = "";
247 // build the seccomp filter as a regular user 263 // build the seccomp filter as a regular user
248 int rv; 264 if (list)
249 if (arg_allow_debuggers) 265 if (arg_allow_debuggers)
250 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 7, 266 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 7,
251 PATH_FSECCOMP, command, "drop", filter, postexec_filter, list, "allow-debuggers"); 267 PATH_FSECCOMP, command, "drop", filter, postexec_filter, list, "allow-debuggers");
268 else
269 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 6,
270 PATH_FSECCOMP, command, "drop", filter, postexec_filter, list);
252 else 271 else
253 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 6, 272 if (arg_allow_debuggers)
254 PATH_FSECCOMP, command, "drop", filter, postexec_filter, list); 273 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4,
274 PATH_FSECCOMP, command, filter, "allow-debuggers");
275 else
276 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3,
277 PATH_FSECCOMP, command, filter);
278
255 if (rv) 279 if (rv)
256 exit(rv); 280 exit(rv);
257 281
diff --git a/src/firejail/util.c b/src/firejail/util.c
index a3927cc88..911c8bd94 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -565,27 +565,18 @@ char *clean_pathname(const char *path) {
565 if (!rv) 565 if (!rv)
566 errExit("malloc"); 566 errExit("malloc");
567 567
568 if (len > 0) { 568 size_t i = 0;
569 size_t i = 0, j = 0, cnt = 0; 569 size_t j = 0;
570 for (; i < len; i++) { 570 while (path[i]) {
571 if (path[i] == '/') 571 while (path[i] == '/' && path[i+1] == '/')
572 cnt++; 572 i++;
573 else 573 rv[j++] = path[i++];
574 cnt = 0;
575
576 if (cnt < 2) {
577 rv[j] = path[i];
578 j++;
579 }
580 }
581 rv[j] = '\0';
582
583 // remove a trailing slash
584 if (j > 1 && rv[j - 1] == '/')
585 rv[j - 1] = '\0';
586 } 574 }
587 else 575 rv[j] = '\0';
588 *rv = '\0'; 576
577 // remove a trailing slash
578 if (j > 1 && rv[j - 1] == '/')
579 rv[j - 1] = '\0';
589 580
590 return rv; 581 return rv;
591} 582}
@@ -820,20 +811,6 @@ void notify_other(int fd) {
820 fclose(stream); 811 fclose(stream);
821} 812}
822 813
823
824
825
826// Equivalent to the GNU version of basename, which is incompatible with
827// the POSIX basename. A few lines of code saves any portability pain.
828// https://www.gnu.org/software/libc/manual/html_node/Finding-Tokens-in-a-String.html#index-basename
829const char *gnu_basename(const char *path) {
830 const char *last_slash = strrchr(path, '/');
831 if (!last_slash)
832 return path;
833 return last_slash+1;
834}
835
836
837uid_t pid_get_uid(pid_t pid) { 814uid_t pid_get_uid(pid_t pid) {
838 EUID_ASSERT(); 815 EUID_ASSERT();
839 uid_t rv = 0; 816 uid_t rv = 0;
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)
diff --git a/src/fldd/Makefile.in b/src/fldd/Makefile.in
index 53382c2df..37b139d38 100644
--- a/src/fldd/Makefile.in
+++ b/src/fldd/Makefile.in
@@ -5,8 +5,8 @@ include ../common.mk
5%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h ../include/ldd_utils.h 5%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h ../include/ldd_utils.h
6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@ 6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@
7 7
8fldd: $(OBJS) ../lib/ldd_utils.o 8fldd: $(OBJS) ../lib/common.o ../lib/ldd_utils.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/ldd_utils.o $(LIBS) $(EXTRA_LDFLAGS) 9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/ldd_utils.o $(LIBS) $(EXTRA_LDFLAGS)
10 10
11clean:; rm -fr *.o fldd *.gcov *.gcda *.gcno *.plist 11clean:; rm -fr *.o fldd *.gcov *.gcda *.gcno *.plist
12 12
diff --git a/src/fldd/main.c b/src/fldd/main.c
index d68504f6b..55a0dfcce 100644
--- a/src/fldd/main.c
+++ b/src/fldd/main.c
@@ -24,7 +24,6 @@
24#include <fcntl.h> 24#include <fcntl.h>
25#include <sys/mman.h> 25#include <sys/mman.h>
26#include <sys/mount.h> 26#include <sys/mount.h>
27#include <sys/prctl.h>
28#include <sys/stat.h> 27#include <sys/stat.h>
29#include <sys/types.h> 28#include <sys/types.h>
30#include <unistd.h> 29#include <unistd.h>
@@ -303,10 +302,7 @@ printf("\n");
303 return 0; 302 return 0;
304 } 303 }
305 304
306#ifdef WARN_DUMPABLE 305 warn_dumpable();
307 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 1 && getuid())
308 fprintf(stderr, "Error fldd: I am dumpable\n");
309#endif
310 306
311 // check program access 307 // check program access
312 if (access(argv[1], R_OK)) { 308 if (access(argv[1], R_OK)) {
diff --git a/src/fnet/Makefile.in b/src/fnet/Makefile.in
index 37566db72..bd5fe9e7a 100644
--- a/src/fnet/Makefile.in
+++ b/src/fnet/Makefile.in
@@ -5,8 +5,8 @@ include ../common.mk
5%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/libnetlink.h 5%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/libnetlink.h
6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@ 6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@
7 7
8fnet: $(OBJS) ../lib/libnetlink.o 8fnet: $(OBJS) ../lib/common.o ../lib/libnetlink.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/libnetlink.o $(LIBS) $(EXTRA_LDFLAGS) 9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/libnetlink.o $(LIBS) $(EXTRA_LDFLAGS)
10 10
11clean:; rm -fr *.o fnet *.gcov *.gcda *.gcno *.plist 11clean:; rm -fr *.o fnet *.gcov *.gcda *.gcno *.plist
12 12
diff --git a/src/fnet/main.c b/src/fnet/main.c
index f6316a7fe..db090fb95 100644
--- a/src/fnet/main.c
+++ b/src/fnet/main.c
@@ -21,7 +21,6 @@
21#include <sys/types.h> 21#include <sys/types.h>
22#include <sys/stat.h> 22#include <sys/stat.h>
23#include <sys/utsname.h> 23#include <sys/utsname.h>
24#include <sys/prctl.h>
25 24
26int arg_quiet = 0; 25int arg_quiet = 0;
27 26
@@ -69,10 +68,9 @@ printf("\n");
69 usage(); 68 usage();
70 return 0; 69 return 0;
71 } 70 }
72#ifdef WARN_DUMPABLE 71
73 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 1 && getuid()) 72 warn_dumpable();
74 fprintf(stderr, "Error fnet: I am dumpable\n"); 73
75#endif
76 char *quiet = getenv("FIREJAIL_QUIET"); 74 char *quiet = getenv("FIREJAIL_QUIET");
77 if (quiet && strcmp(quiet, "yes") == 0) 75 if (quiet && strcmp(quiet, "yes") == 0)
78 arg_quiet = 1; 76 arg_quiet = 1;
diff --git a/src/fnetfilter/Makefile.in b/src/fnetfilter/Makefile.in
index 055167192..6fe650a17 100644
--- a/src/fnetfilter/Makefile.in
+++ b/src/fnetfilter/Makefile.in
@@ -5,8 +5,8 @@ include ../common.mk
5%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h 5%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h
6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@ 6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@
7 7
8fnetfilter: $(OBJS) 8fnetfilter: $(OBJS) ../lib/common.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) 9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS)
10 10
11clean:; rm -fr *.o fnetfilter *.gcov *.gcda *.gcno *.plist 11clean:; rm -fr *.o fnetfilter *.gcov *.gcda *.gcno *.plist
12 12
diff --git a/src/fnetfilter/main.c b/src/fnetfilter/main.c
index 1ca35ab56..381d0d36e 100644
--- a/src/fnetfilter/main.c
+++ b/src/fnetfilter/main.c
@@ -18,7 +18,6 @@
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/ 19*/
20#include "../include/common.h" 20#include "../include/common.h"
21#include <sys/prctl.h>
22 21
23#define MAXBUF 4098 22#define MAXBUF 4098
24#define MAXARGS 16 23#define MAXARGS 16
@@ -181,10 +180,9 @@ printf("\n");
181 usage(); 180 usage();
182 return 1; 181 return 1;
183 } 182 }
184#ifdef WARN_DUMPABLE 183
185 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 1 && getuid()) 184 warn_dumpable();
186 fprintf(stderr, "Error fnetfilter: I am dumpable\n"); 185
187#endif
188 char *destfile = (argc == 3)? argv[2]: argv[1]; 186 char *destfile = (argc == 3)? argv[2]: argv[1];
189 char *command = (argc == 3)? argv[1]: NULL; 187 char *command = (argc == 3)? argv[1]: NULL;
190//printf("command %s\n", command); 188//printf("command %s\n", command);
diff --git a/src/fsec-optimize/Makefile.in b/src/fsec-optimize/Makefile.in
index 0387f7ec7..cc5ac7e35 100644
--- a/src/fsec-optimize/Makefile.in
+++ b/src/fsec-optimize/Makefile.in
@@ -5,8 +5,8 @@ include ../common.mk
5%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/seccomp.h ../include/syscall.h 5%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/seccomp.h ../include/syscall.h
6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@ 6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@
7 7
8fsec-optimize: $(OBJS) ../lib/libnetlink.o 8fsec-optimize: $(OBJS) ../lib/common.o ../lib/libnetlink.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) 9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/errno.o $(LIBS) $(EXTRA_LDFLAGS)
10 10
11clean:; rm -fr *.o fsec-optimize *.gcov *.gcda *.gcno *.plist 11clean:; rm -fr *.o fsec-optimize *.gcov *.gcda *.gcno *.plist
12 12
diff --git a/src/fsec-optimize/fsec_optimize.h b/src/fsec-optimize/fsec_optimize.h
index 034fde2ac..211111641 100644
--- a/src/fsec-optimize/fsec_optimize.h
+++ b/src/fsec-optimize/fsec_optimize.h
@@ -22,7 +22,6 @@
22#include "../include/common.h" 22#include "../include/common.h"
23#include "../include/seccomp.h" 23#include "../include/seccomp.h"
24#include <sys/mman.h> 24#include <sys/mman.h>
25#include <sys/prctl.h>
26 25
27// optimize.c 26// optimize.c
28struct sock_filter *duplicate(struct sock_filter *filter, int entries); 27struct sock_filter *duplicate(struct sock_filter *filter, int entries);
diff --git a/src/fsec-optimize/main.c b/src/fsec-optimize/main.c
index fb13eeca8..c64587068 100644
--- a/src/fsec-optimize/main.c
+++ b/src/fsec-optimize/main.c
@@ -18,6 +18,9 @@
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/ 19*/
20#include "fsec_optimize.h" 20#include "fsec_optimize.h"
21#include "../include/syscall.h"
22
23int arg_seccomp_error_action = SECCOMP_RET_ERRNO | EPERM; // error action: errno, log or kill
21 24
22static void usage(void) { 25static void usage(void) {
23 printf("Usage:\n"); 26 printf("Usage:\n");
@@ -44,11 +47,21 @@ printf("\n");
44 return 0; 47 return 0;
45 } 48 }
46 49
47#ifdef WARN_DUMPABLE 50 warn_dumpable();
48 // check FIREJAIL_PLUGIN in order to not print a warning during make 51
49 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 1 && getuid() && getenv("FIREJAIL_PLUGIN")) 52 char *error_action = getenv("FIREJAIL_SECCOMP_ERROR_ACTION");
50 fprintf(stderr, "Error fsec-optimize: I am dumpable\n"); 53 if (error_action) {
51#endif 54 if (strcmp(error_action, "kill") == 0)
55 arg_seccomp_error_action = SECCOMP_RET_KILL;
56 else if (strcmp(error_action, "log") == 0)
57 arg_seccomp_error_action = SECCOMP_RET_LOG;
58 else {
59 arg_seccomp_error_action = errno_find_name(error_action);
60 if (arg_seccomp_error_action == -1)
61 errExit("seccomp-error-action: unknown errno");
62 arg_seccomp_error_action |= SECCOMP_RET_ERRNO;
63 }
64 }
52 65
53 char *fname = argv[1]; 66 char *fname = argv[1];
54 67
diff --git a/src/fsec-optimize/optimizer.c b/src/fsec-optimize/optimizer.c
index 776beaa75..eb777f13b 100644
--- a/src/fsec-optimize/optimizer.c
+++ b/src/fsec-optimize/optimizer.c
@@ -33,7 +33,7 @@
33static inline int is_blacklist(struct sock_filter *bpf) { 33static inline int is_blacklist(struct sock_filter *bpf) {
34 if (bpf->code == BPF_JMP + BPF_JEQ + BPF_K && 34 if (bpf->code == BPF_JMP + BPF_JEQ + BPF_K &&
35 (bpf + 1)->code == BPF_RET + BPF_K && 35 (bpf + 1)->code == BPF_RET + BPF_K &&
36 (bpf + 1)->k == SECCOMP_RET_KILL ) 36 (bpf + 1)->k == (__u32)arg_seccomp_error_action)
37 return 1; 37 return 1;
38 return 0; 38 return 0;
39} 39}
@@ -89,9 +89,9 @@ static int optimize_blacklists(struct sock_filter *filter, int entries) {
89 } 89 }
90 } 90 }
91 91
92 // step 3: add the new ret KILL, and recalculate entries 92 // step 3: add the new ret KILL/LOG/ERRNO, and recalculate entries
93 filter_step2[j].code = BPF_RET + BPF_K; 93 filter_step2[j].code = BPF_RET + BPF_K;
94 filter_step2[j].k = SECCOMP_RET_KILL; 94 filter_step2[j].k = arg_seccomp_error_action;
95 entries = j + 1; 95 entries = j + 1;
96 96
97 // step 4: recalculate jumps 97 // step 4: recalculate jumps
diff --git a/src/fsec-print/Makefile.in b/src/fsec-print/Makefile.in
index a30ff4ba3..bf39a8c77 100644
--- a/src/fsec-print/Makefile.in
+++ b/src/fsec-print/Makefile.in
@@ -5,8 +5,8 @@ include ../common.mk
5%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/seccomp.h ../include/syscall.h 5%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/seccomp.h ../include/syscall.h
6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@ 6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@
7 7
8fsec-print: $(OBJS) ../lib/libnetlink.o ../lib/errno.o ../lib/syscall.o 8fsec-print: $(OBJS) ../lib/common.o ../lib/libnetlink.o ../lib/errno.o ../lib/syscall.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/errno.o ../lib/syscall.o $(LIBS) $(EXTRA_LDFLAGS) 9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/errno.o ../lib/syscall.o $(LIBS) $(EXTRA_LDFLAGS)
10 10
11clean:; rm -fr *.o fsec-print *.gcov *.gcda *.gcno *.plist 11clean:; rm -fr *.o fsec-print *.gcov *.gcda *.gcno *.plist
12 12
diff --git a/src/fsec-print/fsec_print.h b/src/fsec-print/fsec_print.h
index 9d17e3f18..337199288 100644
--- a/src/fsec-print/fsec_print.h
+++ b/src/fsec-print/fsec_print.h
@@ -23,7 +23,6 @@
23#include "../include/seccomp.h" 23#include "../include/seccomp.h"
24#include "../include/syscall.h" 24#include "../include/syscall.h"
25#include <sys/mman.h> 25#include <sys/mman.h>
26#include <sys/prctl.h>
27 26
28// print.c 27// print.c
29void print(struct sock_filter *filter, int entries); 28void print(struct sock_filter *filter, int entries);
diff --git a/src/fsec-print/main.c b/src/fsec-print/main.c
index d1f056e47..ed030db21 100644
--- a/src/fsec-print/main.c
+++ b/src/fsec-print/main.c
@@ -61,10 +61,7 @@ printf("\n");
61 return 0; 61 return 0;
62 } 62 }
63 63
64#ifdef WARN_DUMPABLE 64 warn_dumpable();
65 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 1 && getuid())
66 fprintf(stderr, "Error fsec-print: I am dumpable\n");
67#endif
68 65
69 char *fname = argv[1]; 66 char *fname = argv[1];
70 67
diff --git a/src/fseccomp/Makefile.in b/src/fseccomp/Makefile.in
index 8623db6f8..b776a73ce 100644
--- a/src/fseccomp/Makefile.in
+++ b/src/fseccomp/Makefile.in
@@ -5,8 +5,8 @@ include ../common.mk
5%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h 5%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h
6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@ 6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@
7 7
8fseccomp: $(OBJS) ../lib/errno.o ../lib/syscall.o 8fseccomp: $(OBJS) ../lib/common.o ../lib/errno.o ../lib/syscall.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/errno.o ../lib/syscall.o $(LIBS) $(EXTRA_LDFLAGS) 9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/errno.o ../lib/syscall.o $(LIBS) $(EXTRA_LDFLAGS)
10 10
11clean:; rm -fr *.o fseccomp *.gcov *.gcda *.gcno *.plist 11clean:; rm -fr *.o fseccomp *.gcov *.gcda *.gcno *.plist
12 12
diff --git a/src/fseccomp/fseccomp.h b/src/fseccomp/fseccomp.h
index e40999938..e8dd083b6 100644
--- a/src/fseccomp/fseccomp.h
+++ b/src/fseccomp/fseccomp.h
@@ -23,7 +23,6 @@
23#include <stdlib.h> 23#include <stdlib.h>
24#include <string.h> 24#include <string.h>
25#include <assert.h> 25#include <assert.h>
26#include <sys/prctl.h>
27#include "../include/common.h" 26#include "../include/common.h"
28#include "../include/syscall.h" 27#include "../include/syscall.h"
29 28
diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c
index f505ca0f3..f47efb5e8 100644
--- a/src/fseccomp/main.c
+++ b/src/fseccomp/main.c
@@ -20,7 +20,7 @@
20#include "fseccomp.h" 20#include "fseccomp.h"
21#include "../include/seccomp.h" 21#include "../include/seccomp.h"
22int arg_quiet = 0; 22int arg_quiet = 0;
23int arg_seccomp_error_action = EPERM; // error action: errno, log or kill 23int arg_seccomp_error_action = SECCOMP_RET_ERRNO | EPERM; // error action: errno, log or kill
24 24
25static void usage(void) { 25static void usage(void) {
26 printf("Usage:\n"); 26 printf("Usage:\n");
@@ -69,11 +69,7 @@ printf("\n");
69 return 0; 69 return 0;
70 } 70 }
71 71
72#ifdef WARN_DUMPABLE 72 warn_dumpable();
73 // check FIREJAIL_PLUGIN in order to not print a warning during make
74 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 1 && getuid() && getenv("FIREJAIL_PLUGIN"))
75 fprintf(stderr, "Error fseccomp: I am dumpable\n");
76#endif
77 73
78 char *quiet = getenv("FIREJAIL_QUIET"); 74 char *quiet = getenv("FIREJAIL_QUIET");
79 if (quiet && strcmp(quiet, "yes") == 0) 75 if (quiet && strcmp(quiet, "yes") == 0)
diff --git a/src/fseccomp/seccomp_secondary.c b/src/fseccomp/seccomp_secondary.c
index f024859d3..b8e8d0a89 100644
--- a/src/fseccomp/seccomp_secondary.c
+++ b/src/fseccomp/seccomp_secondary.c
@@ -126,7 +126,7 @@ void seccomp_secondary_block(const char *fname) {
126 EXAMINE_SYSCALL, 126 EXAMINE_SYSCALL,
127#if defined(__x86_64__) 127#if defined(__x86_64__)
128 // block x32 128 // block x32
129 HANDLE_X32_KILL, 129 HANDLE_X32,
130#endif 130#endif
131 // block personality(2) where domain != PER_LINUX or 0xffffffff (query current personality) 131 // block personality(2) where domain != PER_LINUX or 0xffffffff (query current personality)
132 // 0: if personality(2), continue to 1, else goto 7 (allow) 132 // 0: if personality(2), continue to 1, else goto 7 (allow)
diff --git a/src/include/common.h b/src/include/common.h
index 5df51c5a9..5497929c7 100644
--- a/src/include/common.h
+++ b/src/include/common.h
@@ -38,11 +38,6 @@
38 38
39#define errExit(msg) do { char msgout[500]; snprintf(msgout, 500, "Error %s: %s:%d %s", msg, __FILE__, __LINE__, __FUNCTION__); perror(msgout); exit(1);} while (0) 39#define errExit(msg) do { char msgout[500]; snprintf(msgout, 500, "Error %s: %s:%d %s", msg, __FILE__, __LINE__, __FUNCTION__); perror(msgout); exit(1);} while (0)
40 40
41// check if processes run with dumpable flag set
42// currently we get "Error fseccomp: I am dumpable" every time we run a firejail build on Debian 8,
43// regardless what Debian version we run the build on
44//#define WARN_DUMPABLE
45
46// macro to print ip addresses in a printf statement 41// macro to print ip addresses in a printf statement
47#define PRINT_IP(A) \ 42#define PRINT_IP(A) \
48((int) (((A) >> 24) & 0xFF)), ((int) (((A) >> 16) & 0xFF)), ((int) (((A) >> 8) & 0xFF)), ((int) ( (A) & 0xFF)) 43((int) (((A) >> 24) & 0xFF)), ((int) (((A) >> 16) & 0xFF)), ((int) (((A) >> 8) & 0xFF)), ((int) ( (A) & 0xFF))
@@ -126,4 +121,6 @@ char *pid_proc_comm(const pid_t pid);
126char *pid_proc_cmdline(const pid_t pid); 121char *pid_proc_cmdline(const pid_t pid);
127int pid_proc_cmdline_x11_xpra_xephyr(const pid_t pid); 122int pid_proc_cmdline_x11_xpra_xephyr(const pid_t pid);
128int pid_hidepid(void); 123int pid_hidepid(void);
124void warn_dumpable(void);
125const char *gnu_basename(const char *path);
129#endif 126#endif
diff --git a/src/include/seccomp.h b/src/include/seccomp.h
index 90db16d39..b3b75c2d1 100644
--- a/src/include/seccomp.h
+++ b/src/include/seccomp.h
@@ -201,7 +201,7 @@
201#define VALIDATE_ARCHITECTURE_KILL \ 201#define VALIDATE_ARCHITECTURE_KILL \
202 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \ 202 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \
203 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \ 203 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \
204 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) 204 KILL_OR_RETURN_ERRNO
205 205
206#define VALIDATE_ARCHITECTURE_64 \ 206#define VALIDATE_ARCHITECTURE_64 \
207 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \ 207 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, arch))), \
@@ -222,11 +222,7 @@
222#define HANDLE_X32 \ 222#define HANDLE_X32 \
223 BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, X32_SYSCALL_BIT, 1, 0), \ 223 BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, X32_SYSCALL_BIT, 1, 0), \
224 BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, 0, 1, 0), \ 224 BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, 0, 1, 0), \
225 RETURN_ERRNO(EPERM) 225 KILL_OR_RETURN_ERRNO
226#define HANDLE_X32_KILL \
227 BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, X32_SYSCALL_BIT, 1, 0), \
228 BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, 0, 1, 0), \
229 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
230#endif 226#endif
231 227
232#define EXAMINE_SYSCALL BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 228#define EXAMINE_SYSCALL BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
@@ -258,6 +254,8 @@
258 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO | nr) 254 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO | nr)
259 255
260extern int arg_seccomp_error_action; // error action: errno, log or kill 256extern int arg_seccomp_error_action; // error action: errno, log or kill
257#define DEFAULT_SECCOMP_ERROR_ACTION EPERM
258
261#define KILL_OR_RETURN_ERRNO \ 259#define KILL_OR_RETURN_ERRNO \
262 BPF_STMT(BPF_RET+BPF_K, arg_seccomp_error_action) 260 BPF_STMT(BPF_RET+BPF_K, arg_seccomp_error_action)
263 261
diff --git a/src/lib/common.c b/src/lib/common.c
index 823442835..ace5cb87e 100644
--- a/src/lib/common.c
+++ b/src/lib/common.c
@@ -267,7 +267,6 @@ int pid_proc_cmdline_x11_xpra_xephyr(const pid_t pid) {
267} 267}
268 268
269// return 1 if /proc is mounted hidepid, or if /proc/mouns access is denied 269// return 1 if /proc is mounted hidepid, or if /proc/mouns access is denied
270#define BUFLEN 4096
271int pid_hidepid(void) { 270int pid_hidepid(void) {
272 FILE *fp = fopen("/proc/mounts", "r"); 271 FILE *fp = fopen("/proc/mounts", "r");
273 if (!fp) 272 if (!fp)
@@ -288,6 +287,39 @@ int pid_hidepid(void) {
288 return 0; 287 return 0;
289} 288}
290 289
290// print error if unprivileged users can trace the process
291void warn_dumpable(void) {
292 if (getuid() != 0 && prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 1 && getenv("FIREJAIL_PLUGIN")) {
293 fprintf(stderr, "Error: dumpable process\n");
294
295 // best effort to provide detailed debug information
296 // cannot use process name, it is just a file descriptor number
297 char path[BUFLEN];
298 ssize_t len = readlink("/proc/self/exe", path, BUFLEN - 1);
299 if (len < 0)
300 return;
301 path[len] = '\0';
302 // path can refer to a sandbox mount namespace, use basename only
303 const char *base = gnu_basename(path);
304
305 struct stat s;
306 if (stat("/proc/self/exe", &s) == 0 && s.st_uid != 0)
307 fprintf(stderr, "Change owner of %s executable to root\n", base);
308 else if (access("/proc/self/exe", R_OK) == 0)
309 fprintf(stderr, "Remove read permission on %s executable\n", base);
310 }
311}
312
313// Equivalent to the GNU version of basename, which is incompatible with
314// the POSIX basename. A few lines of code saves any portability pain.
315// https://www.gnu.org/software/libc/manual/html_node/Finding-Tokens-in-a-String.html#index-basename
316const char *gnu_basename(const char *path) {
317 const char *last_slash = strrchr(path, '/');
318 if (!last_slash)
319 return path;
320 return last_slash+1;
321}
322
291//************************** 323//**************************
292// time trace based on getticks function 324// time trace based on getticks function
293//************************** 325//**************************
diff --git a/src/lib/syscall.c b/src/lib/syscall.c
index 4903971ad..6823d0ae6 100644
--- a/src/lib/syscall.c
+++ b/src/lib/syscall.c
@@ -336,6 +336,7 @@ static const SyscallGroupList sysgroups[] = {
336#endif 336#endif
337 }, 337 },
338 { .name = "@default-keep", .list = 338 { .name = "@default-keep", .list =
339 "execveat," // commonly used by fexecve
339 "execve," 340 "execve,"
340 "prctl" 341 "prctl"
341 }, 342 },
diff --git a/src/man/firecfg.txt b/src/man/firecfg.txt
index f3123356a..2c02aee47 100644
--- a/src/man/firecfg.txt
+++ b/src/man/firecfg.txt
@@ -61,7 +61,7 @@ $ sudo firecfg --add-users dustin lucas mike eleven
61 61
62.TP 62.TP
63\fB\-\-bindir=directory 63\fB\-\-bindir=directory
64Create and search symbolic links in directory instead of the default location /user/local/bin. 64Create and search symbolic links in directory instead of the default location /usr/local/bin.
65Directory should precede /usr/bin and /bin in the PATH environment variable. 65Directory should precede /usr/bin and /bin in the PATH environment variable.
66 66
67.TP 67.TP
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt
index 9524254c1..030a3c95c 100644
--- a/src/man/firejail-profile.txt
+++ b/src/man/firejail-profile.txt
@@ -862,6 +862,11 @@ the parent interface specified by --net is not configured. An IP address and
862a default gateway address also have to be added. 862a default gateway address also have to be added.
863 863
864.TP 864.TP
865\fBnetns namespace
866Run the program in a named, persistent network namespace. These can
867be created and configured using "ip netns".
868
869.TP
865\fBveth-name name 870\fBveth-name name
866Use this name for the interface connected to the bridge for --net=bridge_interface commands, 871Use this name for the interface connected to the bridge for --net=bridge_interface commands,
867instead of the default one. 872instead of the default one.
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index 562b3eda3..8958dfaee 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -76,10 +76,10 @@ If an appropriate profile is not found, Firejail will use a default profile.
76The default profile is quite restrictive. In case the application doesn't work, use --noprofile option 76The default profile is quite restrictive. In case the application doesn't work, use --noprofile option
77to disable it. For more information, please see \fBSECURITY PROFILES\fR section below. 77to disable it. For more information, please see \fBSECURITY PROFILES\fR section below.
78.PP 78.PP
79If a program argument is not specified, Firejail starts /bin/bash shell. 79If a program argument is not specified, Firejail starts the user's preferred shell.
80Examples: 80Examples:
81.PP 81.PP
82$ firejail [OPTIONS] # starting a /bin/bash shell 82$ firejail [OPTIONS] # starting the program specified in $SHELL, usually /bin/bash
83.PP 83.PP
84$ firejail [OPTIONS] firefox # starting Mozilla Firefox 84$ firejail [OPTIONS] firefox # starting Mozilla Firefox
85.PP 85.PP
@@ -1317,7 +1317,7 @@ $ firejail --netfilter=/etc/firejail/webserver.net --net=eth0 \\
1317.br 1317.br
1318 1318
1319.br 1319.br
1320.B nolocal.net 1320.B nolocal.net/nolocal6.net
1321is a desktop client firewall that disable access to local network. Example: 1321is a desktop client firewall that disable access to local network. Example:
1322.br 1322.br
1323 1323
@@ -2273,7 +2273,7 @@ rm: cannot remove `testfile': Operation not permitted
2273.TP 2273.TP
2274\fB\-\-seccomp.keep=syscall,@group,!syscall2 2274\fB\-\-seccomp.keep=syscall,@group,!syscall2
2275Enable seccomp filter, blacklist all syscall not listed and "syscall2". 2275Enable seccomp filter, blacklist all syscall not listed and "syscall2".
2276The system calls needed by Firejail (group @default-keep: prctl, execve) 2276The system calls needed by Firejail (group @default-keep: prctl, execve, execveat)
2277are handled with the preload library. On a 64 bit architecture, an 2277are handled with the preload library. On a 64 bit architecture, an
2278additional filter for 32 bit system calls can be installed with 2278additional filter for 32 bit system calls can be installed with
2279\-\-seccomp.32.keep. 2279\-\-seccomp.32.keep.
@@ -2476,7 +2476,7 @@ $ firejail \-\-shell=none script.sh
2476\fB\-\-shell=program 2476\fB\-\-shell=program
2477Set default user shell. Use this shell to run the application using \-c shell option. 2477Set default user shell. Use this shell to run the application using \-c shell option.
2478For example "firejail \-\-shell=/bin/dash firefox" will start Mozilla Firefox as "/bin/dash \-c firefox". 2478For example "firejail \-\-shell=/bin/dash firefox" will start Mozilla Firefox as "/bin/dash \-c firefox".
2479By default Bash shell (/bin/bash) is used. 2479By default the user's preferred shell is used.
2480.br 2480.br
2481 2481
2482.br 2482.br
@@ -3023,7 +3023,7 @@ We provide a tool that automates all this integration, please see \&\flfirecfg\f
3023.SH EXAMPLES 3023.SH EXAMPLES
3024.TP 3024.TP
3025\f\firejail 3025\f\firejail
3026Sandbox a regular /bin/bash session. 3026Sandbox a regular shell session.
3027.TP 3027.TP
3028\f\firejail firefox 3028\f\firejail firefox
3029Start Mozilla Firefox. 3029Start Mozilla Firefox.
@@ -3043,7 +3043,7 @@ Start Firefox in a new network namespace. An IP address is
3043assigned automatically. 3043assigned automatically.
3044.TP 3044.TP
3045\f\firejail \-\-net=br0 \-\-ip=10.10.20.5 \-\-net=br1 \-\-net=br2 3045\f\firejail \-\-net=br0 \-\-ip=10.10.20.5 \-\-net=br1 \-\-net=br2
3046Start a /bin/bash session in a new network namespace and connect it 3046Start a shell session in a new network namespace and connect it
3047to br0, br1, and br2 host bridge devices. IP addresses are assigned 3047to br0, br1, and br2 host bridge devices. IP addresses are assigned
3048automatically for the interfaces connected to br1 and b2 3048automatically for the interfaces connected to br1 and b2
3049#endif 3049#endif
diff --git a/src/profstats/main.c b/src/profstats/main.c
index 4c1221464..68f62831b 100644
--- a/src/profstats/main.c
+++ b/src/profstats/main.c
@@ -30,6 +30,8 @@ static int cnt_seccomp = 0;
30static int cnt_caps = 0; 30static int cnt_caps = 0;
31static int cnt_dbus_system_none = 0; 31static int cnt_dbus_system_none = 0;
32static int cnt_dbus_user_none = 0; 32static int cnt_dbus_user_none = 0;
33static int cnt_dbus_system_filter = 0;
34static int cnt_dbus_user_filter = 0;
33static int cnt_dotlocal = 0; 35static int cnt_dotlocal = 0;
34static int cnt_globalsdotlocal = 0; 36static int cnt_globalsdotlocal = 0;
35static int cnt_netnone = 0; 37static int cnt_netnone = 0;
@@ -107,6 +109,7 @@ void process_file(const char *fname) {
107 return; 109 return;
108 } 110 }
109 111
112 int have_include_local = 0;
110 char buf[MAXBUF]; 113 char buf[MAXBUF];
111 while (fgets(buf, MAXBUF, fp)) { 114 while (fgets(buf, MAXBUF, fp)) {
112 char *ptr = strchr(buf, '\n'); 115 char *ptr = strchr(buf, '\n');
@@ -152,11 +155,16 @@ void process_file(const char *fname) {
152 cnt_privateetc++; 155 cnt_privateetc++;
153 else if (strncmp(ptr, "dbus-system none", 16) == 0) 156 else if (strncmp(ptr, "dbus-system none", 16) == 0)
154 cnt_dbus_system_none++; 157 cnt_dbus_system_none++;
158 else if (strncmp(ptr, "dbus-system", 11) == 0)
159 cnt_dbus_system_filter++;
155 else if (strncmp(ptr, "dbus-user none", 14) == 0) 160 else if (strncmp(ptr, "dbus-user none", 14) == 0)
156 cnt_dbus_user_none++; 161 cnt_dbus_user_none++;
162 else if (strncmp(ptr, "dbus-user", 9) == 0)
163 cnt_dbus_user_filter++;
157 else if (strncmp(ptr, "include ", 8) == 0) { 164 else if (strncmp(ptr, "include ", 8) == 0) {
158 // not processing .local files 165 // not processing .local files
159 if (strstr(ptr, ".local")) { 166 if (strstr(ptr, ".local")) {
167 have_include_local = 1;
160//printf("dotlocal %d, level %d - #%s#, redirect #%s#\n", cnt_dotlocal, level, fname, buf + 8); 168//printf("dotlocal %d, level %d - #%s#, redirect #%s#\n", cnt_dotlocal, level, fname, buf + 8);
161 if (strstr(ptr, "globals.local")) 169 if (strstr(ptr, "globals.local"))
162 cnt_globalsdotlocal++; 170 cnt_globalsdotlocal++;
@@ -174,6 +182,8 @@ void process_file(const char *fname) {
174 } 182 }
175 183
176 fclose(fp); 184 fclose(fp);
185 if (!have_include_local)
186 printf("No include .local found in %s\n", fname);
177 level--; 187 level--;
178} 188}
179 189
@@ -257,7 +267,9 @@ int main(int argc, char **argv) {
257 int whitelistrunuser = cnt_whitelistrunuser; 267 int whitelistrunuser = cnt_whitelistrunuser;
258 int whitelistusrshare = cnt_whitelistusrshare; 268 int whitelistusrshare = cnt_whitelistusrshare;
259 int dbussystemnone = cnt_dbus_system_none; 269 int dbussystemnone = cnt_dbus_system_none;
270 int dbussystemfilter = cnt_dbus_system_filter;
260 int dbususernone = cnt_dbus_user_none; 271 int dbususernone = cnt_dbus_user_none;
272 int dbususerfilter = cnt_dbus_user_filter;
261 int ssh = cnt_ssh; 273 int ssh = cnt_ssh;
262 int mdwx = cnt_mdwx; 274 int mdwx = cnt_mdwx;
263 275
@@ -278,6 +290,16 @@ int main(int argc, char **argv) {
278 cnt_globalsdotlocal = globalsdotlocal + 1; 290 cnt_globalsdotlocal = globalsdotlocal + 1;
279 if (cnt_whitelistrunuser > (whitelistrunuser + 1)) 291 if (cnt_whitelistrunuser > (whitelistrunuser + 1))
280 cnt_whitelistrunuser = whitelistrunuser + 1; 292 cnt_whitelistrunuser = whitelistrunuser + 1;
293 if (cnt_seccomp > (seccomp + 1))
294 cnt_seccomp = seccomp + 1;
295 if (cnt_dbus_user_none > (dbususernone + 1))
296 cnt_dbus_user_none = dbususernone + 1;
297 if (cnt_dbus_user_filter > (dbususerfilter + 1))
298 cnt_dbus_user_filter = dbususerfilter + 1;
299 if (cnt_dbus_system_none > (dbussystemnone + 1))
300 cnt_dbus_system_none = dbussystemnone + 1;
301 if (cnt_dbus_system_filter > (dbussystemfilter + 1))
302 cnt_dbus_system_filter = dbussystemfilter + 1;
281 303
282 if (arg_dbus_system_none && dbussystemnone == cnt_dbus_system_none) 304 if (arg_dbus_system_none && dbussystemnone == cnt_dbus_system_none)
283 printf("No dbus-system none found in %s\n", argv[i]); 305 printf("No dbus-system none found in %s\n", argv[i]);
@@ -337,7 +359,9 @@ int main(int argc, char **argv) {
337 printf(" whitelist usr/share\t\t%d (include whitelist-usr-share-common.inc\n", cnt_whitelistusrshare); 359 printf(" whitelist usr/share\t\t%d (include whitelist-usr-share-common.inc\n", cnt_whitelistusrshare);
338 printf(" net none\t\t\t%d\n", cnt_netnone); 360 printf(" net none\t\t\t%d\n", cnt_netnone);
339 printf(" dbus-user none \t\t%d\n", cnt_dbus_user_none); 361 printf(" dbus-user none \t\t%d\n", cnt_dbus_user_none);
362 printf(" dbus-user filter \t\t%d\n", cnt_dbus_user_filter);
340 printf(" dbus-system none \t\t%d\n", cnt_dbus_system_none); 363 printf(" dbus-system none \t\t%d\n", cnt_dbus_system_none);
364 printf(" dbus-system filter \t\t%d\n", cnt_dbus_system_filter);
341 printf("\n"); 365 printf("\n");
342 return 0; 366 return 0;
343} 367}