aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bash_completion/firejail.bash_completion.in8
-rw-r--r--src/fcopy/main.c3
-rw-r--r--src/firejail/checkcfg.c2
-rw-r--r--src/firejail/firejail.h3
-rw-r--r--src/firejail/fs.c50
-rw-r--r--src/firejail/fs_dev.c2
-rw-r--r--src/firejail/fs_home.c11
-rw-r--r--src/firejail/fs_whitelist.c59
-rw-r--r--src/firejail/mountinfo.c71
-rw-r--r--src/firejail/profile.c15
-rw-r--r--src/firejail/sandbox.c2
-rw-r--r--src/firejail/selinux.c21
-rw-r--r--src/firejail/util.c14
-rw-r--r--src/man/firejail-profile.txt24
-rw-r--r--src/man/firejail.txt18
-rw-r--r--src/man/firemon.txt2
16 files changed, 167 insertions, 138 deletions
diff --git a/src/bash_completion/firejail.bash_completion.in b/src/bash_completion/firejail.bash_completion.in
index f68edf380..ff411c807 100644
--- a/src/bash_completion/firejail.bash_completion.in
+++ b/src/bash_completion/firejail.bash_completion.in
@@ -5,7 +5,7 @@
5# http://bash-completion.alioth.debian.org 5# http://bash-completion.alioth.debian.org
6#******************************************************************* 6#*******************************************************************
7 7
8__interfaces(){ 8__interfaces() {
9 cut -f 1 -d ':' /proc/net/dev | tail -n +3 | grep -v lo | xargs 9 cut -f 1 -d ':' /proc/net/dev | tail -n +3 | grep -v lo | xargs
10} 10}
11 11
@@ -90,11 +90,11 @@ _firejail()
90 _filedir 90 _filedir
91 return 0 91 return 0
92 ;; 92 ;;
93 --net) 93 --net)
94 comps=$(__interfaces) 94 comps=$(__interfaces)
95 COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) 95 COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
96 return 0 96 return 0
97 ;; 97 ;;
98 esac 98 esac
99 99
100 $split && return 0 100 $split && return 0
diff --git a/src/fcopy/main.c b/src/fcopy/main.c
index 31810de9a..f279af89f 100644
--- a/src/fcopy/main.c
+++ b/src/fcopy/main.c
@@ -88,7 +88,8 @@ static void selinux_relabel_path(const char *path, const char *inside_path) {
88 if (arg_debug) 88 if (arg_debug)
89 printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon); 89 printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon);
90 90
91 setfilecon_raw(procfs_path, fcon); 91 if (setfilecon_raw(procfs_path, fcon) != 0 && arg_debug)
92 printf("Cannot relabel %s: %s\n", path, strerror(errno));
92 } 93 }
93 freecon(fcon); 94 freecon(fcon);
94 close: 95 close:
diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c
index 06e6f0ccb..e5d837bbb 100644
--- a/src/firejail/checkcfg.c
+++ b/src/firejail/checkcfg.c
@@ -58,6 +58,7 @@ int checkcfg(int val) {
58 cfg_val[CFG_XPRA_ATTACH] = 0; 58 cfg_val[CFG_XPRA_ATTACH] = 0;
59 cfg_val[CFG_SECCOMP_ERROR_ACTION] = -1; 59 cfg_val[CFG_SECCOMP_ERROR_ACTION] = -1;
60 cfg_val[CFG_BROWSER_ALLOW_DRM] = 0; 60 cfg_val[CFG_BROWSER_ALLOW_DRM] = 0;
61 cfg_val[CFG_ALLOW_TRAY] = 0;
61 62
62 // open configuration file 63 // open configuration file
63 const char *fname = SYSCONFDIR "/firejail.config"; 64 const char *fname = SYSCONFDIR "/firejail.config";
@@ -122,6 +123,7 @@ int checkcfg(int val) {
122 PARSE_YESNO(CFG_XPRA_ATTACH, "xpra-attach") 123 PARSE_YESNO(CFG_XPRA_ATTACH, "xpra-attach")
123 PARSE_YESNO(CFG_BROWSER_DISABLE_U2F, "browser-disable-u2f") 124 PARSE_YESNO(CFG_BROWSER_DISABLE_U2F, "browser-disable-u2f")
124 PARSE_YESNO(CFG_BROWSER_ALLOW_DRM, "browser-allow-drm") 125 PARSE_YESNO(CFG_BROWSER_ALLOW_DRM, "browser-allow-drm")
126 PARSE_YESNO(CFG_ALLOW_TRAY, "allow-tray")
125#undef PARSE_YESNO 127#undef PARSE_YESNO
126 128
127 // netfilter 129 // netfilter
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index bcc7e6ed1..730c37aed 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -563,7 +563,7 @@ typedef struct {
563 563
564// mountinfo.c 564// mountinfo.c
565MountData *get_last_mount(void); 565MountData *get_last_mount(void);
566int get_mount_id(const char *path); 566int get_mount_id(int fd);
567char **build_mount_array(const int mount_id, const char *path); 567char **build_mount_array(const int mount_id, const char *path);
568 568
569// fs_var.c 569// fs_var.c
@@ -802,6 +802,7 @@ enum {
802 CFG_NAME_CHANGE, 802 CFG_NAME_CHANGE,
803 CFG_SECCOMP_ERROR_ACTION, 803 CFG_SECCOMP_ERROR_ACTION,
804 // CFG_FILE_COPY_LIMIT - file copy limit handled using setenv/getenv 804 // CFG_FILE_COPY_LIMIT - file copy limit handled using setenv/getenv
805 CFG_ALLOW_TRAY,
805 CFG_MAX // this should always be the last entry 806 CFG_MAX // this should always be the last entry
806}; 807};
807extern char *xephyr_screen; 808extern char *xephyr_screen;
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index dd4c2139d..3144156a3 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -200,8 +200,6 @@ static void disable_file(OPERATION op, const char *filename) {
200 } 200 }
201 201
202 fs_tmpfs(fname, uid); 202 fs_tmpfs(fname, uid);
203 EUID_USER(); // fs_tmpfs returns with EUID 0
204
205 selinux_relabel_path(fname, fname); 203 selinux_relabel_path(fname, fname);
206 } 204 }
207 else 205 else
@@ -282,6 +280,8 @@ static void globbing(OPERATION op, const char *pattern, const char *noblacklist[
282 280
283// blacklist files or directories by mounting empty files on top of them 281// blacklist files or directories by mounting empty files on top of them
284void fs_blacklist(void) { 282void fs_blacklist(void) {
283 EUID_ASSERT();
284
285 ProfileEntry *entry = cfg.profile; 285 ProfileEntry *entry = cfg.profile;
286 if (!entry) 286 if (!entry)
287 return; 287 return;
@@ -293,7 +293,6 @@ void fs_blacklist(void) {
293 if (noblacklist == NULL) 293 if (noblacklist == NULL)
294 errExit("failed allocating memory for noblacklist entries"); 294 errExit("failed allocating memory for noblacklist entries");
295 295
296 EUID_USER();
297 while (entry) { 296 while (entry) {
298 OPERATION op = OPERATION_MAX; 297 OPERATION op = OPERATION_MAX;
299 char *ptr; 298 char *ptr;
@@ -469,8 +468,6 @@ void fs_blacklist(void) {
469 for (i = 0; i < noblacklist_c; i++) 468 for (i = 0; i < noblacklist_c; i++)
470 free(noblacklist[i]); 469 free(noblacklist[i]);
471 free(noblacklist); 470 free(noblacklist);
472
473 EUID_ROOT();
474} 471}
475 472
476//*********************************************** 473//***********************************************
@@ -479,7 +476,7 @@ void fs_blacklist(void) {
479 476
480// mount a writable tmpfs on directory; requires a resolved path 477// mount a writable tmpfs on directory; requires a resolved path
481void fs_tmpfs(const char *dir, unsigned check_owner) { 478void fs_tmpfs(const char *dir, unsigned check_owner) {
482 EUID_USER(); 479 EUID_ASSERT();
483 assert(dir); 480 assert(dir);
484 if (arg_debug) 481 if (arg_debug)
485 printf("Mounting tmpfs on %s, check owner: %s\n", dir, (check_owner)? "yes": "no"); 482 printf("Mounting tmpfs on %s, check owner: %s\n", dir, (check_owner)? "yes": "no");
@@ -504,12 +501,13 @@ void fs_tmpfs(const char *dir, unsigned check_owner) {
504 errExit("fstatvfs"); 501 errExit("fstatvfs");
505 unsigned long flags = buf.f_flag & ~(MS_RDONLY|MS_BIND|MS_REMOUNT); 502 unsigned long flags = buf.f_flag & ~(MS_RDONLY|MS_BIND|MS_REMOUNT);
506 // mount via the symbolic link in /proc/self/fd 503 // mount via the symbolic link in /proc/self/fd
507 EUID_ROOT();
508 char *proc; 504 char *proc;
509 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) 505 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
510 errExit("asprintf"); 506 errExit("asprintf");
507 EUID_ROOT();
511 if (mount("tmpfs", proc, "tmpfs", flags|MS_NOSUID|MS_NODEV, options) < 0) 508 if (mount("tmpfs", proc, "tmpfs", flags|MS_NOSUID|MS_NODEV, options) < 0)
512 errExit("mounting tmpfs"); 509 errExit("mounting tmpfs");
510 EUID_USER();
513 // check the last mount operation 511 // check the last mount operation
514 MountData *mdata = get_last_mount(); 512 MountData *mdata = get_last_mount();
515 if (strcmp(mdata->fstype, "tmpfs") != 0 || strcmp(mdata->dir, dir) != 0) 513 if (strcmp(mdata->fstype, "tmpfs") != 0 || strcmp(mdata->dir, dir) != 0)
@@ -635,34 +633,30 @@ out:
635} 633}
636 634
637// remount recursively; requires a resolved path 635// remount recursively; requires a resolved path
638static void fs_remount_rec(const char *dir, OPERATION op) { 636static void fs_remount_rec(const char *path, OPERATION op) {
639 EUID_ASSERT(); 637 EUID_ASSERT();
640 assert(dir); 638 assert(op < OPERATION_MAX);
639 assert(path);
641 640
642 struct stat s; 641 // no need to search /proc/self/mountinfo for submounts if not a directory
643 if (stat(dir, &s) != 0) 642 int fd = open(path, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
644 return; 643 if (fd < 0) {
645 if (!S_ISDIR(s.st_mode)) { 644 fs_remount_simple(path, op);
646 // no need to search in /proc/self/mountinfo for submounts if not a directory
647 fs_remount_simple(dir, op);
648 return; 645 return;
649 } 646 }
650 // get mount point of the directory 647
651 int mountid = get_mount_id(dir); 648 // get mount id of the directory
652 if (mountid == -1) 649 int mountid = get_mount_id(fd);
653 return; 650 close(fd);
654 if (mountid == -2) { 651 if (mountid < 0) {
655 // falling back to a simple remount on old kernels 652 // falling back to a simple remount
656 static int mount_warning = 0; 653 fwarning("%s %s not applied recursively\n", opstr[op], path);
657 if (!mount_warning) { 654 fs_remount_simple(path, op);
658 fwarning("read-only, read-write and noexec options are not applied recursively\n");
659 mount_warning = 1;
660 }
661 fs_remount_simple(dir, op);
662 return; 655 return;
663 } 656 }
657
664 // build array with all mount points that need to get remounted 658 // build array with all mount points that need to get remounted
665 char **arr = build_mount_array(mountid, dir); 659 char **arr = build_mount_array(mountid, path);
666 assert(arr); 660 assert(arr);
667 // remount 661 // remount
668 char **tmp = arr; 662 char **tmp = arr;
diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c
index 8cc3ecc62..a43b18344 100644
--- a/src/firejail/fs_dev.c
+++ b/src/firejail/fs_dev.c
@@ -330,8 +330,10 @@ void fs_dev_disable_sound(void) {
330 } 330 }
331 331
332 // disable all jack sockets in /dev/shm 332 // disable all jack sockets in /dev/shm
333 EUID_USER();
333 glob_t globbuf; 334 glob_t globbuf;
334 int globerr = glob("/dev/shm/jack*", GLOB_NOSORT, NULL, &globbuf); 335 int globerr = glob("/dev/shm/jack*", GLOB_NOSORT, NULL, &globbuf);
336 EUID_ROOT();
335 if (globerr) 337 if (globerr)
336 return; 338 return;
337 339
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c
index 0ed476063..590337da1 100644
--- a/src/firejail/fs_home.c
+++ b/src/firejail/fs_home.c
@@ -395,14 +395,16 @@ void fs_private(void) {
395 } 395 }
396 if (chown(homedir, u, g) < 0) 396 if (chown(homedir, u, g) < 0)
397 errExit("chown"); 397 errExit("chown");
398
399 fs_logger2("mkdir", homedir); 398 fs_logger2("mkdir", homedir);
400 fs_logger2("tmpfs", homedir); 399 fs_logger2("tmpfs", homedir);
401 } 400 }
402 else 401 else {
403 // mask user home directory 402 // mask user home directory
404 // the directory should be owned by the current user 403 // the directory should be owned by the current user
404 EUID_USER();
405 fs_tmpfs(homedir, 1); 405 fs_tmpfs(homedir, 1);
406 EUID_ROOT();
407 }
406 408
407 selinux_relabel_path(homedir, homedir); 409 selinux_relabel_path(homedir, homedir);
408 } 410 }
@@ -564,12 +566,13 @@ void fs_private_home_list(void) {
564 int xflag = store_xauthority(); 566 int xflag = store_xauthority();
565 int aflag = store_asoundrc(); 567 int aflag = store_asoundrc();
566 568
567 // create /run/firejail/mnt/home directory
568 EUID_ROOT(); 569 EUID_ROOT();
570 // create /run/firejail/mnt/home directory
569 mkdir_attr(RUN_HOME_DIR, 0755, uid, gid); 571 mkdir_attr(RUN_HOME_DIR, 0755, uid, gid);
570 selinux_relabel_path(RUN_HOME_DIR, homedir); 572 selinux_relabel_path(RUN_HOME_DIR, homedir);
571 573
572 fs_logger_print(); // save the current log 574 // save the current log
575 fs_logger_print();
573 EUID_USER(); 576 EUID_USER();
574 577
575 // copy the list of files in the new home directory 578 // copy the list of files in the new home directory
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c
index 943f275de..7afebed1f 100644
--- a/src/firejail/fs_whitelist.c
+++ b/src/firejail/fs_whitelist.c
@@ -105,6 +105,7 @@ static int whitelist_mkpath(const char* path, mode_t mode) {
105} 105}
106 106
107static void whitelist_file(int dirfd, const char *relpath, const char *path) { 107static void whitelist_file(int dirfd, const char *relpath, const char *path) {
108 EUID_ASSERT();
108 assert(relpath && path); 109 assert(relpath && path);
109 110
110 // open mount source, using a file descriptor that refers to the 111 // open mount source, using a file descriptor that refers to the
@@ -130,12 +131,9 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
130 } 131 }
131 132
132 // create mount target as root, except if inside home or run/user/$UID directory 133 // create mount target as root, except if inside home or run/user/$UID directory
133 int userprivs = 0; 134 if ((strncmp(path, cfg.homedir, homedir_len) != 0 || path[homedir_len] != '/') &&
134 if ((strncmp(path, cfg.homedir, homedir_len) == 0 && path[homedir_len] == '/') || 135 (strncmp(path, runuser, runuser_len) != 0 || path[runuser_len] != '/'))
135 (strncmp(path, runuser, runuser_len) == 0 && path[runuser_len] == '/')) { 136 EUID_ROOT();
136 EUID_USER();
137 userprivs = 1;
138 }
139 137
140 // create path of the mount target 138 // create path of the mount target
141 int fd2 = whitelist_mkpath(path, 0755); 139 int fd2 = whitelist_mkpath(path, 0755);
@@ -146,8 +144,7 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
146 if (arg_debug || arg_debug_whitelists) 144 if (arg_debug || arg_debug_whitelists)
147 printf("Debug %d: skip whitelist %s\n", __LINE__, path); 145 printf("Debug %d: skip whitelist %s\n", __LINE__, path);
148 close(fd); 146 close(fd);
149 if (userprivs) 147 EUID_USER();
150 EUID_ROOT();
151 return; 148 return;
152 } 149 }
153 150
@@ -166,8 +163,7 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
166 } 163 }
167 close(fd); 164 close(fd);
168 close(fd2); 165 close(fd2);
169 if (userprivs) 166 EUID_USER();
170 EUID_ROOT();
171 return; 167 return;
172 } 168 }
173 fd3 = openat(fd2, file, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); 169 fd3 = openat(fd2, file, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
@@ -184,19 +180,17 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
184 } 180 }
185 close(fd); 181 close(fd);
186 close(fd2); 182 close(fd2);
187 if (userprivs) 183 EUID_USER();
188 EUID_ROOT();
189 return; 184 return;
190 } 185 }
191
192 close(fd2); 186 close(fd2);
193 if (userprivs)
194 EUID_ROOT();
195 187
196 if (arg_debug || arg_debug_whitelists) 188 if (arg_debug || arg_debug_whitelists)
197 printf("Whitelisting %s\n", path); 189 printf("Whitelisting %s\n", path);
190 EUID_ROOT();
198 if (bind_mount_by_fd(fd, fd3)) 191 if (bind_mount_by_fd(fd, fd3))
199 errExit("mount bind"); 192 errExit("mount bind");
193 EUID_USER();
200 // check the last mount operation 194 // check the last mount operation
201 MountData *mptr = get_last_mount(); // will do exit(1) if the mount cannot be found 195 MountData *mptr = get_last_mount(); // will do exit(1) if the mount cannot be found
202#ifdef TEST_MOUNTINFO 196#ifdef TEST_MOUNTINFO
@@ -219,22 +213,19 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
219} 213}
220 214
221static void whitelist_symlink(const char *link, const char *target) { 215static void whitelist_symlink(const char *link, const char *target) {
216 EUID_ASSERT();
222 assert(link && target); 217 assert(link && target);
223 218
224 // create files as root, except if inside home or run/user/$UID directory 219 // create files as root, except if inside home or run/user/$UID directory
225 int userprivs = 0; 220 if ((strncmp(link, cfg.homedir, homedir_len) != 0 || link[homedir_len] != '/') &&
226 if ((strncmp(link, cfg.homedir, homedir_len) == 0 && link[homedir_len] == '/') || 221 (strncmp(link, runuser, runuser_len) != 0 || link[runuser_len] != '/'))
227 (strncmp(link, runuser, runuser_len) == 0 && link[runuser_len] == '/')) { 222 EUID_ROOT();
228 EUID_USER();
229 userprivs = 1;
230 }
231 223
232 int fd = whitelist_mkpath(link, 0755); 224 int fd = whitelist_mkpath(link, 0755);
233 if (fd == -1) { 225 if (fd == -1) {
234 if (arg_debug || arg_debug_whitelists) 226 if (arg_debug || arg_debug_whitelists)
235 printf("Debug %d: cannot create symbolic link %s\n", __LINE__, link); 227 printf("Debug %d: cannot create symbolic link %s\n", __LINE__, link);
236 if (userprivs) 228 EUID_USER();
237 EUID_ROOT();
238 return; 229 return;
239 } 230 }
240 231
@@ -252,8 +243,7 @@ static void whitelist_symlink(const char *link, const char *target) {
252 printf("Created symbolic link %s -> %s\n", link, target); 243 printf("Created symbolic link %s -> %s\n", link, target);
253 244
254 close(fd); 245 close(fd);
255 if (userprivs) 246 EUID_USER();
256 EUID_ROOT();
257} 247}
258 248
259static void globbing(const char *pattern) { 249static void globbing(const char *pattern) {
@@ -330,10 +320,11 @@ static void tmpfs_topdirs(const TopDir *topdirs) {
330 // init tmpfs 320 // init tmpfs
331 if (strcmp(topdirs[i].path, "/run") == 0) { 321 if (strcmp(topdirs[i].path, "/run") == 0) {
332 // restore /run/firejail directory 322 // restore /run/firejail directory
333 if (mkdir(RUN_FIREJAIL_DIR, 0755) == -1) 323 EUID_ROOT();
334 errExit("mkdir"); 324 mkdir_attr(RUN_FIREJAIL_DIR, 0755, 0, 0);
335 if (bind_mount_fd_to_path(fd, RUN_FIREJAIL_DIR)) 325 if (bind_mount_fd_to_path(fd, RUN_FIREJAIL_DIR))
336 errExit("mount bind"); 326 errExit("mount bind");
327 EUID_USER();
337 close(fd); 328 close(fd);
338 fs_logger2("whitelist", RUN_FIREJAIL_DIR); 329 fs_logger2("whitelist", RUN_FIREJAIL_DIR);
339 330
@@ -351,12 +342,14 @@ static void tmpfs_topdirs(const TopDir *topdirs) {
351 errExit("asprintf"); 342 errExit("asprintf");
352 if (strcmp(env, pamtmpdir) == 0) { 343 if (strcmp(env, pamtmpdir) == 0) {
353 // create empty user-owned /tmp/user/$UID directory 344 // create empty user-owned /tmp/user/$UID directory
345 EUID_ROOT();
354 mkdir_attr("/tmp/user", 0711, 0, 0); 346 mkdir_attr("/tmp/user", 0711, 0, 0);
355 selinux_relabel_path("/tmp/user", "/tmp/user"); 347 selinux_relabel_path("/tmp/user", "/tmp/user");
356 fs_logger("mkdir /tmp/user"); 348 fs_logger("mkdir /tmp/user");
357 mkdir_attr(pamtmpdir, 0700, getuid(), 0); 349 mkdir_attr(pamtmpdir, 0700, getuid(), 0);
358 selinux_relabel_path(pamtmpdir, pamtmpdir); 350 selinux_relabel_path(pamtmpdir, pamtmpdir);
359 fs_logger2("mkdir", pamtmpdir); 351 fs_logger2("mkdir", pamtmpdir);
352 EUID_USER();
360 } 353 }
361 free(pamtmpdir); 354 free(pamtmpdir);
362 } 355 }
@@ -374,11 +367,8 @@ static void tmpfs_topdirs(const TopDir *topdirs) {
374 } 367 }
375 368
376 // user home directory 369 // user home directory
377 if (tmpfs_home) { 370 if (tmpfs_home)
378 EUID_USER();
379 fs_private(); // checks owner if outside /home 371 fs_private(); // checks owner if outside /home
380 EUID_ROOT();
381 }
382 372
383 // /run/user/$UID directory 373 // /run/user/$UID directory
384 if (tmpfs_runuser) { 374 if (tmpfs_runuser) {
@@ -402,6 +392,7 @@ static int reject_topdir(const char *dir) {
402// keep track of whitelist top level directories by adding them to an array 392// keep track of whitelist top level directories by adding them to an array
403// open each directory 393// open each directory
404static TopDir *add_topdir(const char *dir, TopDir *topdirs, const char *path) { 394static TopDir *add_topdir(const char *dir, TopDir *topdirs, const char *path) {
395 EUID_ASSERT();
405 assert(dir && path); 396 assert(dir && path);
406 397
407 // /proc and /sys are not allowed 398 // /proc and /sys are not allowed
@@ -516,6 +507,8 @@ static char *extract_topdir(const char *path) {
516} 507}
517 508
518void fs_whitelist(void) { 509void fs_whitelist(void) {
510 EUID_ASSERT();
511
519 ProfileEntry *entry = cfg.profile; 512 ProfileEntry *entry = cfg.profile;
520 if (!entry) 513 if (!entry)
521 return; 514 return;
@@ -536,7 +529,6 @@ void fs_whitelist(void) {
536 errExit("calloc"); 529 errExit("calloc");
537 530
538 // verify whitelist files, extract symbolic links, etc. 531 // verify whitelist files, extract symbolic links, etc.
539 EUID_USER();
540 while (entry) { 532 while (entry) {
541 int nowhitelist_flag = 0; 533 int nowhitelist_flag = 0;
542 534
@@ -630,7 +622,7 @@ void fs_whitelist(void) {
630 if (!fname) { 622 if (!fname) {
631 if (arg_debug || arg_debug_whitelists) { 623 if (arg_debug || arg_debug_whitelists) {
632 printf("Removed path: %s\n", entry->data); 624 printf("Removed path: %s\n", entry->data);
633 printf("\texpanded: %s\n", new_name); 625 printf("\tnew_name: %s\n", new_name);
634 printf("\trealpath: (null)\n"); 626 printf("\trealpath: (null)\n");
635 printf("\t%s\n", strerror(errno)); 627 printf("\t%s\n", strerror(errno));
636 } 628 }
@@ -712,7 +704,6 @@ void fs_whitelist(void) {
712 free(nowhitelist); 704 free(nowhitelist);
713 705
714 // mount tmpfs on all top level directories 706 // mount tmpfs on all top level directories
715 EUID_ROOT();
716 tmpfs_topdirs(topdirs); 707 tmpfs_topdirs(topdirs);
717 708
718 // go through profile rules again, and interpret whitelist commands 709 // go through profile rules again, and interpret whitelist commands
diff --git a/src/firejail/mountinfo.c b/src/firejail/mountinfo.c
index 64a94bd84..304f80eee 100644
--- a/src/firejail/mountinfo.c
+++ b/src/firejail/mountinfo.c
@@ -19,6 +19,7 @@
19*/ 19*/
20 20
21#include "firejail.h" 21#include "firejail.h"
22#include <errno.h>
22 23
23#include <fcntl.h> 24#include <fcntl.h>
24#ifndef O_PATH 25#ifndef O_PATH
@@ -151,53 +152,71 @@ MountData *get_last_mount(void) {
151 return &mdata; 152 return &mdata;
152} 153}
153 154
154// Extract the mount id from /proc/self/fdinfo and return it. 155// Returns mount id, or -1 if fd refers to a procfs or sysfs file
155int get_mount_id(const char *path) { 156static int get_mount_id_from_handle(int fd) {
156 EUID_ASSERT(); 157 EUID_ASSERT();
157 assert(path);
158 158
159 int fd = open(path, O_PATH|O_CLOEXEC); 159 char *proc;
160 if (fd == -1) 160 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
161 return -1; 161 errExit("asprintf");
162 struct file_handle *fh = malloc(sizeof *fh);
163 if (!fh)
164 errExit("malloc");
165 fh->handle_bytes = 0;
166
167 int rv = -1;
168 int tmp;
169 if (name_to_handle_at(-1, proc, fh, &tmp, AT_SYMLINK_FOLLOW) != -1) {
170 fprintf(stderr, "Error: unexpected result from name_to_handle_at\n");
171 exit(1);
172 }
173 if (errno == EOVERFLOW && fh->handle_bytes)
174 rv = tmp;
175
176 free(proc);
177 free(fh);
178 return rv;
179}
180
181// Returns mount id, or -1 on kernels < 3.15
182static int get_mount_id_from_fdinfo(int fd) {
183 EUID_ASSERT();
184 int rv = -1;
162 185
163 char *fdinfo; 186 char *proc;
164 if (asprintf(&fdinfo, "/proc/self/fdinfo/%d", fd) == -1) 187 if (asprintf(&proc, "/proc/self/fdinfo/%d", fd) == -1)
165 errExit("asprintf"); 188 errExit("asprintf");
166 EUID_ROOT(); 189 EUID_ROOT();
167 FILE *fp = fopen(fdinfo, "re"); 190 FILE *fp = fopen(proc, "re");
168 EUID_USER(); 191 EUID_USER();
169 free(fdinfo);
170 if (!fp) 192 if (!fp)
171 goto errexit; 193 goto errexit;
172 194
173 // read the file
174 char buf[MAX_BUF]; 195 char buf[MAX_BUF];
175 if (fgets(buf, MAX_BUF, fp) == NULL) 196 while (fgets(buf, MAX_BUF, fp)) {
176 goto errexit;
177 do {
178 if (strncmp(buf, "mnt_id:", 7) == 0) { 197 if (strncmp(buf, "mnt_id:", 7) == 0) {
179 char *ptr = buf + 7; 198 if (sscanf(buf + 7, "%d", &rv) != 1)
180 while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
181 ptr++;
182 }
183 if (*ptr == '\0')
184 goto errexit; 199 goto errexit;
185 fclose(fp); 200 break;
186 close(fd);
187 return atoi(ptr);
188 } 201 }
189 } while (fgets(buf, MAX_BUF, fp)); 202 }
190 203
191 // fallback, kernels older than 3.15 don't expose the mount id in this place 204 free(proc);
192 fclose(fp); 205 fclose(fp);
193 close(fd); 206 return rv;
194 return -2;
195 207
196errexit: 208errexit:
197 fprintf(stderr, "Error: cannot read proc file\n"); 209 fprintf(stderr, "Error: cannot read proc file\n");
198 exit(1); 210 exit(1);
199} 211}
200 212
213int get_mount_id(int fd) {
214 int rv = get_mount_id_from_fdinfo(fd);
215 if (rv < 0)
216 rv = get_mount_id_from_handle(fd);
217 return rv;
218}
219
201// Check /proc/self/mountinfo if path contains any mounts points. 220// Check /proc/self/mountinfo if path contains any mounts points.
202// Returns an array that can be iterated over for recursive remounting. 221// Returns an array that can be iterated over for recursive remounting.
203char **build_mount_array(const int mount_id, const char *path) { 222char **build_mount_array(const int mount_id, const char *path) {
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index 059100fcb..5390249ea 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -175,6 +175,10 @@ static int check_allow_drm(void) {
175 return checkcfg(CFG_BROWSER_ALLOW_DRM) != 0; 175 return checkcfg(CFG_BROWSER_ALLOW_DRM) != 0;
176} 176}
177 177
178static int check_allow_tray(void) {
179 return checkcfg(CFG_ALLOW_TRAY) != 0;
180}
181
178Cond conditionals[] = { 182Cond conditionals[] = {
179 {"HAS_APPIMAGE", check_appimage}, 183 {"HAS_APPIMAGE", check_appimage},
180 {"HAS_NET", check_netoptions}, 184 {"HAS_NET", check_netoptions},
@@ -184,6 +188,7 @@ Cond conditionals[] = {
184 {"HAS_X11", check_x11}, 188 {"HAS_X11", check_x11},
185 {"BROWSER_DISABLE_U2F", check_disable_u2f}, 189 {"BROWSER_DISABLE_U2F", check_disable_u2f},
186 {"BROWSER_ALLOW_DRM", check_allow_drm}, 190 {"BROWSER_ALLOW_DRM", check_allow_drm},
191 {"ALLOW_TRAY", check_allow_tray},
187 { NULL, NULL } 192 { NULL, NULL }
188}; 193};
189 194
@@ -630,7 +635,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
630#endif 635#endif
631 return 0; 636 return 0;
632 } 637 }
633 else if (strncmp(ptr, "netns ", 6) == 0) { 638 else if (strncmp(ptr, "netns ", 6) == 0) {
634#ifdef HAVE_NETWORK 639#ifdef HAVE_NETWORK
635 if (checkcfg(CFG_NETWORK)) { 640 if (checkcfg(CFG_NETWORK)) {
636 arg_netns = ptr + 6; 641 arg_netns = ptr + 6;
@@ -981,10 +986,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
981 warning_feature_disabled("seccomp"); 986 warning_feature_disabled("seccomp");
982 return 0; 987 return 0;
983 } 988 }
984 if (strncmp(ptr, "seccomp.32.drop ", 13) == 0) { 989 if (strncmp(ptr, "seccomp.32.drop ", 16) == 0) {
985 if (checkcfg(CFG_SECCOMP)) { 990 if (checkcfg(CFG_SECCOMP)) {
986 arg_seccomp32 = 1; 991 arg_seccomp32 = 1;
987 cfg.seccomp_list_drop32 = seccomp_check_list(ptr + 13); 992 cfg.seccomp_list_drop32 = seccomp_check_list(ptr + 16);
988 } 993 }
989 else 994 else
990 warning_feature_disabled("seccomp"); 995 warning_feature_disabled("seccomp");
@@ -1001,10 +1006,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
1001 warning_feature_disabled("seccomp"); 1006 warning_feature_disabled("seccomp");
1002 return 0; 1007 return 0;
1003 } 1008 }
1004 if (strncmp(ptr, "seccomp.32.keep ", 13) == 0) { 1009 if (strncmp(ptr, "seccomp.32.keep ", 16) == 0) {
1005 if (checkcfg(CFG_SECCOMP)) { 1010 if (checkcfg(CFG_SECCOMP)) {
1006 arg_seccomp32 = 1; 1011 arg_seccomp32 = 1;
1007 cfg.seccomp_list_keep32 = seccomp_check_list(ptr + 13); 1012 cfg.seccomp_list_keep32 = seccomp_check_list(ptr + 16);
1008 } 1013 }
1009 else 1014 else
1010 warning_feature_disabled("seccomp"); 1015 warning_feature_disabled("seccomp");
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 7a1ce737b..b776a0cc5 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -1007,10 +1007,12 @@ int sandbox(void* sandbox_arg) {
1007 // apply the profile file 1007 // apply the profile file
1008 //**************************** 1008 //****************************
1009 // apply all whitelist commands ... 1009 // apply all whitelist commands ...
1010 EUID_USER();
1010 fs_whitelist(); 1011 fs_whitelist();
1011 1012
1012 // ... followed by blacklist commands 1013 // ... followed by blacklist commands
1013 fs_blacklist(); // mkdir and mkfile are processed all over again 1014 fs_blacklist(); // mkdir and mkfile are processed all over again
1015 EUID_ROOT();
1014 1016
1015 //**************************** 1017 //****************************
1016 // nosound/no3d/notv/novideo and fix for pulseaudio 7.0 1018 // nosound/no3d/notv/novideo and fix for pulseaudio 7.0
diff --git a/src/firejail/selinux.c b/src/firejail/selinux.c
index 6969e7a3d..fa59882ed 100644
--- a/src/firejail/selinux.c
+++ b/src/firejail/selinux.c
@@ -21,6 +21,7 @@
21#include "firejail.h" 21#include "firejail.h"
22#include <sys/types.h> 22#include <sys/types.h>
23#include <sys/stat.h> 23#include <sys/stat.h>
24#include <errno.h>
24 25
25#include <fcntl.h> 26#include <fcntl.h>
26#ifndef O_PATH 27#ifndef O_PATH
@@ -57,7 +58,17 @@ void selinux_relabel_path(const char *path, const char *inside_path)
57 58
58 /* Open the file as O_PATH, to pin it while we determine and adjust the label 59 /* Open the file as O_PATH, to pin it while we determine and adjust the label
59 * Defeat symlink races by not allowing symbolic links */ 60 * Defeat symlink races by not allowing symbolic links */
61 int called_as_root = 0;
62 if (geteuid() == 0)
63 called_as_root = 1;
64 if (called_as_root)
65 EUID_USER();
66
60 fd = safer_openat(-1, path, O_NOFOLLOW|O_CLOEXEC|O_PATH); 67 fd = safer_openat(-1, path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
68
69 if (called_as_root)
70 EUID_ROOT();
71
61 if (fd < 0) 72 if (fd < 0)
62 return; 73 return;
63 if (fstat(fd, &st) < 0) 74 if (fstat(fd, &st) < 0)
@@ -68,8 +79,16 @@ void selinux_relabel_path(const char *path, const char *inside_path)
68 if (arg_debug) 79 if (arg_debug)
69 printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon); 80 printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon);
70 81
71 setfilecon_raw(procfs_path, fcon); 82 if (!called_as_root)
83 EUID_ROOT();
84
85 if (setfilecon_raw(procfs_path, fcon) != 0 && arg_debug)
86 printf("Cannot relabel %s: %s\n", path, strerror(errno));
87
88 if (!called_as_root)
89 EUID_USER();
72 } 90 }
91
73 freecon(fcon); 92 freecon(fcon);
74 close: 93 close:
75 close(fd); 94 close(fd);
diff --git a/src/firejail/util.c b/src/firejail/util.c
index 094a68c60..f0df45eb2 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -459,31 +459,21 @@ int is_dir(const char *fname) {
459 if (*fname == '\0') 459 if (*fname == '\0')
460 return 0; 460 return 0;
461 461
462 int called_as_root = 0;
463 if (geteuid() == 0)
464 called_as_root = 1;
465
466 if (called_as_root)
467 EUID_USER();
468
469 // if fname doesn't end in '/', add one 462 // if fname doesn't end in '/', add one
470 int rv; 463 int rv;
471 struct stat s; 464 struct stat s;
472 if (fname[strlen(fname) - 1] == '/') 465 if (fname[strlen(fname) - 1] == '/')
473 rv = stat(fname, &s); 466 rv = stat_as_user(fname, &s);
474 else { 467 else {
475 char *tmp; 468 char *tmp;
476 if (asprintf(&tmp, "%s/", fname) == -1) { 469 if (asprintf(&tmp, "%s/", fname) == -1) {
477 fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__); 470 fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__);
478 errExit("asprintf"); 471 errExit("asprintf");
479 } 472 }
480 rv = stat(tmp, &s); 473 rv = stat_as_user(tmp, &s);
481 free(tmp); 474 free(tmp);
482 } 475 }
483 476
484 if (called_as_root)
485 EUID_ROOT();
486
487 if (rv == -1) 477 if (rv == -1)
488 return 0; 478 return 0;
489 479
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt
index a768829a1..a1eccaa5e 100644
--- a/src/man/firejail-profile.txt
+++ b/src/man/firejail-profile.txt
@@ -78,7 +78,7 @@ in your desktop environment copy the profile file in ~/.config/firejail director
78Several command line options can be passed to the program using 78Several command line options can be passed to the program using
79profile files. Firejail chooses the profile file as follows: 79profile files. Firejail chooses the profile file as follows:
80 80
81\fB1.\fR If a profile file is provided by the user with \-\-profile option, the profile file is loaded. If a profile name is given, it is searched for first in the ~/.config/firejail directory and if not found then in /etc/firejail directory. Profile names do not include the .profile suffix. 81\fB1.\fR If a profile file is provided by the user with \-\-profile option, the profile file is loaded. If a profile name is given, it is searched for first in the ~/.config/firejail directory and if not found then in /etc/firejail directory. Profile names do not include the .profile suffix.
82Example: 82Example:
83.PP 83.PP
84.RS 84.RS
@@ -174,7 +174,7 @@ Example: "?HAS_APPIMAGE: whitelist ${HOME}/special/appimage/dir"
174 174
175This example will load the whitelist profile line only if the \-\-appimage option has been specified on the command line. 175This example will load the whitelist profile line only if the \-\-appimage option has been specified on the command line.
176 176
177Currently the only conditionals supported this way are HAS_APPIMAGE, HAS_NET, HAS_NODBUS, HAS_NOSOUND, HAS_PRIVATE and HAS_X11. The conditionals BROWSER_DISABLE_U2F and BROWSER_ALLOW_DRM 177Currently the only conditionals supported this way are HAS_APPIMAGE, HAS_NET, HAS_NODBUS, HAS_NOSOUND, HAS_PRIVATE and HAS_X11. The conditionals ALLOW_TRAY, BROWSER_DISABLE_U2F and BROWSER_ALLOW_DRM
178can be enabled or disabled globally in Firejail's configuration file. 178can be enabled or disabled globally in Firejail's configuration file.
179 179
180The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines. 180The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines.
@@ -324,16 +324,16 @@ Remount the file or the directory noexec, nodev and nosuid.
324#ifdef HAVE_OVERLAYFS 324#ifdef HAVE_OVERLAYFS
325.TP 325.TP
326\fBoverlay 326\fBoverlay
327Mount a filesystem overlay on top of the current filesystem. 327Mount a filesystem overlay on top of the current filesystem.
328The overlay is stored in $HOME/.firejail/<PID> directory. 328The overlay is stored in $HOME/.firejail/<PID> directory.
329.TP 329.TP
330\fBoverlay-named name 330\fBoverlay-named name
331Mount a filesystem overlay on top of the current filesystem. 331Mount a filesystem overlay on top of the current filesystem.
332The overlay is stored in $HOME/.firejail/name directory. 332The overlay is stored in $HOME/.firejail/name directory.
333.TP 333.TP
334\fBoverlay-tmpfs 334\fBoverlay-tmpfs
335Mount a filesystem overlay on top of the current filesystem. 335Mount a filesystem overlay on top of the current filesystem.
336All filesystem modifications are discarded when the sandbox is closed. 336All filesystem modifications are discarded when the sandbox is closed.
337#endif 337#endif
338.TP 338.TP
339\fBprivate 339\fBprivate
@@ -487,12 +487,12 @@ does not result in an increase of privilege.
487#ifdef HAVE_USERNS 487#ifdef HAVE_USERNS
488.TP 488.TP
489\fBnoroot 489\fBnoroot
490Use this command to enable an user namespace. The namespace has only one user, the current user. 490Use this command to enable an user namespace. The namespace has only one user, the current user.
491There is no root account (uid 0) defined in the namespace. 491There is no root account (uid 0) defined in the namespace.
492#endif 492#endif
493.TP 493.TP
494\fBprotocol protocol1,protocol2,protocol3 494\fBprotocol protocol1,protocol2,protocol3
495Enable protocol filter. The filter is based on seccomp and checks the 495Enable protocol filter. The filter is based on seccomp and checks the
496first argument to socket system call. Recognized values: \fBunix\fR, 496first argument to socket system call. Recognized values: \fBunix\fR,
497\fBinet\fR, \fBinet6\fR, \fBnetlink\fR, \fBpacket\fR and \fBbluetooth\fR. 497\fBinet\fR, \fBinet6\fR, \fBnetlink\fR, \fBpacket\fR and \fBbluetooth\fR.
498.TP 498.TP
@@ -873,8 +873,8 @@ a DHCP client and releasing the lease manually.
873 873
874.TP 874.TP
875\fBiprange address,address 875\fBiprange address,address
876Assign an IP address in the provided range to the last network 876Assign an IP address in the provided range to the last network
877interface defined by a net command. A default gateway is assigned by default. 877interface defined by a net command. A default gateway is assigned by default.
878.br 878.br
879 879
880.br 880.br
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index 0462705c0..2883ab257 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -45,7 +45,7 @@ firejail {\-? | \-\-debug-caps | \-\-debug-errnos | \-\-debug-syscalls | \-\-deb
45#ifdef HAVE_LTS 45#ifdef HAVE_LTS
46This is Firejail long-term support (LTS), an enterprise focused version of the software, 46This is Firejail long-term support (LTS), an enterprise focused version of the software,
47LTS is usually supported for two or three years. 47LTS is usually supported for two or three years.
48During this time only bugs and the occasional documentation problems are fixed. 48During this time only bugs and the occasional documentation problems are fixed.
49The attack surface of the SUID executable was greatly reduced by removing some of the features. 49The attack surface of the SUID executable was greatly reduced by removing some of the features.
50.br 50.br
51 51
@@ -109,7 +109,7 @@ ptrace system call allows a full bypass of the seccomp filter.
109.br 109.br
110Example: 110Example:
111.br 111.br
112$ firejail --allow-debuggers --profile=/etc/firejail/firefox.profile strace -f firefox 112$ firejail --allow-debuggers --profile=/etc/firejail/firefox.profile strace -f firefox
113.TP 113.TP
114\fB\-\-allusers 114\fB\-\-allusers
115All directories under /home are visible inside the sandbox. By default, only current user home directory is visible. 115All directories under /home are visible inside the sandbox. By default, only current user home directory is visible.
@@ -947,7 +947,7 @@ $ firejail \-\-net=eth0 \-\-\iprange=192.168.1.100,192.168.1.150
947 947
948.TP 948.TP
949\fB\-\-ipc-namespace 949\fB\-\-ipc-namespace
950Enable a new IPC namespace if the sandbox was started as a regular user. IPC namespace is enabled by default 950Enable a new IPC namespace if the sandbox was started as a regular user. IPC namespace is enabled by default
951for sandboxes started as root. 951for sandboxes started as root.
952.br 952.br
953 953
@@ -1014,7 +1014,7 @@ $ sudo firejail --join-network=browser /sbin/iptables -vL
1014.br 1014.br
1015 1015
1016.br 1016.br
1017# verify IP addresses 1017# verify IP addresses
1018.br 1018.br
1019$ sudo firejail --join-network=browser ip addr 1019$ sudo firejail --join-network=browser ip addr
1020.br 1020.br
@@ -2134,7 +2134,7 @@ Use k(ilobyte), m(egabyte) or g(igabyte) for size suffix (base 1024).
2134.TP 2134.TP
2135\fB\-\-rlimit-cpu=number 2135\fB\-\-rlimit-cpu=number
2136Set the maximum limit, in seconds, for the amount of CPU time each 2136Set the maximum limit, in seconds, for the amount of CPU time each
2137sandboxed process can consume. When the limit is reached, the processes are killed. 2137sandboxed process can consume. When the limit is reached, the processes are killed.
2138 2138
2139The CPU limit is a limit on CPU seconds rather than elapsed time. CPU seconds is basically how many seconds 2139The CPU limit is a limit on CPU seconds rather than elapsed time. CPU seconds is basically how many seconds
2140the CPU has been in use and does not necessarily directly relate to the elapsed time. Linux kernel keeps 2140the CPU has been in use and does not necessarily directly relate to the elapsed time. Linux kernel keeps
@@ -2178,7 +2178,7 @@ $ firejail \-\-net=eth0 \-\-scan
2178.TP 2178.TP
2179\fB\-\-seccomp 2179\fB\-\-seccomp
2180Enable seccomp filter and blacklist the syscalls in the default list, 2180Enable seccomp filter and blacklist the syscalls in the default list,
2181which is @default-nodebuggers unless \-\-allow-debuggers is specified, 2181which is @default-nodebuggers unless \-\-allow-debuggers is specified,
2182then it is @default. 2182then it is @default.
2183 2183
2184.br 2184.br
@@ -2865,7 +2865,7 @@ and it is installed by default on most Linux distributions. It provides support
2865connection model. Untrusted clients are restricted in certain ways to prevent them from reading window 2865connection model. Untrusted clients are restricted in certain ways to prevent them from reading window
2866contents of other clients, stealing input events, etc. 2866contents of other clients, stealing input events, etc.
2867 2867
2868The untrusted mode has several limitations. A lot of regular programs assume they are a trusted X11 clients 2868The untrusted mode has several limitations. A lot of regular programs assume they are a trusted X11 clients
2869and will crash or lock up when run in untrusted mode. Chromium browser and xterm are two examples. 2869and will crash or lock up when run in untrusted mode. Chromium browser and xterm are two examples.
2870Firefox and transmission-gtk seem to be working fine. 2870Firefox and transmission-gtk seem to be working fine.
2871A network namespace is not required for this option. 2871A network namespace is not required for this option.
@@ -3256,7 +3256,7 @@ The owner of the sandbox.
3256.SH RESTRICTED SHELL 3256.SH RESTRICTED SHELL
3257To configure a restricted shell, replace /bin/bash with /usr/bin/firejail in 3257To configure a restricted shell, replace /bin/bash with /usr/bin/firejail in
3258/etc/passwd file for each user that needs to be restricted. Alternatively, 3258/etc/passwd file for each user that needs to be restricted. Alternatively,
3259you can specify /usr/bin/firejail in adduser command: 3259you can specify /usr/bin/firejail in adduser command:
3260 3260
3261adduser \-\-shell /usr/bin/firejail username 3261adduser \-\-shell /usr/bin/firejail username
3262 3262
@@ -3266,7 +3266,7 @@ Additional arguments passed to firejail executable upon login are declared in /e
3266Several command line options can be passed to the program using 3266Several command line options can be passed to the program using
3267profile files. Firejail chooses the profile file as follows: 3267profile files. Firejail chooses the profile file as follows:
3268 3268
32691. If a profile file is provided by the user with --profile=FILE option, the profile FILE is loaded. If a profile name is given, it is searched for first in the ~/.config/firejail directory and if not found then in /etc/firejail directory. Profile names do not include the .profile suffix. If there is a file with the same name as the given profile name, it will be used instead of doing the profile search. To force a profile search, prefix the profile name with a colon (:), eg. --profile=:PROFILE_NAME. 32691. If a profile file is provided by the user with --profile=FILE option, the profile FILE is loaded. If a profile name is given, it is searched for first in the ~/.config/firejail directory and if not found then in /etc/firejail directory. Profile names do not include the .profile suffix. If there is a file with the same name as the given profile name, it will be used instead of doing the profile search. To force a profile search, prefix the profile name with a colon (:), eg. --profile=:PROFILE_NAME.
3270Example: 3270Example:
3271.PP 3271.PP
3272.RS 3272.RS
diff --git a/src/man/firemon.txt b/src/man/firemon.txt
index 76b2f7be2..c4e6e15b3 100644
--- a/src/man/firemon.txt
+++ b/src/man/firemon.txt
@@ -56,7 +56,7 @@ Print route table for each sandbox.
56Print seccomp configuration for each sandbox. 56Print seccomp configuration for each sandbox.
57.TP 57.TP
58\fB\-\-top 58\fB\-\-top
59Monitor the most CPU-intensive sandboxes. This command is similar to 59Monitor the most CPU-intensive sandboxes. This command is similar to
60the regular UNIX top command, however it applies only to sandboxes. 60the regular UNIX top command, however it applies only to sandboxes.
61.TP 61.TP
62\fB\-\-tree 62\fB\-\-tree