diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bash_completion/firejail.bash_completion.in | 8 | ||||
-rw-r--r-- | src/fcopy/main.c | 3 | ||||
-rw-r--r-- | src/firejail/checkcfg.c | 2 | ||||
-rw-r--r-- | src/firejail/firejail.h | 3 | ||||
-rw-r--r-- | src/firejail/fs.c | 50 | ||||
-rw-r--r-- | src/firejail/fs_dev.c | 2 | ||||
-rw-r--r-- | src/firejail/fs_home.c | 11 | ||||
-rw-r--r-- | src/firejail/fs_whitelist.c | 59 | ||||
-rw-r--r-- | src/firejail/mountinfo.c | 71 | ||||
-rw-r--r-- | src/firejail/profile.c | 15 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 2 | ||||
-rw-r--r-- | src/firejail/selinux.c | 21 | ||||
-rw-r--r-- | src/firejail/util.c | 14 | ||||
-rw-r--r-- | src/man/firejail-profile.txt | 24 | ||||
-rw-r--r-- | src/man/firejail.txt | 18 | ||||
-rw-r--r-- | src/man/firemon.txt | 2 |
16 files changed, 167 insertions, 138 deletions
diff --git a/src/bash_completion/firejail.bash_completion.in b/src/bash_completion/firejail.bash_completion.in index f68edf380..ff411c807 100644 --- a/src/bash_completion/firejail.bash_completion.in +++ b/src/bash_completion/firejail.bash_completion.in | |||
@@ -5,7 +5,7 @@ | |||
5 | # http://bash-completion.alioth.debian.org | 5 | # http://bash-completion.alioth.debian.org |
6 | #******************************************************************* | 6 | #******************************************************************* |
7 | 7 | ||
8 | __interfaces(){ | 8 | __interfaces() { |
9 | cut -f 1 -d ':' /proc/net/dev | tail -n +3 | grep -v lo | xargs | 9 | cut -f 1 -d ':' /proc/net/dev | tail -n +3 | grep -v lo | xargs |
10 | } | 10 | } |
11 | 11 | ||
@@ -90,11 +90,11 @@ _firejail() | |||
90 | _filedir | 90 | _filedir |
91 | return 0 | 91 | return 0 |
92 | ;; | 92 | ;; |
93 | --net) | 93 | --net) |
94 | comps=$(__interfaces) | 94 | comps=$(__interfaces) |
95 | COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) | 95 | COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) |
96 | return 0 | 96 | return 0 |
97 | ;; | 97 | ;; |
98 | esac | 98 | esac |
99 | 99 | ||
100 | $split && return 0 | 100 | $split && return 0 |
diff --git a/src/fcopy/main.c b/src/fcopy/main.c index 31810de9a..f279af89f 100644 --- a/src/fcopy/main.c +++ b/src/fcopy/main.c | |||
@@ -88,7 +88,8 @@ static void selinux_relabel_path(const char *path, const char *inside_path) { | |||
88 | if (arg_debug) | 88 | if (arg_debug) |
89 | printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon); | 89 | printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon); |
90 | 90 | ||
91 | setfilecon_raw(procfs_path, fcon); | 91 | if (setfilecon_raw(procfs_path, fcon) != 0 && arg_debug) |
92 | printf("Cannot relabel %s: %s\n", path, strerror(errno)); | ||
92 | } | 93 | } |
93 | freecon(fcon); | 94 | freecon(fcon); |
94 | close: | 95 | close: |
diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c index 06e6f0ccb..e5d837bbb 100644 --- a/src/firejail/checkcfg.c +++ b/src/firejail/checkcfg.c | |||
@@ -58,6 +58,7 @@ int checkcfg(int val) { | |||
58 | cfg_val[CFG_XPRA_ATTACH] = 0; | 58 | cfg_val[CFG_XPRA_ATTACH] = 0; |
59 | cfg_val[CFG_SECCOMP_ERROR_ACTION] = -1; | 59 | cfg_val[CFG_SECCOMP_ERROR_ACTION] = -1; |
60 | cfg_val[CFG_BROWSER_ALLOW_DRM] = 0; | 60 | cfg_val[CFG_BROWSER_ALLOW_DRM] = 0; |
61 | cfg_val[CFG_ALLOW_TRAY] = 0; | ||
61 | 62 | ||
62 | // open configuration file | 63 | // open configuration file |
63 | const char *fname = SYSCONFDIR "/firejail.config"; | 64 | const char *fname = SYSCONFDIR "/firejail.config"; |
@@ -122,6 +123,7 @@ int checkcfg(int val) { | |||
122 | PARSE_YESNO(CFG_XPRA_ATTACH, "xpra-attach") | 123 | PARSE_YESNO(CFG_XPRA_ATTACH, "xpra-attach") |
123 | PARSE_YESNO(CFG_BROWSER_DISABLE_U2F, "browser-disable-u2f") | 124 | PARSE_YESNO(CFG_BROWSER_DISABLE_U2F, "browser-disable-u2f") |
124 | PARSE_YESNO(CFG_BROWSER_ALLOW_DRM, "browser-allow-drm") | 125 | PARSE_YESNO(CFG_BROWSER_ALLOW_DRM, "browser-allow-drm") |
126 | PARSE_YESNO(CFG_ALLOW_TRAY, "allow-tray") | ||
125 | #undef PARSE_YESNO | 127 | #undef PARSE_YESNO |
126 | 128 | ||
127 | // netfilter | 129 | // netfilter |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index bcc7e6ed1..730c37aed 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -563,7 +563,7 @@ typedef struct { | |||
563 | 563 | ||
564 | // mountinfo.c | 564 | // mountinfo.c |
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 |
@@ -802,6 +802,7 @@ enum { | |||
802 | CFG_NAME_CHANGE, | 802 | CFG_NAME_CHANGE, |
803 | CFG_SECCOMP_ERROR_ACTION, | 803 | CFG_SECCOMP_ERROR_ACTION, |
804 | // CFG_FILE_COPY_LIMIT - file copy limit handled using setenv/getenv | 804 | // CFG_FILE_COPY_LIMIT - file copy limit handled using setenv/getenv |
805 | CFG_ALLOW_TRAY, | ||
805 | CFG_MAX // this should always be the last entry | 806 | CFG_MAX // this should always be the last entry |
806 | }; | 807 | }; |
807 | extern char *xephyr_screen; | 808 | extern char *xephyr_screen; |
diff --git a/src/firejail/fs.c b/src/firejail/fs.c index dd4c2139d..3144156a3 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c | |||
@@ -200,8 +200,6 @@ static void disable_file(OPERATION op, const char *filename) { | |||
200 | } | 200 | } |
201 | 201 | ||
202 | fs_tmpfs(fname, uid); | 202 | fs_tmpfs(fname, uid); |
203 | EUID_USER(); // fs_tmpfs returns with EUID 0 | ||
204 | |||
205 | selinux_relabel_path(fname, fname); | 203 | selinux_relabel_path(fname, fname); |
206 | } | 204 | } |
207 | else | 205 | else |
@@ -282,6 +280,8 @@ static void globbing(OPERATION op, const char *pattern, const char *noblacklist[ | |||
282 | 280 | ||
283 | // blacklist files or directories by mounting empty files on top of them | 281 | // blacklist files or directories by mounting empty files on top of them |
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_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/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 059100fcb..5390249ea 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -175,6 +175,10 @@ static int check_allow_drm(void) { | |||
175 | return checkcfg(CFG_BROWSER_ALLOW_DRM) != 0; | 175 | return checkcfg(CFG_BROWSER_ALLOW_DRM) != 0; |
176 | } | 176 | } |
177 | 177 | ||
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"); |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 7a1ce737b..b776a0cc5 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -1007,10 +1007,12 @@ int sandbox(void* sandbox_arg) { | |||
1007 | // apply the profile file | 1007 | // apply the profile file |
1008 | //**************************** | 1008 | //**************************** |
1009 | // apply all whitelist commands ... | 1009 | // apply all whitelist commands ... |
1010 | EUID_USER(); | ||
1010 | fs_whitelist(); | 1011 | fs_whitelist(); |
1011 | 1012 | ||
1012 | // ... followed by blacklist commands | 1013 | // ... followed by blacklist commands |
1013 | fs_blacklist(); // mkdir and mkfile are processed all over again | 1014 | fs_blacklist(); // mkdir and mkfile are processed all over again |
1015 | EUID_ROOT(); | ||
1014 | 1016 | ||
1015 | //**************************** | 1017 | //**************************** |
1016 | // nosound/no3d/notv/novideo and fix for pulseaudio 7.0 | 1018 | // nosound/no3d/notv/novideo and fix for pulseaudio 7.0 |
diff --git a/src/firejail/selinux.c b/src/firejail/selinux.c index 6969e7a3d..fa59882ed 100644 --- a/src/firejail/selinux.c +++ b/src/firejail/selinux.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "firejail.h" | 21 | #include "firejail.h" |
22 | #include <sys/types.h> | 22 | #include <sys/types.h> |
23 | #include <sys/stat.h> | 23 | #include <sys/stat.h> |
24 | #include <errno.h> | ||
24 | 25 | ||
25 | #include <fcntl.h> | 26 | #include <fcntl.h> |
26 | #ifndef O_PATH | 27 | #ifndef O_PATH |
@@ -57,7 +58,17 @@ void selinux_relabel_path(const char *path, const char *inside_path) | |||
57 | 58 | ||
58 | /* Open the file as O_PATH, to pin it while we determine and adjust the label | 59 | /* Open the file as O_PATH, to pin it while we determine and adjust the label |
59 | * Defeat symlink races by not allowing symbolic links */ | 60 | * Defeat symlink races by not allowing symbolic links */ |
61 | int called_as_root = 0; | ||
62 | if (geteuid() == 0) | ||
63 | called_as_root = 1; | ||
64 | if (called_as_root) | ||
65 | EUID_USER(); | ||
66 | |||
60 | fd = safer_openat(-1, path, O_NOFOLLOW|O_CLOEXEC|O_PATH); | 67 | fd = safer_openat(-1, path, O_NOFOLLOW|O_CLOEXEC|O_PATH); |
68 | |||
69 | if (called_as_root) | ||
70 | EUID_ROOT(); | ||
71 | |||
61 | if (fd < 0) | 72 | if (fd < 0) |
62 | return; | 73 | return; |
63 | if (fstat(fd, &st) < 0) | 74 | if (fstat(fd, &st) < 0) |
@@ -68,8 +79,16 @@ void selinux_relabel_path(const char *path, const char *inside_path) | |||
68 | if (arg_debug) | 79 | if (arg_debug) |
69 | printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon); | 80 | printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon); |
70 | 81 | ||
71 | setfilecon_raw(procfs_path, fcon); | 82 | if (!called_as_root) |
83 | EUID_ROOT(); | ||
84 | |||
85 | if (setfilecon_raw(procfs_path, fcon) != 0 && arg_debug) | ||
86 | printf("Cannot relabel %s: %s\n", path, strerror(errno)); | ||
87 | |||
88 | if (!called_as_root) | ||
89 | EUID_USER(); | ||
72 | } | 90 | } |
91 | |||
73 | freecon(fcon); | 92 | freecon(fcon); |
74 | close: | 93 | close: |
75 | close(fd); | 94 | close(fd); |
diff --git a/src/firejail/util.c b/src/firejail/util.c index 094a68c60..f0df45eb2 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -459,31 +459,21 @@ int is_dir(const char *fname) { | |||
459 | if (*fname == '\0') | 459 | if (*fname == '\0') |
460 | return 0; | 460 | return 0; |
461 | 461 | ||
462 | int called_as_root = 0; | ||
463 | if (geteuid() == 0) | ||
464 | called_as_root = 1; | ||
465 | |||
466 | if (called_as_root) | ||
467 | EUID_USER(); | ||
468 | |||
469 | // if fname doesn't end in '/', add one | 462 | // if fname doesn't end in '/', add one |
470 | int rv; | 463 | int rv; |
471 | struct stat s; | 464 | struct stat s; |
472 | if (fname[strlen(fname) - 1] == '/') | 465 | if (fname[strlen(fname) - 1] == '/') |
473 | rv = stat(fname, &s); | 466 | rv = stat_as_user(fname, &s); |
474 | else { | 467 | else { |
475 | char *tmp; | 468 | char *tmp; |
476 | if (asprintf(&tmp, "%s/", fname) == -1) { | 469 | if (asprintf(&tmp, "%s/", fname) == -1) { |
477 | fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__); | 470 | fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__); |
478 | errExit("asprintf"); | 471 | errExit("asprintf"); |
479 | } | 472 | } |
480 | rv = stat(tmp, &s); | 473 | rv = stat_as_user(tmp, &s); |
481 | free(tmp); | 474 | free(tmp); |
482 | } | 475 | } |
483 | 476 | ||
484 | if (called_as_root) | ||
485 | EUID_ROOT(); | ||
486 | |||
487 | if (rv == -1) | 477 | if (rv == -1) |
488 | return 0; | 478 | return 0; |
489 | 479 | ||
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index a768829a1..a1eccaa5e 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt | |||
@@ -78,7 +78,7 @@ in your desktop environment copy the profile file in ~/.config/firejail director | |||
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 |
@@ -174,7 +174,7 @@ Example: "?HAS_APPIMAGE: whitelist ${HOME}/special/appimage/dir" | |||
174 | 174 | ||
175 | This example will load the whitelist 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. |
@@ -324,16 +324,16 @@ Remount the file or the directory noexec, nodev and nosuid. | |||
324 | #ifdef HAVE_OVERLAYFS | 324 | #ifdef HAVE_OVERLAYFS |
325 | .TP | 325 | .TP |
326 | \fBoverlay | 326 | \fBoverlay |
327 | Mount a filesystem overlay on top of the current filesystem. | 327 | Mount a filesystem overlay on top of the current filesystem. |
328 | The overlay is stored in $HOME/.firejail/<PID> directory. | 328 | The overlay is stored in $HOME/.firejail/<PID> directory. |
329 | .TP | 329 | .TP |
330 | \fBoverlay-named name | 330 | \fBoverlay-named name |
331 | Mount a filesystem overlay on top of the current filesystem. | 331 | Mount a filesystem overlay on top of the current filesystem. |
332 | The overlay is stored in $HOME/.firejail/name directory. | 332 | The overlay is stored in $HOME/.firejail/name directory. |
333 | .TP | 333 | .TP |
334 | \fBoverlay-tmpfs | 334 | \fBoverlay-tmpfs |
335 | Mount a filesystem overlay on top of the current filesystem. | 335 | Mount a filesystem overlay on top of the current filesystem. |
336 | All filesystem modifications are discarded when the sandbox is closed. | 336 | All filesystem modifications are discarded when the sandbox is closed. |
337 | #endif | 337 | #endif |
338 | .TP | 338 | .TP |
339 | \fBprivate | 339 | \fBprivate |
@@ -487,12 +487,12 @@ does not result in an increase of privilege. | |||
487 | #ifdef HAVE_USERNS | 487 | #ifdef HAVE_USERNS |
488 | .TP | 488 | .TP |
489 | \fBnoroot | 489 | \fBnoroot |
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 |
@@ -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 0462705c0..2883ab257 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -45,7 +45,7 @@ firejail {\-? | \-\-debug-caps | \-\-debug-errnos | \-\-debug-syscalls | \-\-deb | |||
45 | #ifdef HAVE_LTS | 45 | #ifdef HAVE_LTS |
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 | ||
@@ -109,7 +109,7 @@ ptrace system call allows a full bypass of the seccomp filter. | |||
109 | .br | 109 | .br |
110 | Example: | 110 | Example: |
111 | .br | 111 | .br |
112 | $ firejail --allow-debuggers --profile=/etc/firejail/firefox.profile strace -f firefox | 112 | $ firejail --allow-debuggers --profile=/etc/firejail/firefox.profile strace -f firefox |
113 | .TP | 113 | .TP |
114 | \fB\-\-allusers | 114 | \fB\-\-allusers |
115 | 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. |
@@ -947,7 +947,7 @@ $ firejail \-\-net=eth0 \-\-\iprange=192.168.1.100,192.168.1.150 | |||
947 | 947 | ||
948 | .TP | 948 | .TP |
949 | \fB\-\-ipc-namespace | 949 | \fB\-\-ipc-namespace |
950 | 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 |
951 | for sandboxes started as root. | 951 | for sandboxes started as root. |
952 | .br | 952 | .br |
953 | 953 | ||
@@ -1014,7 +1014,7 @@ $ sudo firejail --join-network=browser /sbin/iptables -vL | |||
1014 | .br | 1014 | .br |
1015 | 1015 | ||
1016 | .br | 1016 | .br |
1017 | # verify IP addresses | 1017 | # verify IP addresses |
1018 | .br | 1018 | .br |
1019 | $ sudo firejail --join-network=browser ip addr | 1019 | $ sudo firejail --join-network=browser ip addr |
1020 | .br | 1020 | .br |
@@ -2134,7 +2134,7 @@ Use k(ilobyte), m(egabyte) or g(igabyte) for size suffix (base 1024). | |||
2134 | .TP | 2134 | .TP |
2135 | \fB\-\-rlimit-cpu=number | 2135 | \fB\-\-rlimit-cpu=number |
2136 | 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 |
2137 | 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. |
2138 | 2138 | ||
2139 | 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 |
2140 | 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 |
@@ -2178,7 +2178,7 @@ $ firejail \-\-net=eth0 \-\-scan | |||
2178 | .TP | 2178 | .TP |
2179 | \fB\-\-seccomp | 2179 | \fB\-\-seccomp |
2180 | Enable seccomp filter and blacklist the syscalls in the default list, | 2180 | Enable seccomp filter and blacklist the syscalls in the default list, |
2181 | which is @default-nodebuggers unless \-\-allow-debuggers is specified, | 2181 | which is @default-nodebuggers unless \-\-allow-debuggers is specified, |
2182 | then it is @default. | 2182 | then it is @default. |
2183 | 2183 | ||
2184 | .br | 2184 | .br |
@@ -2865,7 +2865,7 @@ and it is installed by default on most Linux distributions. It provides support | |||
2865 | 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 |
2866 | contents of other clients, stealing input events, etc. | 2866 | contents of other clients, stealing input events, etc. |
2867 | 2867 | ||
2868 | 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 |
2869 | 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. |
2870 | Firefox and transmission-gtk seem to be working fine. | 2870 | Firefox and transmission-gtk seem to be working fine. |
2871 | A network namespace is not required for this option. | 2871 | A network namespace is not required for this option. |
@@ -3256,7 +3256,7 @@ The owner of the sandbox. | |||
3256 | .SH RESTRICTED SHELL | 3256 | .SH RESTRICTED SHELL |
3257 | 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 |
3258 | /etc/passwd file for each user that needs to be restricted. Alternatively, | 3258 | /etc/passwd file for each user that needs to be restricted. Alternatively, |
3259 | you can specify /usr/bin/firejail in adduser command: | 3259 | you can specify /usr/bin/firejail in adduser command: |
3260 | 3260 | ||
3261 | adduser \-\-shell /usr/bin/firejail username | 3261 | adduser \-\-shell /usr/bin/firejail username |
3262 | 3262 | ||
@@ -3266,7 +3266,7 @@ Additional arguments passed to firejail executable upon login are declared in /e | |||
3266 | Several command line options can be passed to the program using | 3266 | Several command line options can be passed to the program using |
3267 | profile files. Firejail chooses the profile file as follows: | 3267 | profile files. Firejail chooses the profile file as follows: |
3268 | 3268 | ||
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. | 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. |
3270 | Example: | 3270 | Example: |
3271 | .PP | 3271 | .PP |
3272 | .RS | 3272 | .RS |
diff --git a/src/man/firemon.txt b/src/man/firemon.txt index 76b2f7be2..c4e6e15b3 100644 --- a/src/man/firemon.txt +++ b/src/man/firemon.txt | |||
@@ -56,7 +56,7 @@ Print route table for each sandbox. | |||
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 |