diff options
Diffstat (limited to 'src')
30 files changed, 350 insertions, 320 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/fids/fids.h b/src/fids/fids.h index a2e2886fe..eaf2bbd29 100644 --- a/src/fids/fids.h +++ b/src/fids/fids.h | |||
@@ -48,4 +48,4 @@ int db_exclude_check(const char *fname); | |||
48 | //#define KEY_SIZE 512 | 48 | //#define KEY_SIZE 512 |
49 | int blake2b(void *out, size_t outlen, const void *in, size_t inlen); | 49 | int blake2b(void *out, size_t outlen, const void *in, size_t inlen); |
50 | 50 | ||
51 | #endif \ No newline at end of file | 51 | #endif |
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config index 698630180..a544e25f2 100644 --- a/src/firecfg/firecfg.config +++ b/src/firecfg/firecfg.config | |||
@@ -348,6 +348,7 @@ gnome-weather | |||
348 | gnote | 348 | gnote |
349 | gnubik | 349 | gnubik |
350 | godot | 350 | godot |
351 | goldendict | ||
351 | goobox | 352 | goobox |
352 | google-chrome | 353 | google-chrome |
353 | google-chrome-beta | 354 | google-chrome-beta |
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/env.c b/src/firejail/env.c index f5e9dd980..ad16de037 100644 --- a/src/firejail/env.c +++ b/src/firejail/env.c | |||
@@ -262,7 +262,7 @@ static const char * const env_whitelist[] = { | |||
262 | "LANG", | 262 | "LANG", |
263 | "LANGUAGE", | 263 | "LANGUAGE", |
264 | "LC_MESSAGES", | 264 | "LC_MESSAGES", |
265 | "PATH", | 265 | // "PATH", |
266 | "DISPLAY" // required by X11 | 266 | "DISPLAY" // required by X11 |
267 | }; | 267 | }; |
268 | 268 | ||
@@ -311,6 +311,10 @@ void env_apply_whitelist(void) { | |||
311 | errExit("clearenv"); | 311 | errExit("clearenv"); |
312 | 312 | ||
313 | env_apply_list(env_whitelist, ARRAY_SIZE(env_whitelist)); | 313 | env_apply_list(env_whitelist, ARRAY_SIZE(env_whitelist)); |
314 | |||
315 | // hardcoding PATH | ||
316 | if (setenv("PATH", "/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin", 1) < 0) | ||
317 | errExit("setenv"); | ||
314 | } | 318 | } |
315 | 319 | ||
316 | // Filter env variables for a sbox app | 320 | // Filter env variables for a sbox app |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 2a7d88575..90cb2952b 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 |
565 | MountData *get_last_mount(void); | 565 | MountData *get_last_mount(void); |
566 | int get_mount_id(const char *path); | 566 | int get_mount_id(int fd); |
567 | char **build_mount_array(const int mount_id, const char *path); | 567 | char **build_mount_array(const int mount_id, const char *path); |
568 | 568 | ||
569 | // fs_var.c | 569 | // fs_var.c |
@@ -801,6 +801,7 @@ enum { | |||
801 | CFG_NAME_CHANGE, | 801 | CFG_NAME_CHANGE, |
802 | CFG_SECCOMP_ERROR_ACTION, | 802 | CFG_SECCOMP_ERROR_ACTION, |
803 | // CFG_FILE_COPY_LIMIT - file copy limit handled using setenv/getenv | 803 | // CFG_FILE_COPY_LIMIT - file copy limit handled using setenv/getenv |
804 | CFG_ALLOW_TRAY, | ||
804 | CFG_MAX // this should always be the last entry | 805 | CFG_MAX // this should always be the last entry |
805 | }; | 806 | }; |
806 | extern char *xephyr_screen; | 807 | extern char *xephyr_screen; |
diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 5ac2da164..3144156a3 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c | |||
@@ -108,7 +108,7 @@ static void disable_file(OPERATION op, const char *filename) { | |||
108 | } | 108 | } |
109 | 109 | ||
110 | // check for firejail executable | 110 | // check for firejail executable |
111 | // we migth have a file found in ${PATH} pointing to /usr/bin/firejail | 111 | // we might have a file found in ${PATH} pointing to /usr/bin/firejail |
112 | // blacklisting it here will end up breaking situations like user clicks on a link in Thunderbird | 112 | // blacklisting it here will end up breaking situations like user clicks on a link in Thunderbird |
113 | // and expects Firefox to open in the same sandbox | 113 | // and expects Firefox to open in the same sandbox |
114 | if (strcmp(BINDIR "/firejail", fname) == 0) { | 114 | if (strcmp(BINDIR "/firejail", fname) == 0) { |
@@ -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 |
284 | void fs_blacklist(void) { | 282 | void 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 |
481 | void fs_tmpfs(const char *dir, unsigned check_owner) { | 478 | void 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 |
638 | static void fs_remount_rec(const char *dir, OPERATION op) { | 636 | static 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_hostname.c b/src/firejail/fs_hostname.c index 1a9a78ceb..7d320e90b 100644 --- a/src/firejail/fs_hostname.c +++ b/src/firejail/fs_hostname.c | |||
@@ -93,10 +93,6 @@ char *fs_check_hosts_file(const char *fname) { | |||
93 | invalid_filename(fname, 0); // no globbing | 93 | invalid_filename(fname, 0); // no globbing |
94 | char *rv = expand_macros(fname); | 94 | char *rv = expand_macros(fname); |
95 | 95 | ||
96 | // no a link | ||
97 | if (is_link(rv)) | ||
98 | goto errexit; | ||
99 | |||
100 | // the user has read access to the file | 96 | // the user has read access to the file |
101 | if (access(rv, R_OK)) | 97 | if (access(rv, R_OK)) |
102 | goto errexit; | 98 | goto errexit; |
@@ -119,9 +115,6 @@ void fs_mount_hosts_file(void) { | |||
119 | struct stat s; | 115 | struct stat s; |
120 | if (stat("/etc/hosts", &s) == -1) | 116 | if (stat("/etc/hosts", &s) == -1) |
121 | goto errexit; | 117 | goto errexit; |
122 | // not a link | ||
123 | if (is_link("/etc/hosts")) | ||
124 | goto errexit; | ||
125 | // owned by root | 118 | // owned by root |
126 | if (s.st_uid != 0) | 119 | if (s.st_uid != 0) |
127 | goto errexit; | 120 | goto errexit; |
diff --git a/src/firejail/fs_lib.c b/src/firejail/fs_lib.c index 9d7a17cf3..848c186fa 100644 --- a/src/firejail/fs_lib.c +++ b/src/firejail/fs_lib.c | |||
@@ -195,6 +195,11 @@ void fslib_mount_libs(const char *full_path, unsigned user) { | |||
195 | assert(full_path); | 195 | assert(full_path); |
196 | // if library/executable does not exist or the user does not have read access to it | 196 | // if library/executable does not exist or the user does not have read access to it |
197 | // print a warning and exit the function. | 197 | // print a warning and exit the function. |
198 | if (access(full_path, F_OK)) { | ||
199 | if (arg_debug || arg_debug_private_lib) | ||
200 | printf("Cannot find %s, skipping...\n", full_path); | ||
201 | return; | ||
202 | } | ||
198 | if (user && access(full_path, R_OK)) { | 203 | if (user && access(full_path, R_OK)) { |
199 | if (arg_debug || arg_debug_private_lib) | 204 | if (arg_debug || arg_debug_private_lib) |
200 | printf("Cannot read %s, skipping...\n", full_path); | 205 | printf("Cannot read %s, skipping...\n", full_path); |
diff --git a/src/firejail/fs_lib2.c b/src/firejail/fs_lib2.c index c69bf7c98..a347b380c 100644 --- a/src/firejail/fs_lib2.c +++ b/src/firejail/fs_lib2.c | |||
@@ -143,7 +143,7 @@ static void fdir(void) { | |||
143 | NULL, | 143 | NULL, |
144 | }; | 144 | }; |
145 | 145 | ||
146 | // need to parse as root user, unprivileged users have no read permission on executables | 146 | // need to parse as root user, unprivileged users have no read permission on some of these binaries |
147 | int i; | 147 | int i; |
148 | for (i = 0; fbin[i]; i++) | 148 | for (i = 0; fbin[i]; i++) |
149 | fslib_mount_libs(fbin[i], 0); | 149 | fslib_mount_libs(fbin[i], 0); |
@@ -153,7 +153,9 @@ void fslib_install_firejail(void) { | |||
153 | timetrace_start(); | 153 | timetrace_start(); |
154 | // bring in firejail executable libraries, in case we are redirected here | 154 | // bring in firejail executable libraries, in case we are redirected here |
155 | // by a firejail symlink from /usr/local/bin/firejail | 155 | // by a firejail symlink from /usr/local/bin/firejail |
156 | fslib_mount_libs(PATH_FIREJAIL, 1); // parse as user | 156 | // fldd might have no read permission on the firejail executable |
157 | // parse as root in order to support these setups | ||
158 | fslib_mount_libs(PATH_FIREJAIL, 0); | ||
157 | 159 | ||
158 | // bring in firejail directory | 160 | // bring in firejail directory |
159 | fdir(); | 161 | fdir(); |
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 | ||
107 | static void whitelist_file(int dirfd, const char *relpath, const char *path) { | 107 | static 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 | ||
221 | static void whitelist_symlink(const char *link, const char *target) { | 215 | static 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 | ||
259 | static void globbing(const char *pattern) { | 249 | static 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 |
404 | static TopDir *add_topdir(const char *dir, TopDir *topdirs, const char *path) { | 394 | static 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 | ||
518 | void fs_whitelist(void) { | 509 | void 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/ids.c b/src/firejail/ids.c index 59acdb1fe..a9ff59be4 100644 --- a/src/firejail/ids.c +++ b/src/firejail/ids.c | |||
@@ -86,4 +86,4 @@ void run_ids(int argc, char **argv) { | |||
86 | fprintf(stderr, "Error: unrecognized IDS command\n"); | 86 | fprintf(stderr, "Error: unrecognized IDS command\n"); |
87 | 87 | ||
88 | exit(0); | 88 | exit(0); |
89 | } \ No newline at end of file | 89 | } |
diff --git a/src/firejail/join.c b/src/firejail/join.c index 394bbb528..a869f6b64 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c | |||
@@ -45,7 +45,7 @@ static unsigned display = 0; | |||
45 | static void signal_handler(int sig){ | 45 | static void signal_handler(int sig){ |
46 | flush_stdin(); | 46 | flush_stdin(); |
47 | 47 | ||
48 | exit(sig); | 48 | exit(128 + sig); |
49 | } | 49 | } |
50 | 50 | ||
51 | static void install_handler(void) { | 51 | static void install_handler(void) { |
@@ -536,7 +536,6 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
536 | prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); | 536 | prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); |
537 | 537 | ||
538 | #ifdef HAVE_APPARMOR | 538 | #ifdef HAVE_APPARMOR |
539 | // add apparmor confinement after the execve | ||
540 | set_apparmor(); | 539 | set_apparmor(); |
541 | #endif | 540 | #endif |
542 | 541 | ||
@@ -552,10 +551,6 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
552 | if (cfg.cpus) // not available for uid 0 | 551 | if (cfg.cpus) // not available for uid 0 |
553 | set_cpu_affinity(); | 552 | set_cpu_affinity(); |
554 | 553 | ||
555 | // set nice value | ||
556 | if (arg_nice) | ||
557 | set_nice(cfg.nice); | ||
558 | |||
559 | // add x11 display | 554 | // add x11 display |
560 | if (display) { | 555 | if (display) { |
561 | char *display_str; | 556 | char *display_str; |
@@ -574,6 +569,11 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
574 | dbus_set_system_bus_env(); | 569 | dbus_set_system_bus_env(); |
575 | #endif | 570 | #endif |
576 | 571 | ||
572 | // set nice and rlimits | ||
573 | if (arg_nice) | ||
574 | set_nice(cfg.nice); | ||
575 | set_rlimits(); | ||
576 | |||
577 | start_application(0, shfd, NULL); | 577 | start_application(0, shfd, NULL); |
578 | 578 | ||
579 | __builtin_unreachable(); | 579 | __builtin_unreachable(); |
@@ -596,15 +596,17 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
596 | 596 | ||
597 | // end of signal-safe code | 597 | // end of signal-safe code |
598 | //***************************** | 598 | //***************************** |
599 | flush_stdin(); | ||
600 | 599 | ||
601 | if (WIFEXITED(status)) { | 600 | if (WIFEXITED(status)) { |
601 | // if we had a proper exit, return that exit status | ||
602 | status = WEXITSTATUS(status); | 602 | status = WEXITSTATUS(status); |
603 | } else if (WIFSIGNALED(status)) { | 603 | } else if (WIFSIGNALED(status)) { |
604 | status = WTERMSIG(status); | 604 | // distinguish fatal signals by adding 128 |
605 | status = 128 + WTERMSIG(status); | ||
605 | } else { | 606 | } else { |
606 | status = 0; | 607 | status = -1; |
607 | } | 608 | } |
608 | 609 | ||
610 | flush_stdin(); | ||
609 | exit(status); | 611 | exit(status); |
610 | } | 612 | } |
diff --git a/src/firejail/main.c b/src/firejail/main.c index e0bf44f62..81d148257 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -189,13 +189,15 @@ static void my_handler(int s) { | |||
189 | logsignal(s); | 189 | logsignal(s); |
190 | 190 | ||
191 | if (waitpid(child, NULL, WNOHANG) == 0) { | 191 | if (waitpid(child, NULL, WNOHANG) == 0) { |
192 | if (has_handler(child, s)) // signals are not delivered if there is no handler yet | 192 | // child is pid 1 of a pid namespace: |
193 | // signals are not delivered if there is no handler yet | ||
194 | if (has_handler(child, s)) | ||
193 | kill(child, s); | 195 | kill(child, s); |
194 | else | 196 | else |
195 | kill(child, SIGKILL); | 197 | kill(child, SIGKILL); |
196 | waitpid(child, NULL, 0); | 198 | waitpid(child, NULL, 0); |
197 | } | 199 | } |
198 | myexit(s); | 200 | myexit(128 + s); |
199 | } | 201 | } |
200 | 202 | ||
201 | static void install_handler(void) { | 203 | static void install_handler(void) { |
@@ -1263,9 +1265,9 @@ int main(int argc, char **argv, char **envp) { | |||
1263 | arg_debug = 1; | 1265 | arg_debug = 1; |
1264 | arg_quiet = 0; | 1266 | arg_quiet = 0; |
1265 | } | 1267 | } |
1266 | else if (strcmp(argv[i], "--debug-deny") == 0) | 1268 | else if (strcmp(argv[i], "--debug-blacklists") == 0) |
1267 | arg_debug_blacklists = 1; | 1269 | arg_debug_blacklists = 1; |
1268 | else if (strcmp(argv[i], "--debug-allow") == 0) | 1270 | else if (strcmp(argv[i], "--debug-whitelists") == 0) |
1269 | arg_debug_whitelists = 1; | 1271 | arg_debug_whitelists = 1; |
1270 | else if (strcmp(argv[i], "--debug-private-lib") == 0) | 1272 | else if (strcmp(argv[i], "--debug-private-lib") == 0) |
1271 | arg_debug_private_lib = 1; | 1273 | arg_debug_private_lib = 1; |
@@ -3216,10 +3218,11 @@ printf("link #%s#\n", prf->link); | |||
3216 | if (WIFEXITED(status)){ | 3218 | if (WIFEXITED(status)){ |
3217 | myexit(WEXITSTATUS(status)); | 3219 | myexit(WEXITSTATUS(status)); |
3218 | } else if (WIFSIGNALED(status)) { | 3220 | } else if (WIFSIGNALED(status)) { |
3219 | myexit(WTERMSIG(status)); | 3221 | // distinguish fatal signals by adding 128 |
3222 | myexit(128 + WTERMSIG(status)); | ||
3220 | } else { | 3223 | } else { |
3221 | myexit(0); | 3224 | myexit(1); |
3222 | } | 3225 | } |
3223 | 3226 | ||
3224 | return 0; | 3227 | return 1; |
3225 | } | 3228 | } |
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 |
155 | int get_mount_id(const char *path) { | 156 | static 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 | ||
182 | static 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 | ||
196 | errexit: | 208 | errexit: |
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 | ||
213 | int 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. |
203 | char **build_mount_array(const int mount_id, const char *path) { | 222 | char **build_mount_array(const int mount_id, const char *path) { |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index b7c7185a6..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 | ||
178 | static int check_allow_tray(void) { | ||
179 | return checkcfg(CFG_ALLOW_TRAY) != 0; | ||
180 | } | ||
181 | |||
178 | Cond conditionals[] = { | 182 | Cond 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"); |
@@ -1938,7 +1943,7 @@ char *profile_list_compress(char *list) | |||
1938 | /* Include non-empty item */ | 1943 | /* Include non-empty item */ |
1939 | if (!*item) | 1944 | if (!*item) |
1940 | in[i] = 0; | 1945 | in[i] = 0; |
1941 | /* Remove all allready included items */ | 1946 | /* Remove all already included items */ |
1942 | for (k = 0; k < i; ++k) | 1947 | for (k = 0; k < i; ++k) |
1943 | in[k] = 0; | 1948 | in[k] = 0; |
1944 | break; | 1949 | break; |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 59ddfb855..83e50aee2 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -87,9 +87,9 @@ static void sandbox_handler(int sig){ | |||
87 | 87 | ||
88 | // broadcast a SIGKILL | 88 | // broadcast a SIGKILL |
89 | kill(-1, SIGKILL); | 89 | kill(-1, SIGKILL); |
90 | flush_stdin(); | ||
91 | 90 | ||
92 | exit(sig); | 91 | flush_stdin(); |
92 | exit(128 + sig); | ||
93 | } | 93 | } |
94 | 94 | ||
95 | static void install_handler(void) { | 95 | static void install_handler(void) { |
@@ -1004,10 +1004,12 @@ int sandbox(void* sandbox_arg) { | |||
1004 | // apply the profile file | 1004 | // apply the profile file |
1005 | //**************************** | 1005 | //**************************** |
1006 | // apply all whitelist commands ... | 1006 | // apply all whitelist commands ... |
1007 | EUID_USER(); | ||
1007 | fs_whitelist(); | 1008 | fs_whitelist(); |
1008 | 1009 | ||
1009 | // ... followed by blacklist commands | 1010 | // ... followed by blacklist commands |
1010 | fs_blacklist(); // mkdir and mkfile are processed all over again | 1011 | fs_blacklist(); // mkdir and mkfile are processed all over again |
1012 | EUID_ROOT(); | ||
1011 | 1013 | ||
1012 | //**************************** | 1014 | //**************************** |
1013 | // nosound/no3d/notv/novideo and fix for pulseaudio 7.0 | 1015 | // nosound/no3d/notv/novideo and fix for pulseaudio 7.0 |
@@ -1243,7 +1245,6 @@ int sandbox(void* sandbox_arg) { | |||
1243 | 1245 | ||
1244 | if (app_pid == 0) { | 1246 | if (app_pid == 0) { |
1245 | #ifdef HAVE_APPARMOR | 1247 | #ifdef HAVE_APPARMOR |
1246 | // add apparmor confinement after the execve | ||
1247 | set_apparmor(); | 1248 | set_apparmor(); |
1248 | #endif | 1249 | #endif |
1249 | 1250 | ||
@@ -1258,13 +1259,17 @@ int sandbox(void* sandbox_arg) { | |||
1258 | munmap(set_sandbox_status, 1); | 1259 | munmap(set_sandbox_status, 1); |
1259 | 1260 | ||
1260 | int status = monitor_application(app_pid); // monitor application | 1261 | int status = monitor_application(app_pid); // monitor application |
1261 | flush_stdin(); | ||
1262 | 1262 | ||
1263 | if (WIFEXITED(status)) { | 1263 | if (WIFEXITED(status)) { |
1264 | // if we had a proper exit, return that exit status | 1264 | // if we had a proper exit, return that exit status |
1265 | return WEXITSTATUS(status); | 1265 | status = WEXITSTATUS(status); |
1266 | } else if (WIFSIGNALED(status)) { | ||
1267 | // distinguish fatal signals by adding 128 | ||
1268 | status = 128 + WTERMSIG(status); | ||
1266 | } else { | 1269 | } else { |
1267 | // something else went wrong! | 1270 | status = -1; |
1268 | return -1; | ||
1269 | } | 1271 | } |
1272 | |||
1273 | flush_stdin(); | ||
1274 | return status; | ||
1270 | } | 1275 | } |
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/usage.c b/src/firejail/usage.c index d843c74ae..43f862b9d 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c | |||
@@ -28,7 +28,6 @@ static char *usage_str = | |||
28 | "\n" | 28 | "\n" |
29 | "Options:\n" | 29 | "Options:\n" |
30 | " -- - signal the end of options and disables further option processing.\n" | 30 | " -- - signal the end of options and disables further option processing.\n" |
31 | " --allow=filename - allow file system access.\n" | ||
32 | " --allow-debuggers - allow tools such as strace and gdb inside the sandbox.\n" | 31 | " --allow-debuggers - allow tools such as strace and gdb inside the sandbox.\n" |
33 | " --allusers - all user home directories are visible inside the sandbox.\n" | 32 | " --allusers - all user home directories are visible inside the sandbox.\n" |
34 | " --apparmor - enable AppArmor confinement.\n" | 33 | " --apparmor - enable AppArmor confinement.\n" |
@@ -39,12 +38,13 @@ static char *usage_str = | |||
39 | #endif | 38 | #endif |
40 | " --bind=dirname1,dirname2 - mount-bind dirname1 on top of dirname2.\n" | 39 | " --bind=dirname1,dirname2 - mount-bind dirname1 on top of dirname2.\n" |
41 | " --bind=filename1,filename2 - mount-bind filename1 on top of filename2.\n" | 40 | " --bind=filename1,filename2 - mount-bind filename1 on top of filename2.\n" |
42 | " --build - build a profile for the application.\n" | 41 | " --blacklist=filename - blacklist directory or file.\n" |
43 | " --build=filename - build a profile for the application.\n" | 42 | " --build - build a whitelisted profile for the application.\n" |
43 | " --build=filename - build a whitelisted profile for the application.\n" | ||
44 | " --caps - enable default Linux capabilities filter.\n" | 44 | " --caps - enable default Linux capabilities filter.\n" |
45 | " --caps.drop=all - drop all capabilities.\n" | 45 | " --caps.drop=all - drop all capabilities.\n" |
46 | " --caps.drop=capability,capability - drop capabilities.\n" | 46 | " --caps.drop=capability,capability - blacklist capabilities filter.\n" |
47 | " --caps.keep=capability,capability - allow capabilities.\n" | 47 | " --caps.keep=capability,capability - whitelist capabilities filter.\n" |
48 | " --caps.print=name|pid - print the caps filter.\n" | 48 | " --caps.print=name|pid - print the caps filter.\n" |
49 | #ifdef HAVE_FILE_TRANSFER | 49 | #ifdef HAVE_FILE_TRANSFER |
50 | " --cat=name|pid filename - print content of file from sandbox container.\n" | 50 | " --cat=name|pid filename - print content of file from sandbox container.\n" |
@@ -75,18 +75,17 @@ static char *usage_str = | |||
75 | " --dbus-user.talk=name - allow talking to name on the session DBus.\n" | 75 | " --dbus-user.talk=name - allow talking to name on the session DBus.\n" |
76 | #endif | 76 | #endif |
77 | " --debug - print sandbox debug messages.\n" | 77 | " --debug - print sandbox debug messages.\n" |
78 | " --debug-allow - debug file system access.\n" | 78 | " --debug-blacklists - debug blacklisting.\n" |
79 | " --debug-deny - debug file system access.\n" | ||
80 | " --debug-caps - print all recognized capabilities.\n" | 79 | " --debug-caps - print all recognized capabilities.\n" |
81 | " --debug-errnos - print all recognized error numbers.\n" | 80 | " --debug-errnos - print all recognized error numbers.\n" |
82 | " --debug-private-lib - debug for --private-lib option.\n" | 81 | " --debug-private-lib - debug for --private-lib option.\n" |
83 | " --debug-protocols - print all recognized protocols.\n" | 82 | " --debug-protocols - print all recognized protocols.\n" |
84 | " --debug-syscalls - print all recognized system calls.\n" | 83 | " --debug-syscalls - print all recognized system calls.\n" |
85 | " --debug-syscalls32 - print all recognized 32 bit system calls.\n" | 84 | " --debug-syscalls32 - print all recognized 32 bit system calls.\n" |
85 | " --debug-whitelists - debug whitelisting.\n" | ||
86 | #ifdef HAVE_NETWORK | 86 | #ifdef HAVE_NETWORK |
87 | " --defaultgw=address - configure default gateway.\n" | 87 | " --defaultgw=address - configure default gateway.\n" |
88 | #endif | 88 | #endif |
89 | " --deny=filename - deny access to directory or file.\n" | ||
90 | " --deterministic-exit-code - always exit with first child's status code.\n" | 89 | " --deterministic-exit-code - always exit with first child's status code.\n" |
91 | " --dns=address - set DNS server.\n" | 90 | " --dns=address - set DNS server.\n" |
92 | " --dns.print=name|pid - print DNS configuration.\n" | 91 | " --dns.print=name|pid - print DNS configuration.\n" |
@@ -147,14 +146,13 @@ static char *usage_str = | |||
147 | " --netfilter6=filename - enable IPv6 firewall.\n" | 146 | " --netfilter6=filename - enable IPv6 firewall.\n" |
148 | " --netfilter6.print=name|pid - print the IPv6 firewall.\n" | 147 | " --netfilter6.print=name|pid - print the IPv6 firewall.\n" |
149 | " --netmask=address - define a network mask when dealing with unconfigured\n" | 148 | " --netmask=address - define a network mask when dealing with unconfigured\n" |
150 | "\tparrent interfaces.\n" | 149 | "\tparent interfaces.\n" |
151 | " --netns=name - Run the program in a named, persistent network namespace.\n" | 150 | " --netns=name - Run the program in a named, persistent network namespace.\n" |
152 | " --netstats - monitor network statistics.\n" | 151 | " --netstats - monitor network statistics.\n" |
153 | #endif | 152 | #endif |
154 | " --nice=value - set nice value.\n" | 153 | " --nice=value - set nice value.\n" |
155 | " --no3d - disable 3D hardware acceleration.\n" | 154 | " --no3d - disable 3D hardware acceleration.\n" |
156 | " --noallow=filename - disable allow command for file or directory.\n" | 155 | " --noblacklist=filename - disable blacklist for file or directory.\n" |
157 | " --nodeny=filename - disable deny command for file or directory.\n" | ||
158 | " --nodbus - disable D-Bus access.\n" | 156 | " --nodbus - disable D-Bus access.\n" |
159 | " --nodvd - disable DVD and audio CD devices.\n" | 157 | " --nodvd - disable DVD and audio CD devices.\n" |
160 | " --noexec=filename - remount the file or directory noexec nosuid and nodev.\n" | 158 | " --noexec=filename - remount the file or directory noexec nosuid and nodev.\n" |
@@ -169,6 +167,7 @@ static char *usage_str = | |||
169 | " --noautopulse - disable automatic ~/.config/pulse init.\n" | 167 | " --noautopulse - disable automatic ~/.config/pulse init.\n" |
170 | " --novideo - disable video devices.\n" | 168 | " --novideo - disable video devices.\n" |
171 | " --nou2f - disable U2F devices.\n" | 169 | " --nou2f - disable U2F devices.\n" |
170 | " --nowhitelist=filename - disable whitelist for file or directory.\n" | ||
172 | #ifdef HAVE_OUTPUT | 171 | #ifdef HAVE_OUTPUT |
173 | " --output=logfile - stdout logging and log rotation.\n" | 172 | " --output=logfile - stdout logging and log rotation.\n" |
174 | " --output-stderr=logfile - stdout and stderr logging and log rotation.\n" | 173 | " --output-stderr=logfile - stdout and stderr logging and log rotation.\n" |
@@ -225,14 +224,14 @@ static char *usage_str = | |||
225 | #ifdef HAVE_NETWORK | 224 | #ifdef HAVE_NETWORK |
226 | " --scan - ARP-scan all the networks from inside a network namespace.\n" | 225 | " --scan - ARP-scan all the networks from inside a network namespace.\n" |
227 | #endif | 226 | #endif |
228 | " --seccomp - enable seccomp filter and drop the default syscalls.\n" | 227 | " --seccomp - enable seccomp filter and apply the default blacklist.\n" |
229 | " --seccomp=syscall,syscall,syscall - enable seccomp filter, drop the\n" | 228 | " --seccomp=syscall,syscall,syscall - enable seccomp filter, blacklist the\n" |
230 | "\tdefault syscall list and the syscalls specified by the command.\n" | 229 | "\tdefault syscall list and the syscalls specified by the command.\n" |
231 | " --seccomp.block-secondary - build only the native architecture filters.\n" | 230 | " --seccomp.block-secondary - build only the native architecture filters.\n" |
232 | " --seccomp.drop=syscall,syscall,syscall - enable seccomp filter, and\n" | 231 | " --seccomp.drop=syscall,syscall,syscall - enable seccomp filter, and\n" |
233 | "\tdrop the syscalls specified by the command.\n" | 232 | "\tblacklist the syscalls specified by the command.\n" |
234 | " --seccomp.keep=syscall,syscall,syscall - enable seccomp filter, and\n" | 233 | " --seccomp.keep=syscall,syscall,syscall - enable seccomp filter, and\n" |
235 | "\tallow the syscalls specified by the command.\n" | 234 | "\twhitelist the syscalls specified by the command.\n" |
236 | " --seccomp.print=name|pid - print the seccomp filter for the sandbox\n" | 235 | " --seccomp.print=name|pid - print the seccomp filter for the sandbox\n" |
237 | "\tidentified by name or PID.\n" | 236 | "\tidentified by name or PID.\n" |
238 | " --seccomp.32[.drop,.keep][=syscall] - like above but for 32 bit architecture.\n" | 237 | " --seccomp.32[.drop,.keep][=syscall] - like above but for 32 bit architecture.\n" |
@@ -247,7 +246,7 @@ static char *usage_str = | |||
247 | " --top - monitor the most CPU-intensive sandboxes.\n" | 246 | " --top - monitor the most CPU-intensive sandboxes.\n" |
248 | " --trace - trace open, access and connect system calls.\n" | 247 | " --trace - trace open, access and connect system calls.\n" |
249 | " --tracelog - add a syslog message for every access to files or\n" | 248 | " --tracelog - add a syslog message for every access to files or\n" |
250 | "\tdirectories dropped by the security profile.\n" | 249 | "\tdirectories blacklisted by the security profile.\n" |
251 | " --tree - print a tree of all sandboxed processes.\n" | 250 | " --tree - print a tree of all sandboxed processes.\n" |
252 | " --tunnel[=devname] - connect the sandbox to a tunnel created by\n" | 251 | " --tunnel[=devname] - connect the sandbox to a tunnel created by\n" |
253 | "\tfiretunnel utility.\n" | 252 | "\tfiretunnel utility.\n" |
@@ -255,6 +254,7 @@ static char *usage_str = | |||
255 | #ifdef HAVE_NETWORK | 254 | #ifdef HAVE_NETWORK |
256 | " --veth-name=name - use this name for the interface connected to the bridge.\n" | 255 | " --veth-name=name - use this name for the interface connected to the bridge.\n" |
257 | #endif | 256 | #endif |
257 | " --whitelist=filename - whitelist directory or file.\n" | ||
258 | " --writable-etc - /etc directory is mounted read-write.\n" | 258 | " --writable-etc - /etc directory is mounted read-write.\n" |
259 | " --writable-run-user - allow access to /run/user/$UID/systemd and\n" | 259 | " --writable-run-user - allow access to /run/user/$UID/systemd and\n" |
260 | "\t/run/user/$UID/gnupg.\n" | 260 | "\t/run/user/$UID/gnupg.\n" |
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/jailcheck/jailcheck.h b/src/jailcheck/jailcheck.h index be3104da3..3f8c89bfb 100644 --- a/src/jailcheck/jailcheck.h +++ b/src/jailcheck/jailcheck.h | |||
@@ -61,4 +61,4 @@ char *get_homedir(const char *user, uid_t *uid, gid_t *gid); | |||
61 | int find_child(pid_t pid); | 61 | int find_child(pid_t pid); |
62 | pid_t switch_to_child(pid_t pid); | 62 | pid_t switch_to_child(pid_t pid); |
63 | 63 | ||
64 | #endif \ No newline at end of file | 64 | #endif |
diff --git a/src/jailcheck/noexec.c b/src/jailcheck/noexec.c index 7f994d6a1..be18ac109 100644 --- a/src/jailcheck/noexec.c +++ b/src/jailcheck/noexec.c | |||
@@ -110,4 +110,4 @@ void noexec_test(const char *path) { | |||
110 | wait(&status); | 110 | wait(&status); |
111 | int rv = unlink(fname); | 111 | int rv = unlink(fname); |
112 | (void) rv; | 112 | (void) rv; |
113 | } \ No newline at end of file | 113 | } |
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index 6280026e6..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 | |||
78 | Several command line options can be passed to the program using | 78 | Several command line options can be passed to the program using |
79 | profile files. Firejail chooses the profile file as follows: | 79 | profile 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. |
82 | Example: | 82 | Example: |
83 | .PP | 83 | .PP |
84 | .RS | 84 | .RS |
@@ -156,7 +156,7 @@ Scripting commands: | |||
156 | \fBFile and directory names | 156 | \fBFile and directory names |
157 | File and directory names containing spaces are supported. The space character ' ' should not be escaped. | 157 | File and directory names containing spaces are supported. The space character ' ' should not be escaped. |
158 | 158 | ||
159 | Example: "deny ~/My Virtual Machines" | 159 | Example: "blacklist ~/My Virtual Machines" |
160 | 160 | ||
161 | .TP | 161 | .TP |
162 | \fB# this is a comment | 162 | \fB# this is a comment |
@@ -170,11 +170,11 @@ net none # this command creates an empty network namespace | |||
170 | \fB?CONDITIONAL: profile line | 170 | \fB?CONDITIONAL: profile line |
171 | Conditionally add profile line. | 171 | Conditionally add profile line. |
172 | 172 | ||
173 | Example: "?HAS_APPIMAGE: allow ${HOME}/special/appimage/dir" | 173 | Example: "?HAS_APPIMAGE: whitelist ${HOME}/special/appimage/dir" |
174 | 174 | ||
175 | This example will load the profile line only if the \-\-appimage option has been specified on the command line. | 175 | This example will load the whitelist profile line only if the \-\-appimage option has been specified on the command line. |
176 | 176 | ||
177 | Currently 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 | 177 | Currently 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 |
178 | can be enabled or disabled globally in Firejail's configuration file. | 178 | can be enabled or disabled globally in Firejail's configuration file. |
179 | 179 | ||
180 | The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines. | 180 | The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines. |
@@ -205,16 +205,16 @@ storing modifications to the persistent configuration. Persistent .local files | |||
205 | are included at the start of regular profile files. | 205 | are included at the start of regular profile files. |
206 | 206 | ||
207 | .TP | 207 | .TP |
208 | \fBnoallow file_name | 208 | \fBnoblacklist file_name |
209 | If the file name matches file_name, the file will not be allowed in any allow commands that follow. | 209 | If the file name matches file_name, the file will not be blacklisted in any blacklist commands that follow. |
210 | 210 | ||
211 | Example: "nowhitelist ~/.config" | 211 | Example: "noblacklist ${HOME}/.mozilla" |
212 | 212 | ||
213 | .TP | 213 | .TP |
214 | \fBnodeny file_name | 214 | \fBnowhitelist file_name |
215 | If the file name matches file_name, the file will not be denied any deny commands that follow. | 215 | If the file name matches file_name, the file will not be whitelisted in any whitelist commands that follow. |
216 | 216 | ||
217 | Example: "nodeny ${HOME}/.mozilla" | 217 | Example: "nowhitelist ~/.config" |
218 | 218 | ||
219 | .TP | 219 | .TP |
220 | \fBignore | 220 | \fBignore |
@@ -242,17 +242,19 @@ HOME directories are searched, see the \fBfirejail\f(1) \fBFILE GLOBBING\fR sect | |||
242 | for more details. | 242 | for more details. |
243 | Examples: | 243 | Examples: |
244 | .TP | 244 | .TP |
245 | \fBallow file_or_directory | 245 | \fBblacklist file_or_directory |
246 | Allow directory or file. A temporary file system is mounted on the top directory, and the | 246 | Blacklist directory or file. Examples: |
247 | allowed files are mount-binded inside. Modifications to allowd files are persistent, | ||
248 | everything else is discarded when the sandbox is closed. The top directory can be | ||
249 | all directories in / (except /proc and /sys), /sys/module, /run/user/$UID, $HOME and | ||
250 | all directories in /usr. | ||
251 | .br | 247 | .br |
252 | 248 | ||
253 | .br | 249 | .br |
254 | Symbolic link handling: with the exception of user home, both the link and the real file should be in | 250 | blacklist /usr/bin |
255 | the same top directory. For user home, both the link and the real file should be owned by the user. | 251 | .br |
252 | blacklist /usr/bin/gcc* | ||
253 | .br | ||
254 | blacklist ${PATH}/ifconfig | ||
255 | .br | ||
256 | blacklist ${HOME}/.ssh | ||
257 | |||
256 | .TP | 258 | .TP |
257 | \fBblacklist-nolog file_or_directory | 259 | \fBblacklist-nolog file_or_directory |
258 | When --tracelog flag is set, blacklisting generates syslog messages if the sandbox tries to access the file or directory. | 260 | When --tracelog flag is set, blacklisting generates syslog messages if the sandbox tries to access the file or directory. |
@@ -271,20 +273,6 @@ Mount-bind directory1 on top of directory2. This option is only available when r | |||
271 | \fBbind file1,file2 | 273 | \fBbind file1,file2 |
272 | Mount-bind file1 on top of file2. This option is only available when running as root. | 274 | Mount-bind file1 on top of file2. This option is only available when running as root. |
273 | .TP | 275 | .TP |
274 | \fBdeny file_or_directory | ||
275 | Deny access to directory or file. Examples: | ||
276 | .br | ||
277 | |||
278 | .br | ||
279 | deny /usr/bin | ||
280 | .br | ||
281 | deny /usr/bin/gcc* | ||
282 | .br | ||
283 | deny ${PATH}/ifconfig | ||
284 | .br | ||
285 | deny ${HOME}/.ssh | ||
286 | |||
287 | .TP | ||
288 | \fBdisable-mnt | 276 | \fBdisable-mnt |
289 | Disable /mnt, /media, /run/mount and /run/media access. | 277 | Disable /mnt, /media, /run/mount and /run/media access. |
290 | .TP | 278 | .TP |
@@ -304,7 +292,7 @@ The directory is created if it doesn't already exist. | |||
304 | .br | 292 | .br |
305 | 293 | ||
306 | .br | 294 | .br |
307 | Use this command for allowed directories you need to preserve | 295 | Use this command for whitelisted directories you need to preserve |
308 | when the sandbox is closed. Without it, the application will create the directory, and the directory | 296 | when the sandbox is closed. Without it, the application will create the directory, and the directory |
309 | will be deleted when the sandbox is closed. Subdirectories are recursively created. Example from | 297 | will be deleted when the sandbox is closed. Subdirectories are recursively created. Example from |
310 | firefox profile: | 298 | firefox profile: |
@@ -317,7 +305,7 @@ whitelist ~/.mozilla | |||
317 | .br | 305 | .br |
318 | mkdir ~/.cache/mozilla/firefox | 306 | mkdir ~/.cache/mozilla/firefox |
319 | .br | 307 | .br |
320 | allow ~/.cache/mozilla/firefox | 308 | whitelist ~/.cache/mozilla/firefox |
321 | .br | 309 | .br |
322 | 310 | ||
323 | .br | 311 | .br |
@@ -336,16 +324,16 @@ Remount the file or the directory noexec, nodev and nosuid. | |||
336 | #ifdef HAVE_OVERLAYFS | 324 | #ifdef HAVE_OVERLAYFS |
337 | .TP | 325 | .TP |
338 | \fBoverlay | 326 | \fBoverlay |
339 | Mount a filesystem overlay on top of the current filesystem. | 327 | Mount a filesystem overlay on top of the current filesystem. |
340 | The overlay is stored in $HOME/.firejail/<PID> directory. | 328 | The overlay is stored in $HOME/.firejail/<PID> directory. |
341 | .TP | 329 | .TP |
342 | \fBoverlay-named name | 330 | \fBoverlay-named name |
343 | Mount a filesystem overlay on top of the current filesystem. | 331 | Mount a filesystem overlay on top of the current filesystem. |
344 | The overlay is stored in $HOME/.firejail/name directory. | 332 | The overlay is stored in $HOME/.firejail/name directory. |
345 | .TP | 333 | .TP |
346 | \fBoverlay-tmpfs | 334 | \fBoverlay-tmpfs |
347 | Mount a filesystem overlay on top of the current filesystem. | 335 | Mount a filesystem overlay on top of the current filesystem. |
348 | All filesystem modifications are discarded when the sandbox is closed. | 336 | All filesystem modifications are discarded when the sandbox is closed. |
349 | #endif | 337 | #endif |
350 | .TP | 338 | .TP |
351 | \fBprivate | 339 | \fBprivate |
@@ -423,7 +411,7 @@ expressed as foo/bar -- is disallowed). | |||
423 | All modifications are discarded when the sandbox is closed. | 411 | All modifications are discarded when the sandbox is closed. |
424 | .TP | 412 | .TP |
425 | \fBprivate-tmp | 413 | \fBprivate-tmp |
426 | Mount an empty temporary filesystem on top of /tmp directory allowing /tmp/.X11-unix. | 414 | Mount an empty temporary filesystem on top of /tmp directory whitelisting /tmp/.X11-unix. |
427 | .TP | 415 | .TP |
428 | \fBread-only file_or_directory | 416 | \fBread-only file_or_directory |
429 | Make directory or file read-only. | 417 | Make directory or file read-only. |
@@ -435,13 +423,25 @@ Make directory or file read-write. | |||
435 | Mount an empty tmpfs filesystem on top of directory. Directories outside user home or not owned by the user are not allowed. Sandboxes running as root are exempt from these restrictions. | 423 | Mount an empty tmpfs filesystem on top of directory. Directories outside user home or not owned by the user are not allowed. Sandboxes running as root are exempt from these restrictions. |
436 | .TP | 424 | .TP |
437 | \fBtracelog | 425 | \fBtracelog |
438 | File system deny violations logged to syslog. | 426 | Blacklist violations logged to syslog. |
427 | .TP | ||
428 | \fBwhitelist file_or_directory | ||
429 | Whitelist directory or file. A temporary file system is mounted on the top directory, and the | ||
430 | whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent, | ||
431 | everything else is discarded when the sandbox is closed. The top directory can be | ||
432 | all directories in / (except /proc and /sys), /sys/module, /run/user/$UID, $HOME and | ||
433 | all directories in /usr. | ||
434 | .br | ||
435 | |||
436 | .br | ||
437 | Symbolic link handling: with the exception of user home, both the link and the real file should be in | ||
438 | the same top directory. For user home, both the link and the real file should be owned by the user. | ||
439 | .TP | 439 | .TP |
440 | \fBwritable-etc | 440 | \fBwritable-etc |
441 | Mount /etc directory read-write. | 441 | Mount /etc directory read-write. |
442 | .TP | 442 | .TP |
443 | \fBwritable-run-user | 443 | \fBwritable-run-user |
444 | Disable the default denying of run/user/$UID/systemd and /run/user/$UID/gnupg. | 444 | Disable the default blacklisting of run/user/$UID/systemd and /run/user/$UID/gnupg. |
445 | .TP | 445 | .TP |
446 | \fBwritable-var | 446 | \fBwritable-var |
447 | Mount /var directory read-write. | 447 | Mount /var directory read-write. |
@@ -455,7 +455,7 @@ The following security filters are currently implemented: | |||
455 | 455 | ||
456 | .TP | 456 | .TP |
457 | \fBallow-debuggers | 457 | \fBallow-debuggers |
458 | Allow tools such as strace and gdb inside the sandbox by allowing system calls ptrace and process_vm_readv. | 458 | Allow tools such as strace and gdb inside the sandbox by whitelisting system calls ptrace and process_vm_readv. |
459 | #ifdef HAVE_APPARMOR | 459 | #ifdef HAVE_APPARMOR |
460 | .TP | 460 | .TP |
461 | \fBapparmor | 461 | \fBapparmor |
@@ -466,13 +466,13 @@ Enable AppArmor confinement. | |||
466 | Enable default Linux capabilities filter. | 466 | Enable default Linux capabilities filter. |
467 | .TP | 467 | .TP |
468 | \fBcaps.drop capability,capability,capability | 468 | \fBcaps.drop capability,capability,capability |
469 | Deny given Linux capabilities. | 469 | Blacklist given Linux capabilities. |
470 | .TP | 470 | .TP |
471 | \fBcaps.drop all | 471 | \fBcaps.drop all |
472 | Deny all Linux capabilities. | 472 | Blacklist all Linux capabilities. |
473 | .TP | 473 | .TP |
474 | \fBcaps.keep capability,capability,capability | 474 | \fBcaps.keep capability,capability,capability |
475 | Allow given Linux capabilities. | 475 | Whitelist given Linux capabilities. |
476 | .TP | 476 | .TP |
477 | \fBmemory-deny-write-execute | 477 | \fBmemory-deny-write-execute |
478 | Install a seccomp filter to block attempts to create memory mappings | 478 | Install a seccomp filter to block attempts to create memory mappings |
@@ -487,42 +487,42 @@ does not result in an increase of privilege. | |||
487 | #ifdef HAVE_USERNS | 487 | #ifdef HAVE_USERNS |
488 | .TP | 488 | .TP |
489 | \fBnoroot | 489 | \fBnoroot |
490 | Use this command to enable an user namespace. The namespace has only one user, the current user. | 490 | Use this command to enable an user namespace. The namespace has only one user, the current user. |
491 | There is no root account (uid 0) defined in the namespace. | 491 | There 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 |
495 | Enable protocol filter. The filter is based on seccomp and checks the | 495 | Enable protocol filter. The filter is based on seccomp and checks the |
496 | first argument to socket system call. Recognized values: \fBunix\fR, | 496 | first 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 |
499 | \fBseccomp | 499 | \fBseccomp |
500 | Enable seccomp filter and deny the syscalls in the default list. See man 1 firejail for more details. | 500 | Enable seccomp filter and blacklist the syscalls in the default list. See man 1 firejail for more details. |
501 | .TP | 501 | .TP |
502 | \fBseccomp.32 | 502 | \fBseccomp.32 |
503 | Enable seccomp filter and deny the syscalls in the default list for 32 bit system calls on a 64 bit architecture system. | 503 | Enable seccomp filter and blacklist the syscalls in the default list for 32 bit system calls on a 64 bit architecture system. |
504 | .TP | 504 | .TP |
505 | \fBseccomp syscall,syscall,syscall | 505 | \fBseccomp syscall,syscall,syscall |
506 | Enable seccomp filter and deny the system calls in the list on top of default seccomp filter. | 506 | Enable seccomp filter and blacklist the system calls in the list on top of default seccomp filter. |
507 | .TP | 507 | .TP |
508 | \fBseccomp.32 syscall,syscall,syscall | 508 | \fBseccomp.32 syscall,syscall,syscall |
509 | Enable seccomp filter and deny the system calls in the list on top of default seccomp filter for 32 bit system calls on a 64 bit architecture system. | 509 | Enable seccomp filter and blacklist the system calls in the list on top of default seccomp filter for 32 bit system calls on a 64 bit architecture system. |
510 | .TP | 510 | .TP |
511 | \fBseccomp.block-secondary | 511 | \fBseccomp.block-secondary |
512 | Enable seccomp filter and filter system call architectures | 512 | Enable seccomp filter and filter system call architectures |
513 | so that only the native architecture is allowed. | 513 | so that only the native architecture is allowed. |
514 | .TP | 514 | .TP |
515 | \fBseccomp.drop syscall,syscall,syscall | 515 | \fBseccomp.drop syscall,syscall,syscall |
516 | Enable seccomp filter and deny the system calls in the list. | 516 | Enable seccomp filter and blacklist the system calls in the list. |
517 | .TP | 517 | .TP |
518 | \fBseccomp.32.drop syscall,syscall,syscall | 518 | \fBseccomp.32.drop syscall,syscall,syscall |
519 | Enable seccomp filter and deny the system calls in the list for 32 bit system calls on a 64 bit architecture system. | 519 | Enable seccomp filter and blacklist the system calls in the list for 32 bit system calls on a 64 bit architecture system. |
520 | .TP | 520 | .TP |
521 | \fBseccomp.keep syscall,syscall,syscall | 521 | \fBseccomp.keep syscall,syscall,syscall |
522 | Enable seccomp filter and allow the system calls in the list. | 522 | Enable seccomp filter and whitelist the system calls in the list. |
523 | .TP | 523 | .TP |
524 | \fBseccomp.32.keep syscall,syscall,syscall | 524 | \fBseccomp.32.keep syscall,syscall,syscall |
525 | Enable seccomp filter and allow the system calls in the list for 32 bit system calls on a 64 bit architecture system. | 525 | Enable seccomp filter and whitelist the system calls in the list for 32 bit system calls on a 64 bit architecture system. |
526 | .TP | 526 | .TP |
527 | \fBseccomp-error-action kill | log | ERRNO | 527 | \fBseccomp-error-action kill | log | ERRNO |
528 | Return a different error instead of EPERM to the process, kill it when | 528 | Return a different error instead of EPERM to the process, kill it when |
@@ -534,7 +534,7 @@ attempt. | |||
534 | Enable X11 sandboxing. | 534 | Enable X11 sandboxing. |
535 | .TP | 535 | .TP |
536 | \fBx11 none | 536 | \fBx11 none |
537 | Deny access to /tmp/.X11-unix directory, ${HOME}/.Xauthority and file specified in ${XAUTHORITY} environment variable. | 537 | Blacklist /tmp/.X11-unix directory, ${HOME}/.Xauthority and file specified in ${XAUTHORITY} environment variable. |
538 | Remove DISPLAY and XAUTHORITY environment variables. | 538 | Remove DISPLAY and XAUTHORITY environment variables. |
539 | Stop with error message if X11 abstract socket will be accessible in jail. | 539 | Stop with error message if X11 abstract socket will be accessible in jail. |
540 | .TP | 540 | .TP |
@@ -606,7 +606,7 @@ Allow the application to see but not talk to the name org.freedesktop.Notificati | |||
606 | Allow the application to call methods of the interface org.freedesktop.Notifications of the object exposed at the path /org/freedesktop/Notifications by the client owning the bus name org.freedesktop.Notifications on the system DBus. | 606 | Allow the application to call methods of the interface org.freedesktop.Notifications of the object exposed at the path /org/freedesktop/Notifications by the client owning the bus name org.freedesktop.Notifications on the system DBus. |
607 | .TP | 607 | .TP |
608 | \fBdbus-system.broadcast org.freedesktop.Notifications=org.freedesktop.Notifications.*@/org/freedesktop/Notifications | 608 | \fBdbus-system.broadcast org.freedesktop.Notifications=org.freedesktop.Notifications.*@/org/freedesktop/Notifications |
609 | Allow the application to receive broadcast signals from the the interface org.freedesktop.Notifications of the object exposed at the path /org/freedesktop/Notifications by the client owning the bus name org.freedesktop.Notifications on the system DBus. | 609 | Allow the application to receive broadcast signals from the interface org.freedesktop.Notifications of the object exposed at the path /org/freedesktop/Notifications by the client owning the bus name org.freedesktop.Notifications on the system DBus. |
610 | .TP | 610 | .TP |
611 | \fBdbus-user filter | 611 | \fBdbus-user filter |
612 | Enable filtered access to the session DBus. Filters can be specified with the dbus-user.talk and dbus-user.own commands. | 612 | Enable filtered access to the session DBus. Filters can be specified with the dbus-user.talk and dbus-user.own commands. |
@@ -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 |
876 | Assign an IP address in the provided range to the last network | 876 | Assign an IP address in the provided range to the last network |
877 | interface defined by a net command. A default gateway is assigned by default. | 877 | interface 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 498ff9aa9..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 |
46 | This is Firejail long-term support (LTS), an enterprise focused version of the software, | 46 | This is Firejail long-term support (LTS), an enterprise focused version of the software, |
47 | LTS is usually supported for two or three years. | 47 | LTS is usually supported for two or three years. |
48 | During this time only bugs and the occasional documentation problems are fixed. | 48 | During this time only bugs and the occasional documentation problems are fixed. |
49 | The attack surface of the SUID executable was greatly reduced by removing some of the features. | 49 | The attack surface of the SUID executable was greatly reduced by removing some of the features. |
50 | .br | 50 | .br |
51 | 51 | ||
@@ -99,40 +99,6 @@ $ firejail [OPTIONS] firefox # starting Mozilla Firefox | |||
99 | \fB\-\- | 99 | \fB\-\- |
100 | Signal the end of options and disables further option processing. | 100 | Signal the end of options and disables further option processing. |
101 | .TP | 101 | .TP |
102 | \fB\-\-allow=dirname_or_filename | ||
103 | Allow access to a directory or file. A temporary file system is mounted on the top directory, and the | ||
104 | allowed files are mount-binded inside. Modifications to allowed files are persistent, | ||
105 | everything else is discarded when the sandbox is closed. The top directory can be | ||
106 | all directories in / (except /proc and /sys), /sys/module, /run/user/$UID, $HOME and | ||
107 | all directories in /usr. | ||
108 | .br | ||
109 | |||
110 | .br | ||
111 | Symbolic link handling: with the exception of user home, both the link and the real file should be in | ||
112 | the same top directory. For user home, both the link and the real file should be owned by the user. | ||
113 | .br | ||
114 | |||
115 | .br | ||
116 | File globbing is supported, see \fBFILE GLOBBING\fR section for more details. | ||
117 | .br | ||
118 | |||
119 | .br | ||
120 | Example: | ||
121 | .br | ||
122 | $ firejail \-\-noprofile \-\-allow=~/.mozilla | ||
123 | .br | ||
124 | $ firejail \-\-allow=/tmp/.X11-unix --allow=/dev/null | ||
125 | .br | ||
126 | $ firejail "\-\-allow=/home/username/My Virtual Machines" | ||
127 | .br | ||
128 | $ firejail \-\-allow=~/work* \-\-allow=/var/backups* | ||
129 | |||
130 | |||
131 | |||
132 | |||
133 | |||
134 | |||
135 | .TP | ||
136 | \fB\-\-allow-debuggers | 102 | \fB\-\-allow-debuggers |
137 | Allow tools such as strace and gdb inside the sandbox by whitelisting | 103 | Allow tools such as strace and gdb inside the sandbox by whitelisting |
138 | system calls ptrace and process_vm_readv. This option is only | 104 | system calls ptrace and process_vm_readv. This option is only |
@@ -143,7 +109,7 @@ ptrace system call allows a full bypass of the seccomp filter. | |||
143 | .br | 109 | .br |
144 | Example: | 110 | Example: |
145 | .br | 111 | .br |
146 | $ firejail --allow-debuggers --profile=/etc/firejail/firefox.profile strace -f firefox | 112 | $ firejail --allow-debuggers --profile=/etc/firejail/firefox.profile strace -f firefox |
147 | .TP | 113 | .TP |
148 | \fB\-\-allusers | 114 | \fB\-\-allusers |
149 | All directories under /home are visible inside the sandbox. By default, only current user home directory is visible. | 115 | All directories under /home are visible inside the sandbox. By default, only current user home directory is visible. |
@@ -203,6 +169,21 @@ Example: | |||
203 | .br | 169 | .br |
204 | # firejail \-\-bind=/config/etc/passwd,/etc/passwd | 170 | # firejail \-\-bind=/config/etc/passwd,/etc/passwd |
205 | .TP | 171 | .TP |
172 | \fB\-\-blacklist=dirname_or_filename | ||
173 | Blacklist directory or file. File globbing is supported, see \fBFILE GLOBBING\fR section for more details. | ||
174 | .br | ||
175 | |||
176 | .br | ||
177 | Example: | ||
178 | .br | ||
179 | $ firejail \-\-blacklist=/sbin \-\-blacklist=/usr/sbin | ||
180 | .br | ||
181 | $ firejail \-\-blacklist=~/.mozilla | ||
182 | .br | ||
183 | $ firejail "\-\-blacklist=/home/username/My Virtual Machines" | ||
184 | .br | ||
185 | $ firejail \-\-blacklist=/home/username/My\\ Virtual\\ Machines | ||
186 | .TP | ||
206 | \fB\-\-build | 187 | \fB\-\-build |
207 | The command builds a whitelisted profile. The profile is printed on the screen. If /usr/bin/strace is installed on the system, it also | 188 | The command builds a whitelisted profile. The profile is printed on the screen. If /usr/bin/strace is installed on the system, it also |
208 | builds a whitelisted seccomp profile. The program is run in a very relaxed sandbox, | 189 | builds a whitelisted seccomp profile. The program is run in a very relaxed sandbox, |
@@ -262,7 +243,7 @@ $ firejail \-\-caps.drop=all warzone2100 | |||
262 | 243 | ||
263 | .TP | 244 | .TP |
264 | \fB\-\-caps.drop=capability,capability,capability | 245 | \fB\-\-caps.drop=capability,capability,capability |
265 | Define a custom Linux capabilities filter. | 246 | Define a custom blacklist Linux capabilities filter. |
266 | .br | 247 | .br |
267 | 248 | ||
268 | .br | 249 | .br |
@@ -643,14 +624,14 @@ Example: | |||
643 | $ firejail \-\-debug firefox | 624 | $ firejail \-\-debug firefox |
644 | 625 | ||
645 | .TP | 626 | .TP |
646 | \fB\-\-debug-allow\fR | 627 | \fB\-\-debug-blacklists\fR |
647 | Debug file system access. | 628 | Debug blacklisting. |
648 | .br | 629 | .br |
649 | 630 | ||
650 | .br | 631 | .br |
651 | Example: | 632 | Example: |
652 | .br | 633 | .br |
653 | $ firejail \-\-debug-allow firefox | 634 | $ firejail \-\-debug-blacklists firefox |
654 | 635 | ||
655 | .TP | 636 | .TP |
656 | \fB\-\-debug-caps | 637 | \fB\-\-debug-caps |
@@ -663,16 +644,6 @@ Example: | |||
663 | $ firejail \-\-debug-caps | 644 | $ firejail \-\-debug-caps |
664 | 645 | ||
665 | .TP | 646 | .TP |
666 | \fB\-\-debug-deny\fR | ||
667 | Debug file access. | ||
668 | .br | ||
669 | |||
670 | .br | ||
671 | Example: | ||
672 | .br | ||
673 | $ firejail \-\-debug-deny firefox | ||
674 | |||
675 | .TP | ||
676 | \fB\-\-debug-errnos | 647 | \fB\-\-debug-errnos |
677 | Print all recognized error numbers in the current Firejail software build and exit. | 648 | Print all recognized error numbers in the current Firejail software build and exit. |
678 | .br | 649 | .br |
@@ -706,44 +677,33 @@ $ firejail \-\-debug-syscalls | |||
706 | \fB\-\-debug-syscalls32 | 677 | \fB\-\-debug-syscalls32 |
707 | Print all recognized 32 bit system calls in the current Firejail software build and exit. | 678 | Print all recognized 32 bit system calls in the current Firejail software build and exit. |
708 | .br | 679 | .br |
709 | |||
710 | #ifdef HAVE_NETWORK | ||
711 | .TP | 680 | .TP |
712 | \fB\-\-defaultgw=address | 681 | \fB\-\-debug-whitelists\fR |
713 | Use this address as default gateway in the new network namespace. | 682 | Debug whitelisting. |
714 | .br | 683 | .br |
715 | 684 | ||
716 | .br | 685 | .br |
717 | Example: | 686 | Example: |
718 | .br | 687 | .br |
719 | $ firejail \-\-net=eth0 \-\-defaultgw=10.10.20.1 firefox | 688 | $ firejail \-\-debug-whitelists firefox |
720 | #endif | 689 | #ifdef HAVE_NETWORK |
721 | |||
722 | .TP | 690 | .TP |
723 | \fB\-\-deny=dirname_or_filename | 691 | \fB\-\-defaultgw=address |
724 | Deny access to directory or file. File globbing is supported, see \fBFILE GLOBBING\fR section for more details. | 692 | Use this address as default gateway in the new network namespace. |
725 | .br | 693 | .br |
726 | 694 | ||
727 | .br | 695 | .br |
728 | Example: | 696 | Example: |
729 | .br | 697 | .br |
730 | $ firejail \-\-deny=/sbin \-\-deny=/usr/sbin | 698 | $ firejail \-\-net=eth0 \-\-defaultgw=10.10.20.1 firefox |
731 | .br | 699 | #endif |
732 | $ firejail \-\-deny=~/.mozilla | ||
733 | .br | ||
734 | $ firejail "\-\-deny=/home/username/My Virtual Machines" | ||
735 | .br | ||
736 | $ firejail \-\-deny=/home/username/My\\ Virtual\\ Machines | ||
737 | |||
738 | |||
739 | |||
740 | .TP | 700 | .TP |
741 | \fB\-\-deterministic-exit-code | 701 | \fB\-\-deterministic-exit-code |
742 | Always exit firejail with the first child's exit status. The default behavior is to use the exit status of the final child to exit, which can be nondeterministic. | 702 | Always exit firejail with the first child's exit status. The default behavior is to use the exit status of the final child to exit, which can be nondeterministic. |
743 | .br | 703 | .br |
744 | .TP | 704 | .TP |
745 | \fB\-\-disable-mnt | 705 | \fB\-\-disable-mnt |
746 | Deny access to /mnt, /media, /run/mount and /run/media. | 706 | Blacklist /mnt, /media, /run/mount and /run/media access. |
747 | .br | 707 | .br |
748 | 708 | ||
749 | .br | 709 | .br |
@@ -987,7 +947,7 @@ $ firejail \-\-net=eth0 \-\-\iprange=192.168.1.100,192.168.1.150 | |||
987 | 947 | ||
988 | .TP | 948 | .TP |
989 | \fB\-\-ipc-namespace | 949 | \fB\-\-ipc-namespace |
990 | Enable a new IPC namespace if the sandbox was started as a regular user. IPC namespace is enabled by default | 950 | Enable a new IPC namespace if the sandbox was started as a regular user. IPC namespace is enabled by default |
991 | for sandboxes started as root. | 951 | for sandboxes started as root. |
992 | .br | 952 | .br |
993 | 953 | ||
@@ -1054,7 +1014,7 @@ $ sudo firejail --join-network=browser /sbin/iptables -vL | |||
1054 | .br | 1014 | .br |
1055 | 1015 | ||
1056 | .br | 1016 | .br |
1057 | # verify IP addresses | 1017 | # verify IP addresses |
1058 | .br | 1018 | .br |
1059 | $ sudo firejail --join-network=browser ip addr | 1019 | $ sudo firejail --join-network=browser ip addr |
1060 | .br | 1020 | .br |
@@ -1511,16 +1471,12 @@ Example: | |||
1511 | $ firejail --no3d firefox | 1471 | $ firejail --no3d firefox |
1512 | 1472 | ||
1513 | .TP | 1473 | .TP |
1514 | \fB\-\-noallow=dirname_or_filename | ||
1515 | Disable \-\-allow for this directory or file. | ||
1516 | |||
1517 | .TP | ||
1518 | \fB\-\-noautopulse \fR(deprecated) | 1474 | \fB\-\-noautopulse \fR(deprecated) |
1519 | See --keep-config-pulse. | 1475 | See --keep-config-pulse. |
1520 | 1476 | ||
1521 | .TP | 1477 | .TP |
1522 | \fB\-\-nodeny=dirname_or_filename | 1478 | \fB\-\-noblacklist=dirname_or_filename |
1523 | Disable \-\-deny for this directory or file. | 1479 | Disable blacklist for this directory or file. |
1524 | .br | 1480 | .br |
1525 | 1481 | ||
1526 | .br | 1482 | .br |
@@ -1536,7 +1492,7 @@ $ exit | |||
1536 | .br | 1492 | .br |
1537 | 1493 | ||
1538 | .br | 1494 | .br |
1539 | $ firejail --nodeny=/bin/nc | 1495 | $ firejail --noblacklist=/bin/nc |
1540 | .br | 1496 | .br |
1541 | $ nc dict.org 2628 | 1497 | $ nc dict.org 2628 |
1542 | .br | 1498 | .br |
@@ -1710,6 +1666,10 @@ $ firejail \-\-nou2f | |||
1710 | Disable video devices. | 1666 | Disable video devices. |
1711 | .br | 1667 | .br |
1712 | 1668 | ||
1669 | .TP | ||
1670 | \fB\-\-nowhitelist=dirname_or_filename | ||
1671 | Disable whitelist for this directory or file. | ||
1672 | |||
1713 | #ifdef HAVE_OUTPUT | 1673 | #ifdef HAVE_OUTPUT |
1714 | .TP | 1674 | .TP |
1715 | \fB\-\-output=logfile | 1675 | \fB\-\-output=logfile |
@@ -2174,7 +2134,7 @@ Use k(ilobyte), m(egabyte) or g(igabyte) for size suffix (base 1024). | |||
2174 | .TP | 2134 | .TP |
2175 | \fB\-\-rlimit-cpu=number | 2135 | \fB\-\-rlimit-cpu=number |
2176 | Set the maximum limit, in seconds, for the amount of CPU time each | 2136 | Set the maximum limit, in seconds, for the amount of CPU time each |
2177 | sandboxed process can consume. When the limit is reached, the processes are killed. | 2137 | sandboxed process can consume. When the limit is reached, the processes are killed. |
2178 | 2138 | ||
2179 | The CPU limit is a limit on CPU seconds rather than elapsed time. CPU seconds is basically how many seconds | 2139 | The CPU limit is a limit on CPU seconds rather than elapsed time. CPU seconds is basically how many seconds |
2180 | the CPU has been in use and does not necessarily directly relate to the elapsed time. Linux kernel keeps | 2140 | the CPU has been in use and does not necessarily directly relate to the elapsed time. Linux kernel keeps |
@@ -2218,7 +2178,7 @@ $ firejail \-\-net=eth0 \-\-scan | |||
2218 | .TP | 2178 | .TP |
2219 | \fB\-\-seccomp | 2179 | \fB\-\-seccomp |
2220 | Enable seccomp filter and blacklist the syscalls in the default list, | 2180 | Enable seccomp filter and blacklist the syscalls in the default list, |
2221 | which is @default-nodebuggers unless \-\-allow-debuggers is specified, | 2181 | which is @default-nodebuggers unless \-\-allow-debuggers is specified, |
2222 | then it is @default. | 2182 | then it is @default. |
2223 | 2183 | ||
2224 | .br | 2184 | .br |
@@ -2773,6 +2733,34 @@ Example: | |||
2773 | .br | 2733 | .br |
2774 | $ firejail \-\-net=br0 --veth-name=if0 | 2734 | $ firejail \-\-net=br0 --veth-name=if0 |
2775 | #endif | 2735 | #endif |
2736 | .TP | ||
2737 | \fB\-\-whitelist=dirname_or_filename | ||
2738 | Whitelist directory or file. A temporary file system is mounted on the top directory, and the | ||
2739 | whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent, | ||
2740 | everything else is discarded when the sandbox is closed. The top directory can be | ||
2741 | all directories in / (except /proc and /sys), /sys/module, /run/user/$UID, $HOME and | ||
2742 | all directories in /usr. | ||
2743 | .br | ||
2744 | |||
2745 | .br | ||
2746 | Symbolic link handling: with the exception of user home, both the link and the real file should be in | ||
2747 | the same top directory. For user home, both the link and the real file should be owned by the user. | ||
2748 | .br | ||
2749 | |||
2750 | .br | ||
2751 | File globbing is supported, see \fBFILE GLOBBING\fR section for more details. | ||
2752 | .br | ||
2753 | |||
2754 | .br | ||
2755 | Example: | ||
2756 | .br | ||
2757 | $ firejail \-\-noprofile \-\-whitelist=~/.mozilla | ||
2758 | .br | ||
2759 | $ firejail \-\-whitelist=/tmp/.X11-unix --whitelist=/dev/null | ||
2760 | .br | ||
2761 | $ firejail "\-\-whitelist=/home/username/My Virtual Machines" | ||
2762 | .br | ||
2763 | $ firejail \-\-whitelist=~/work* \-\-whitelist=/var/backups* | ||
2776 | 2764 | ||
2777 | .TP | 2765 | .TP |
2778 | \fB\-\-writable-etc | 2766 | \fB\-\-writable-etc |
@@ -2877,7 +2865,7 @@ and it is installed by default on most Linux distributions. It provides support | |||
2877 | connection model. Untrusted clients are restricted in certain ways to prevent them from reading window | 2865 | connection model. Untrusted clients are restricted in certain ways to prevent them from reading window |
2878 | contents of other clients, stealing input events, etc. | 2866 | contents of other clients, stealing input events, etc. |
2879 | 2867 | ||
2880 | The untrusted mode has several limitations. A lot of regular programs assume they are a trusted X11 clients | 2868 | The untrusted mode has several limitations. A lot of regular programs assume they are a trusted X11 clients |
2881 | and will crash or lock up when run in untrusted mode. Chromium browser and xterm are two examples. | 2869 | and will crash or lock up when run in untrusted mode. Chromium browser and xterm are two examples. |
2882 | Firefox and transmission-gtk seem to be working fine. | 2870 | Firefox and transmission-gtk seem to be working fine. |
2883 | A network namespace is not required for this option. | 2871 | A network namespace is not required for this option. |
@@ -3268,7 +3256,7 @@ The owner of the sandbox. | |||
3268 | .SH RESTRICTED SHELL | 3256 | .SH RESTRICTED SHELL |
3269 | To configure a restricted shell, replace /bin/bash with /usr/bin/firejail in | 3257 | To configure a restricted shell, replace /bin/bash with /usr/bin/firejail in |
3270 | /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, |
3271 | you can specify /usr/bin/firejail in adduser command: | 3259 | you can specify /usr/bin/firejail in adduser command: |
3272 | 3260 | ||
3273 | adduser \-\-shell /usr/bin/firejail username | 3261 | adduser \-\-shell /usr/bin/firejail username |
3274 | 3262 | ||
@@ -3278,7 +3266,7 @@ Additional arguments passed to firejail executable upon login are declared in /e | |||
3278 | Several command line options can be passed to the program using | 3266 | Several command line options can be passed to the program using |
3279 | profile files. Firejail chooses the profile file as follows: | 3267 | profile files. Firejail chooses the profile file as follows: |
3280 | 3268 | ||
3281 | 1. 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. | 3269 | 1. 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. |
3282 | Example: | 3270 | Example: |
3283 | .PP | 3271 | .PP |
3284 | .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. | |||
56 | Print seccomp configuration for each sandbox. | 56 | Print seccomp configuration for each sandbox. |
57 | .TP | 57 | .TP |
58 | \fB\-\-top | 58 | \fB\-\-top |
59 | Monitor the most CPU-intensive sandboxes. This command is similar to | 59 | Monitor the most CPU-intensive sandboxes. This command is similar to |
60 | the regular UNIX top command, however it applies only to sandboxes. | 60 | the regular UNIX top command, however it applies only to sandboxes. |
61 | .TP | 61 | .TP |
62 | \fB\-\-tree | 62 | \fB\-\-tree |
diff --git a/src/tools/profcleaner.c b/src/tools/profcleaner.c index 93bb3f73d..beff93199 100644 --- a/src/tools/profcleaner.c +++ b/src/tools/profcleaner.c | |||
@@ -72,4 +72,4 @@ int main(int argc, char **argv) { | |||
72 | } | 72 | } |
73 | 73 | ||
74 | return 0; | 74 | return 0; |
75 | } \ No newline at end of file | 75 | } |
diff --git a/src/zsh_completion/_firejail.in b/src/zsh_completion/_firejail.in index 666dfd4c2..c7f6ee3f1 100644 --- a/src/zsh_completion/_firejail.in +++ b/src/zsh_completion/_firejail.in | |||
@@ -218,7 +218,7 @@ _firejail_args=( | |||
218 | '--netfilter.print=-[print the firewall name|pid]: :_all_firejails' | 218 | '--netfilter.print=-[print the firewall name|pid]: :_all_firejails' |
219 | '--netfilter6=-[enable IPv6 firewall]: :' | 219 | '--netfilter6=-[enable IPv6 firewall]: :' |
220 | '--netfilter6.print=-[print the IPv6 firewall name|pid]: :_all_firejails' | 220 | '--netfilter6.print=-[print the IPv6 firewall name|pid]: :_all_firejails' |
221 | '--netmask=-[define a network mask when dealing with unconfigured parrent interfaces]: :' | 221 | '--netmask=-[define a network mask when dealing with unconfigured parent interfaces]: :' |
222 | '--netns=-[Run the program in a named, persistent network namespace]: :' | 222 | '--netns=-[Run the program in a named, persistent network namespace]: :' |
223 | '--netstats[monitor network statistics]' | 223 | '--netstats[monitor network statistics]' |
224 | '--interface=-[move interface in sandbox]: :' | 224 | '--interface=-[move interface in sandbox]: :' |