diff options
-rw-r--r-- | etc/dig.profile | 3 | ||||
-rw-r--r-- | etc/disable-common.inc | 3 | ||||
-rw-r--r-- | etc/firejail-default | 18 | ||||
-rw-r--r-- | etc/k3b.profile | 13 | ||||
-rw-r--r-- | etc/wine.profile | 7 | ||||
-rw-r--r-- | src/firejail/fs.c | 6 | ||||
-rw-r--r-- | src/firejail/fs_home.c | 63 | ||||
-rw-r--r-- | src/firejail/main.c | 2 | ||||
-rw-r--r-- | src/firejail/profile.c | 5 | ||||
-rw-r--r-- | src/man/firejail-profile.txt | 2 |
10 files changed, 82 insertions, 40 deletions
diff --git a/etc/dig.profile b/etc/dig.profile index e609105b4..af71ff17f 100644 --- a/etc/dig.profile +++ b/etc/dig.profile | |||
@@ -46,7 +46,8 @@ private | |||
46 | private-bin bash,dig,sh | 46 | private-bin bash,dig,sh |
47 | private-cache | 47 | private-cache |
48 | private-dev | 48 | private-dev |
49 | private-lib | 49 | # Uncomment the next line (or put 'private-lib' in your dig.local) on non Debian/Ubuntu OS (see issue #3038) |
50 | #private-lib | ||
50 | private-tmp | 51 | private-tmp |
51 | 52 | ||
52 | memory-deny-write-execute | 53 | memory-deny-write-execute |
diff --git a/etc/disable-common.inc b/etc/disable-common.inc index 96957eeaf..b2837b443 100644 --- a/etc/disable-common.inc +++ b/etc/disable-common.inc | |||
@@ -315,6 +315,7 @@ blacklist ${HOME}/.config/keybase | |||
315 | blacklist ${HOME}/.davfs2/secrets | 315 | blacklist ${HOME}/.davfs2/secrets |
316 | blacklist ${HOME}/.ecryptfs | 316 | blacklist ${HOME}/.ecryptfs |
317 | blacklist ${HOME}/.fetchmailrc | 317 | blacklist ${HOME}/.fetchmailrc |
318 | blacklist ${HOME}/.fscrypt | ||
318 | blacklist ${HOME}/.git-credential-cache | 319 | blacklist ${HOME}/.git-credential-cache |
319 | blacklist ${HOME}/.git-credentials | 320 | blacklist ${HOME}/.git-credentials |
320 | blacklist ${HOME}/.gnome2/keyrings | 321 | blacklist ${HOME}/.gnome2/keyrings |
@@ -335,6 +336,7 @@ blacklist ${HOME}/.local/share/pki | |||
335 | blacklist ${HOME}/.smbcredentials | 336 | blacklist ${HOME}/.smbcredentials |
336 | blacklist ${HOME}/.ssh | 337 | blacklist ${HOME}/.ssh |
337 | blacklist ${HOME}/.vaults | 338 | blacklist ${HOME}/.vaults |
339 | blacklist /.fscrypt | ||
338 | blacklist /etc/davfs2/secrets | 340 | blacklist /etc/davfs2/secrets |
339 | blacklist /etc/group+ | 341 | blacklist /etc/group+ |
340 | blacklist /etc/group- | 342 | blacklist /etc/group- |
@@ -348,6 +350,7 @@ blacklist /etc/shadow+ | |||
348 | blacklist /etc/shadow- | 350 | blacklist /etc/shadow- |
349 | blacklist /etc/ssh | 351 | blacklist /etc/ssh |
350 | blacklist /home/.ecryptfs | 352 | blacklist /home/.ecryptfs |
353 | blacklist /home/.fscrypt | ||
351 | blacklist /var/backup | 354 | blacklist /var/backup |
352 | 355 | ||
353 | # cloud provider configuration | 356 | # cloud provider configuration |
diff --git a/etc/firejail-default b/etc/firejail-default index e7831e145..a012f5440 100644 --- a/etc/firejail-default +++ b/etc/firejail-default | |||
@@ -22,12 +22,11 @@ dbus, | |||
22 | 22 | ||
23 | ########## | 23 | ########## |
24 | # With ptrace it is possible to inspect and hijack running programs. | 24 | # With ptrace it is possible to inspect and hijack running programs. |
25 | # Some browsers are also using ptrace for their sandboxing. | ||
26 | ########## | 25 | ########## |
27 | # Uncomment this line to allow all ptrace access | 26 | # Uncomment this line to allow all ptrace access |
28 | #ptrace, | 27 | #ptrace, |
29 | # Allow obtaining some process information, but not ptrace(2) | 28 | # Allow obtaining some process information, but not ptrace(2) |
30 | ptrace (read,readby) peer=firejail-default, | 29 | ptrace (read,readby) peer=@{profile_name}, |
31 | 30 | ||
32 | ########## | 31 | ########## |
33 | # Allow read access to whole filesystem and control it from firejail. | 32 | # Allow read access to whole filesystem and control it from firejail. |
@@ -46,9 +45,6 @@ ptrace (read,readby) peer=firejail-default, | |||
46 | ########## | 45 | ########## |
47 | owner /{,run/firejail/mnt/oroot/}{,var/}run/firejail/mnt/trace w, | 46 | owner /{,run/firejail/mnt/oroot/}{,var/}run/firejail/mnt/trace w, |
48 | owner /{,run/firejail/mnt/oroot/}{,var/}run/user/[0-9]*/** w, | 47 | owner /{,run/firejail/mnt/oroot/}{,var/}run/user/[0-9]*/** w, |
49 | owner /{,run/firejail/mnt/oroot/}{,var/}run/user/[0-9]*/*.slave-socket w, | ||
50 | owner /{,run/firejail/mnt/oroot/}{,var/}run/user/[0-9]*/orcexec.* w, | ||
51 | |||
52 | owner /{,run/firejail/mnt/oroot/}{run,dev}/shm/** w, | 48 | owner /{,run/firejail/mnt/oroot/}{run,dev}/shm/** w, |
53 | 49 | ||
54 | # Allow writing to removable media | 50 | # Allow writing to removable media |
@@ -58,9 +54,6 @@ owner /{,var/}run/media/** w, | |||
58 | /{,var/}run/systemd/journal/socket w, | 54 | /{,var/}run/systemd/journal/socket w, |
59 | /{,var/}run/systemd/journal/dev-log w, | 55 | /{,var/}run/systemd/journal/dev-log w, |
60 | 56 | ||
61 | # Needed for wine | ||
62 | /{,var/}run/firejail/profile/@{PID} w, | ||
63 | |||
64 | # Allow access to cups printing socket. | 57 | # Allow access to cups printing socket. |
65 | /{,var/}run/cups/cups.sock w, | 58 | /{,var/}run/cups/cups.sock w, |
66 | 59 | ||
@@ -94,8 +87,10 @@ deny /proc/@{PID}/oom_score_adj w, | |||
94 | ########## | 87 | ########## |
95 | # Blacklist specific sensitive paths. | 88 | # Blacklist specific sensitive paths. |
96 | ########## | 89 | ########## |
97 | # Common backup directory | 90 | deny /**/.fscrypt/ rw, |
98 | deny /**/.snapshots/ rwx, | 91 | deny /**/.fscrypt/** rwklmx, |
92 | deny /**/.snapshots/ rw, | ||
93 | deny /**/.snapshots/** rwklmx, | ||
99 | 94 | ||
100 | ########## | 95 | ########## |
101 | # Allow all networking functionality, and control it from Firejail. | 96 | # Allow all networking functionality, and control it from Firejail. |
@@ -111,7 +106,8 @@ network packet, | |||
111 | ########## | 106 | ########## |
112 | # There is no equivalent in Firejail for filtering signals. | 107 | # There is no equivalent in Firejail for filtering signals. |
113 | ########## | 108 | ########## |
114 | signal, | 109 | signal (send) peer=@{profile_name}, |
110 | signal (receive), | ||
115 | 111 | ||
116 | ########## | 112 | ########## |
117 | # We let Firejail deal with capabilities, but ensure that | 113 | # We let Firejail deal with capabilities, but ensure that |
diff --git a/etc/k3b.profile b/etc/k3b.profile index 60da458ab..0c1da7ae1 100644 --- a/etc/k3b.profile +++ b/etc/k3b.profile | |||
@@ -20,17 +20,18 @@ include disable-xdg.inc | |||
20 | 20 | ||
21 | include whitelist-var-common.inc | 21 | include whitelist-var-common.inc |
22 | 22 | ||
23 | caps.drop all | 23 | caps.keep ipc_lock,sys_nice,sys_rawio,sys_resource |
24 | # net none | ||
24 | netfilter | 25 | netfilter |
25 | no3d | 26 | no3d |
26 | nonewprivs | 27 | # nonewprivs - breaks privileged helpers |
27 | noroot | 28 | # noroot - breaks privileged helpers |
28 | nosound | 29 | nosound |
29 | notv | 30 | notv |
30 | novideo | 31 | novideo |
31 | protocol unix | 32 | # protocol unix - breaks privileged helpers |
32 | seccomp | 33 | # seccomp - breaks privileged helpers |
33 | shell none | 34 | shell none |
34 | tracelog | ||
35 | 35 | ||
36 | private-dev | ||
36 | # private-tmp | 37 | # private-tmp |
diff --git a/etc/wine.profile b/etc/wine.profile index 192c375cd..29e79c3f5 100644 --- a/etc/wine.profile +++ b/etc/wine.profile | |||
@@ -15,13 +15,20 @@ noblacklist ${HOME}/.wine | |||
15 | include disable-common.inc | 15 | include disable-common.inc |
16 | include disable-devel.inc | 16 | include disable-devel.inc |
17 | include disable-interpreters.inc | 17 | include disable-interpreters.inc |
18 | include disable-passwdmgr.inc | ||
18 | include disable-programs.inc | 19 | include disable-programs.inc |
19 | 20 | ||
21 | # uncomment next line if seccomp breaks a program | ||
22 | # allow-debuggers | ||
20 | caps.drop all | 23 | caps.drop all |
24 | # net none | ||
21 | netfilter | 25 | netfilter |
22 | nodvd | 26 | nodvd |
23 | nogroups | 27 | nogroups |
24 | nonewprivs | 28 | nonewprivs |
25 | noroot | 29 | noroot |
26 | notv | 30 | notv |
31 | # novideo | ||
27 | seccomp | 32 | seccomp |
33 | |||
34 | private-dev | ||
diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 3df551d4c..3e802efb5 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c | |||
@@ -1191,15 +1191,15 @@ void fs_private_cache(void) { | |||
1191 | // check if ~/.cache is a valid destination | 1191 | // check if ~/.cache is a valid destination |
1192 | struct stat s; | 1192 | struct stat s; |
1193 | if (lstat(cache, &s) == -1) { | 1193 | if (lstat(cache, &s) == -1) { |
1194 | fwarning("cannot find %s, tmpfs not mounted\n", cache); | 1194 | fwarning("skipping private-cache: cannot find %s\n", cache); |
1195 | free(cache); | 1195 | free(cache); |
1196 | return; | 1196 | return; |
1197 | } | 1197 | } |
1198 | if (!S_ISDIR(s.st_mode)) { | 1198 | if (!S_ISDIR(s.st_mode)) { |
1199 | if (S_ISLNK(s.st_mode)) | 1199 | if (S_ISLNK(s.st_mode)) |
1200 | fwarning("%s is a symbolic link, tmpfs not mounted\n", cache); | 1200 | fwarning("skipping private-cache: %s is a symbolic link\n", cache); |
1201 | else | 1201 | else |
1202 | fwarning("%s is not a directory; cannot mount a tmpfs on top of it\n", cache); | 1202 | fwarning("skipping private-cache: %s is not a directory\n", cache); |
1203 | free(cache); | 1203 | free(cache); |
1204 | return; | 1204 | return; |
1205 | } | 1205 | } |
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index 25c167af1..2e8a8ad96 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c | |||
@@ -250,6 +250,9 @@ void fs_private_homedir(void) { | |||
250 | int xflag = store_xauthority(); | 250 | int xflag = store_xauthority(); |
251 | int aflag = store_asoundrc(); | 251 | int aflag = store_asoundrc(); |
252 | 252 | ||
253 | // home directory outside /home? | ||
254 | int oflag = (strncmp(homedir, "/home/", 6) != 0); | ||
255 | |||
253 | uid_t u = getuid(); | 256 | uid_t u = getuid(); |
254 | gid_t g = getgid(); | 257 | gid_t g = getgid(); |
255 | 258 | ||
@@ -259,20 +262,33 @@ void fs_private_homedir(void) { | |||
259 | // get file descriptors for homedir and private_homedir, fails if there is any symlink | 262 | // get file descriptors for homedir and private_homedir, fails if there is any symlink |
260 | int src = safe_fd(private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); | 263 | int src = safe_fd(private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); |
261 | if (src == -1) | 264 | if (src == -1) |
262 | errExit("safe_fd"); | 265 | errExit("opening private directory"); |
263 | int dst = safe_fd(homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); | 266 | int dst = safe_fd(homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); |
264 | if (dst == -1) | 267 | if (dst == -1) |
265 | errExit("safe_fd"); | 268 | errExit("opening home directory"); |
266 | // check if new home directory is owned by the user | 269 | if (u != 0) { |
267 | struct stat s; | 270 | struct stat s; |
268 | if (fstat(src, &s) == -1) | 271 | // sometimes system users are assigned home directories like /, /proc, ... |
269 | errExit("fstat"); | 272 | // require that a home directory outside /home is owned by the user |
270 | if (s.st_uid != getuid()) { | 273 | if (oflag) { |
271 | fprintf(stderr, "Error: private directory is not owned by the current user\n"); | 274 | if (fstat(dst, &s) == -1) |
272 | exit(1); | 275 | errExit("fstat"); |
276 | if (s.st_uid != u) { | ||
277 | fprintf(stderr, "Error: cannot mount private directory:\n" | ||
278 | "Home directory is not owned by the current user\n"); | ||
279 | exit(1); | ||
280 | } | ||
281 | } | ||
282 | // check if new home directory is owned by the user | ||
283 | if (fstat(src, &s) == -1) | ||
284 | errExit("fstat"); | ||
285 | if (s.st_uid != u) { | ||
286 | fprintf(stderr, "Error: private directory is not owned by the current user\n"); | ||
287 | exit(1); | ||
288 | } | ||
289 | if ((S_IRWXU & s.st_mode) != S_IRWXU) | ||
290 | fwarning("no full permissions on private directory\n"); | ||
273 | } | 291 | } |
274 | if ((S_IRWXU & s.st_mode) != S_IRWXU) | ||
275 | fwarning("no full permissions on private directory\n"); | ||
276 | // mount via the links in /proc/self/fd | 292 | // mount via the links in /proc/self/fd |
277 | char *proc_src, *proc_dst; | 293 | char *proc_src, *proc_dst; |
278 | if (asprintf(&proc_src, "/proc/self/fd/%d", src) == -1) | 294 | if (asprintf(&proc_src, "/proc/self/fd/%d", src) == -1) |
@@ -308,7 +324,7 @@ void fs_private_homedir(void) { | |||
308 | errExit("mounting home directory"); | 324 | errExit("mounting home directory"); |
309 | fs_logger("tmpfs /root"); | 325 | fs_logger("tmpfs /root"); |
310 | } | 326 | } |
311 | if (u == 0 || strncmp(homedir, "/home/", 6) != 0) { | 327 | if (oflag) { |
312 | // mask /home | 328 | // mask /home |
313 | if (arg_debug) | 329 | if (arg_debug) |
314 | printf("Mounting a new /home directory\n"); | 330 | printf("Mounting a new /home directory\n"); |
@@ -317,7 +333,6 @@ void fs_private_homedir(void) { | |||
317 | fs_logger("tmpfs /home"); | 333 | fs_logger("tmpfs /home"); |
318 | } | 334 | } |
319 | 335 | ||
320 | |||
321 | skel(homedir, u, g); | 336 | skel(homedir, u, g); |
322 | if (xflag) | 337 | if (xflag) |
323 | copy_xauthority(); | 338 | copy_xauthority(); |
@@ -377,6 +392,7 @@ void fs_private(void) { | |||
377 | } | 392 | } |
378 | else | 393 | else |
379 | // user directory is outside /home, mask it as well | 394 | // user directory is outside /home, mask it as well |
395 | // check if directory is owned by the current user | ||
380 | fs_tmpfs(homedir, 1); | 396 | fs_tmpfs(homedir, 1); |
381 | } | 397 | } |
382 | 398 | ||
@@ -385,7 +401,6 @@ void fs_private(void) { | |||
385 | copy_xauthority(); | 401 | copy_xauthority(); |
386 | if (aflag) | 402 | if (aflag) |
387 | copy_asoundrc(); | 403 | copy_asoundrc(); |
388 | |||
389 | } | 404 | } |
390 | 405 | ||
391 | // check new private home directory (--private= option) - exit if it fails | 406 | // check new private home directory (--private= option) - exit if it fails |
@@ -531,6 +546,9 @@ void fs_private_home_list(void) { | |||
531 | int xflag = store_xauthority(); | 546 | int xflag = store_xauthority(); |
532 | int aflag = store_asoundrc(); | 547 | int aflag = store_asoundrc(); |
533 | 548 | ||
549 | // home directory outside /home? | ||
550 | int oflag = (strncmp(homedir, "/home/", 6) != 0); | ||
551 | |||
534 | uid_t uid = getuid(); | 552 | uid_t uid = getuid(); |
535 | gid_t gid = getgid(); | 553 | gid_t gid = getgid(); |
536 | 554 | ||
@@ -563,7 +581,19 @@ void fs_private_home_list(void) { | |||
563 | 581 | ||
564 | int fd = safe_fd(homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); | 582 | int fd = safe_fd(homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); |
565 | if (fd == -1) | 583 | if (fd == -1) |
566 | errExit("safe_fd"); | 584 | errExit("opening home directory"); |
585 | if (uid != 0 && oflag) { | ||
586 | // home directory outside /home should be owned by the user | ||
587 | struct stat s; | ||
588 | if (fstat(fd, &s) == -1) | ||
589 | errExit("fstat"); | ||
590 | if (s.st_uid != uid) { | ||
591 | fprintf(stderr, "Error: cannot mount private directory:\n" | ||
592 | "Home directory is not owned by the current user\n"); | ||
593 | exit(1); | ||
594 | } | ||
595 | } | ||
596 | // mount using the file descriptor | ||
567 | char *proc; | 597 | char *proc; |
568 | if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) | 598 | if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) |
569 | errExit("asprintf"); | 599 | errExit("asprintf"); |
@@ -584,7 +614,7 @@ void fs_private_home_list(void) { | |||
584 | if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=700,gid=0") < 0) | 614 | if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=700,gid=0") < 0) |
585 | errExit("mounting home directory"); | 615 | errExit("mounting home directory"); |
586 | } | 616 | } |
587 | if (uid == 0 || strncmp(homedir, "/home/", 6) != 0) { | 617 | if (oflag) { |
588 | // mask /home | 618 | // mask /home |
589 | if (arg_debug) | 619 | if (arg_debug) |
590 | printf("Mounting a new /home directory\n"); | 620 | printf("Mounting a new /home directory\n"); |
@@ -600,5 +630,4 @@ void fs_private_home_list(void) { | |||
600 | 630 | ||
601 | if (!arg_quiet) | 631 | if (!arg_quiet) |
602 | fprintf(stderr, "Home directory installed in %0.2f ms\n", timetrace_end()); | 632 | fprintf(stderr, "Home directory installed in %0.2f ms\n", timetrace_end()); |
603 | |||
604 | } | 633 | } |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 5b39dd491..1786cfac2 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -262,7 +262,7 @@ static int has_link(const char *dir) { | |||
262 | 262 | ||
263 | static void check_homedir(void) { | 263 | static void check_homedir(void) { |
264 | assert(cfg.homedir); | 264 | assert(cfg.homedir); |
265 | if (cfg.homedir[0] != '/' || cfg.homedir[1] == '\0') { // system users sometimes have root directory as home | 265 | if (cfg.homedir[0] != '/') { |
266 | fprintf(stderr, "Error: invalid user directory \"%s\"\n", cfg.homedir); | 266 | fprintf(stderr, "Error: invalid user directory \"%s\"\n", cfg.homedir); |
267 | exit(1); | 267 | exit(1); |
268 | } | 268 | } |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 03cd9dadb..9a724331b 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -143,6 +143,10 @@ static int check_appimage(void) { | |||
143 | return arg_appimage != 0; | 143 | return arg_appimage != 0; |
144 | } | 144 | } |
145 | 145 | ||
146 | static int check_netoptions(void) { | ||
147 | return (arg_nonetwork || any_bridge_configured()); | ||
148 | } | ||
149 | |||
146 | static int check_nodbus(void) { | 150 | static int check_nodbus(void) { |
147 | return arg_nodbus != 0; | 151 | return arg_nodbus != 0; |
148 | } | 152 | } |
@@ -161,6 +165,7 @@ static int check_allow_drm(void) { | |||
161 | 165 | ||
162 | Cond conditionals[] = { | 166 | Cond conditionals[] = { |
163 | {"HAS_APPIMAGE", check_appimage}, | 167 | {"HAS_APPIMAGE", check_appimage}, |
168 | {"HAS_NET", check_netoptions}, | ||
164 | {"HAS_NODBUS", check_nodbus}, | 169 | {"HAS_NODBUS", check_nodbus}, |
165 | {"HAS_X11", check_x11}, | 170 | {"HAS_X11", check_x11}, |
166 | {"BROWSER_DISABLE_U2F", check_disable_u2f}, | 171 | {"BROWSER_DISABLE_U2F", check_disable_u2f}, |
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index 4a84cc828..719a80c2c 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt | |||
@@ -103,7 +103,7 @@ Example: "?HAS_APPIMAGE: whitelist ${HOME}/special/appimage/dir" | |||
103 | 103 | ||
104 | This example will load the whitelist profile line only if the \-\-appimage option has been specified on the command line. | 104 | This example will load the whitelist profile line only if the \-\-appimage option has been specified on the command line. |
105 | 105 | ||
106 | Currently the only conditionals supported this way are HAS_APPIMAGE, HAS_NODBUS and HAS_X11. The conditionals BROWSER_DISABLE_U2F and BROWSER_ALLOW_DRM | 106 | Currently the only conditionals supported this way are HAS_APPIMAGE, HAS_NET, HAS_NODBUS and HAS_X11. The conditionals BROWSER_DISABLE_U2F and BROWSER_ALLOW_DRM |
107 | can be enabled or disabled globally in Firejail's configuration file. | 107 | can be enabled or disabled globally in Firejail's configuration file. |
108 | 108 | ||
109 | The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines. | 109 | The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines. |