aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md21
-rw-r--r--RELNOTES1
-rw-r--r--contrib/vim/syntax/firejail.vim2
-rw-r--r--etc/firejail.config3
-rw-r--r--etc/inc/allow-common-devel.inc5
-rw-r--r--etc/inc/allow-ruby.inc1
-rw-r--r--etc/inc/disable-interpreters.inc1
-rw-r--r--etc/inc/disable-programs.inc3
-rw-r--r--etc/profile-a-l/amule.profile1
-rw-r--r--etc/profile-a-l/build-systems-common.profile66
-rw-r--r--etc/profile-a-l/bundle.profile23
-rw-r--r--etc/profile-a-l/cargo.profile56
-rw-r--r--etc/profile-a-l/cmake.profile13
-rw-r--r--etc/profile-m-z/make.profile13
-rw-r--r--etc/profile-m-z/meson.profile14
-rw-r--r--etc/profile-m-z/pip.profile18
-rw-r--r--src/firejail/checkcfg.c2
-rw-r--r--src/firejail/firejail.h6
-rw-r--r--src/firejail/fs.c38
-rw-r--r--src/firejail/fs_trace.c31
-rw-r--r--src/firejail/mountinfo.c71
-rw-r--r--src/firejail/profile.c15
-rw-r--r--src/firejail/sandbox.c11
-rw-r--r--src/man/firejail-profile.txt2
24 files changed, 287 insertions, 130 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 0f13afc51..eb485b8a2 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -7,6 +7,13 @@ assignees: ''
7 7
8--- 8---
9 9
10<!--
11See the following links for help with formatting:
12
13https://guides.github.com/features/mastering-markdown/
14https://docs.github.com/en/github/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax
15-->
16
10### Description 17### Description
11 18
12_Describe the bug_ 19_Describe the bug_
@@ -15,7 +22,7 @@ _Describe the bug_
15 22
16_Steps to reproduce the behavior_ 23_Steps to reproduce the behavior_
17 24
181. Run in bash `LANG=C firejail PROGRAM` (`LANG=C` to get English messages that can be understood by everybody) 251. Run in bash `LC_ALL=C firejail PROGRAM` (`LC_ALL=C` to get a consistent output in English that can be understood by everybody)
192. Click on '....' 262. Click on '....'
203. Scroll down to '....' 273. Scroll down to '....'
214. See error `ERROR` 284. See error `ERROR`
@@ -30,7 +37,7 @@ _What actually happened_
30 37
31### Behavior without a profile 38### Behavior without a profile
32 39
33_What changed calling `firejail --noprofile /path/to/program` in a terminal?_ 40_What changed calling `LC_ALL=C firejail --noprofile /path/to/program` in a terminal?_
34 41
35### Additional context 42### Additional context
36 43
@@ -44,6 +51,12 @@ _Any other detail that may help to understand/debug the problem_
44 51
45### Checklist 52### Checklist
46 53
54<!--
55Note: Items are checked with an "x", like so:
56
57- [x] This is a checked item.
58-->
59
47- [ ] The issues is caused by firejail (i.e. running the program by path (e.g. `/usr/bin/vlc`) "fixes" it). 60- [ ] The issues is caused by firejail (i.e. running the program by path (e.g. `/usr/bin/vlc`) "fixes" it).
48- [ ] I can reproduce the issue without custom modifications (e.g. globals.local). 61- [ ] I can reproduce the issue without custom modifications (e.g. globals.local).
49- [ ] The program has a profile. (If not, request one in `https://github.com/netblue30/firejail/issues/1139`) 62- [ ] The program has a profile. (If not, request one in `https://github.com/netblue30/firejail/issues/1139`)
@@ -55,7 +68,7 @@ _Any other detail that may help to understand/debug the problem_
55### Log 68### Log
56 69
57<details> 70<details>
58<summary>Output of <code>firejail /path/to/program</code></summary> 71<summary>Output of <code>LC_ALL=C firejail /path/to/program</code></summary>
59<p> 72<p>
60 73
61``` 74```
@@ -66,7 +79,7 @@ output goes here
66</details> 79</details>
67 80
68<details> 81<details>
69<summary>Output of <code>firejail --debug /path/to/program</code></summary> 82<summary>Output of <code>LC_ALL=C firejail --debug /path/to/program</code></summary>
70<p> 83<p>
71 84
72``` 85```
diff --git a/RELNOTES b/RELNOTES
index f52ce09f1..b50fcd559 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -1,5 +1,6 @@
1firejail (0.9.67) baseline; urgency=low 1firejail (0.9.67) baseline; urgency=low
2 * work in progress 2 * work in progress
3 * exit code: distinguish fatal signals by adding 128
3 * deprecated --disable-whitelist at compile time 4 * deprecated --disable-whitelist at compile time
4 * deprecated whitelist=yes/no in /etc/firejail/firejail.config 5 * deprecated whitelist=yes/no in /etc/firejail/firejail.config
5 * remove (some) environment variables with auth-tokens 6 * remove (some) environment variables with auth-tokens
diff --git a/contrib/vim/syntax/firejail.vim b/contrib/vim/syntax/firejail.vim
index d07690ee2..fa80a9c00 100644
--- a/contrib/vim/syntax/firejail.vim
+++ b/contrib/vim/syntax/firejail.vim
@@ -72,7 +72,7 @@ syn match fjCommandNoCond /quiet$/ contained
72 72
73" Conditionals grabbed from: src/firejail/profile.c 73" Conditionals grabbed from: src/firejail/profile.c
74" Generate list with: awk -- 'BEGIN {process=0;} /^Cond conditionals\[\] = \{$/ {process=1;} /\t*\{"[^"]+".*/ { if (process) {print gensub(/^\t*\{"([^"]+)".*$/, "\\1", 1);} } /^\t\{ NULL, NULL \}$/ {process=0;}' src/firejail/profile.c | sort -u | tr $'\n' '|' 74" Generate list with: awk -- 'BEGIN {process=0;} /^Cond conditionals\[\] = \{$/ {process=1;} /\t*\{"[^"]+".*/ { if (process) {print gensub(/^\t*\{"([^"]+)".*$/, "\\1", 1);} } /^\t\{ NULL, NULL \}$/ {process=0;}' src/firejail/profile.c | sort -u | tr $'\n' '|'
75syn match fjConditional /\v\?(BROWSER_ALLOW_DRM|BROWSER_DISABLE_U2F|HAS_APPIMAGE|HAS_NET|HAS_NODBUS|HAS_NOSOUND|HAS_X11) ?:/ nextgroup=fjCommand skipwhite contained 75syn match fjConditional /\v\?(ALLOW_TRAY|BROWSER_ALLOW_DRM|BROWSER_DISABLE_U2F|HAS_APPIMAGE|HAS_NET|HAS_NODBUS|HAS_NOSOUND|HAS_X11) ?:/ nextgroup=fjCommand skipwhite contained
76 76
77" A line is either a command, a conditional or a comment 77" A line is either a command, a conditional or a comment
78syn match fjStatement /^/ nextgroup=fjCommand,fjCommandNoCond,fjConditional,fjComment 78syn match fjStatement /^/ nextgroup=fjCommand,fjCommandNoCond,fjConditional,fjComment
diff --git a/etc/firejail.config b/etc/firejail.config
index aec152b85..7912b746c 100644
--- a/etc/firejail.config
+++ b/etc/firejail.config
@@ -2,6 +2,9 @@
2# keyword-argument pairs, one per line. Most features are enabled by default. 2# keyword-argument pairs, one per line. Most features are enabled by default.
3# Use 'yes' or 'no' as configuration values. 3# Use 'yes' or 'no' as configuration values.
4 4
5# Allow programs to display a tray icon
6# allow-tray no
7
5# Enable AppArmor functionality, default enabled. 8# Enable AppArmor functionality, default enabled.
6# apparmor yes 9# apparmor yes
7 10
diff --git a/etc/inc/allow-common-devel.inc b/etc/inc/allow-common-devel.inc
index 011bbe226..4e460fc10 100644
--- a/etc/inc/allow-common-devel.inc
+++ b/etc/inc/allow-common-devel.inc
@@ -27,5 +27,8 @@ noblacklist ${HOME}/.python-history
27noblacklist ${HOME}/.python_history 27noblacklist ${HOME}/.python_history
28noblacklist ${HOME}/.pythonhist 28noblacklist ${HOME}/.pythonhist
29 29
30# Ruby
31noblacklist ${HOME}/.bundle
32
30# Rust 33# Rust
31noblacklist ${HOME}/.cargo/* 34noblacklist ${HOME}/.cargo
diff --git a/etc/inc/allow-ruby.inc b/etc/inc/allow-ruby.inc
index a8c701219..00276cac7 100644
--- a/etc/inc/allow-ruby.inc
+++ b/etc/inc/allow-ruby.inc
@@ -4,3 +4,4 @@ include allow-ruby.local
4 4
5noblacklist ${PATH}/ruby 5noblacklist ${PATH}/ruby
6noblacklist /usr/lib/ruby 6noblacklist /usr/lib/ruby
7noblacklist /usr/lib64/ruby
diff --git a/etc/inc/disable-interpreters.inc b/etc/inc/disable-interpreters.inc
index 5d8a236fb..804869e2a 100644
--- a/etc/inc/disable-interpreters.inc
+++ b/etc/inc/disable-interpreters.inc
@@ -48,6 +48,7 @@ blacklist /usr/share/php*
48# Ruby 48# Ruby
49blacklist ${PATH}/ruby 49blacklist ${PATH}/ruby
50blacklist /usr/lib/ruby 50blacklist /usr/lib/ruby
51blacklist /usr/lib64/ruby
51 52
52# Programs using python: deluge, firefox addons, filezilla, cherrytree, xchat, hexchat, libreoffice, scribus 53# Programs using python: deluge, firefox addons, filezilla, cherrytree, xchat, hexchat, libreoffice, scribus
53# Python 2 54# Python 2
diff --git a/etc/inc/disable-programs.inc b/etc/inc/disable-programs.inc
index e11df4e64..6734e220a 100644
--- a/etc/inc/disable-programs.inc
+++ b/etc/inc/disable-programs.inc
@@ -49,8 +49,9 @@ blacklist ${HOME}/.bibletime
49blacklist ${HOME}/.bitcoin 49blacklist ${HOME}/.bitcoin
50blacklist ${HOME}/.blobby 50blacklist ${HOME}/.blobby
51blacklist ${HOME}/.bogofilter 51blacklist ${HOME}/.bogofilter
52blacklist ${HOME}/.bundle
52blacklist ${HOME}/.bzf 53blacklist ${HOME}/.bzf
53blacklist ${HOME}/.cargo/* 54blacklist ${HOME}/.cargo
54blacklist ${HOME}/.claws-mail 55blacklist ${HOME}/.claws-mail
55blacklist ${HOME}/.cliqz 56blacklist ${HOME}/.cliqz
56blacklist ${HOME}/.clion* 57blacklist ${HOME}/.clion*
diff --git a/etc/profile-a-l/amule.profile b/etc/profile-a-l/amule.profile
index 3ce05c5bc..e82c145d1 100644
--- a/etc/profile-a-l/amule.profile
+++ b/etc/profile-a-l/amule.profile
@@ -32,6 +32,7 @@ nosound
32notv 32notv
33nou2f 33nou2f
34novideo 34novideo
35# Add netlink protocol to use UPnP
35protocol unix,inet,inet6 36protocol unix,inet,inet6
36seccomp 37seccomp
37shell none 38shell none
diff --git a/etc/profile-a-l/build-systems-common.profile b/etc/profile-a-l/build-systems-common.profile
new file mode 100644
index 000000000..1b199d612
--- /dev/null
+++ b/etc/profile-a-l/build-systems-common.profile
@@ -0,0 +1,66 @@
1# Firejail profile for build-systems-common
2# This file is overwritten after every install/update
3# Persistent local customizations
4include build-systems-common.local
5# Persistent global definitions
6# added by caller profile
7#include globals.local
8
9ignore noexec ${HOME}
10ignore noexec /tmp
11
12# Allow /bin/sh (blacklisted by disable-shell.inc)
13include allow-bin-sh.inc
14
15# Allows files commonly used by IDEs
16include allow-common-devel.inc
17
18# Allow ssh (blacklisted by disable-common.inc)
19#include allow-ssh.inc
20
21blacklist ${RUNUSER}
22
23include disable-common.inc
24include disable-exec.inc
25include disable-interpreters.inc
26include disable-programs.inc
27include disable-shell.inc
28include disable-X11.inc
29include disable-xdg.inc
30
31#whitelist ${HOME}/Projects
32#include whitelist-common.inc
33
34whitelist /usr/share/pkgconfig
35include whitelist-run-common.inc
36include whitelist-usr-share-common.inc
37include whitelist-var-common.inc
38
39caps.drop all
40ipc-namespace
41machine-id
42# net none
43netfilter
44no3d
45nodvd
46nogroups
47noinput
48nonewprivs
49noroot
50nosound
51notv
52nou2f
53novideo
54protocol unix,inet,inet6
55seccomp
56seccomp.block-secondary
57shell none
58tracelog
59
60disable-mnt
61private-cache
62private-dev
63private-tmp
64
65dbus-user none
66dbus-system none
diff --git a/etc/profile-a-l/bundle.profile b/etc/profile-a-l/bundle.profile
new file mode 100644
index 000000000..bb82022b1
--- /dev/null
+++ b/etc/profile-a-l/bundle.profile
@@ -0,0 +1,23 @@
1# Firejail profile for bundle
2# Description: Ruby Dependency Management
3# This file is overwritten after every install/update
4quiet
5# Persistent local customizations
6include bundle.local
7# Persistent global definitions
8include globals.local
9
10noblacklist ${HOME}/.bundle
11
12# Allow ruby (blacklisted by disable-interpreters.inc)
13include allow-ruby.inc
14
15#whitelist ${HOME}/.bundle
16#whitelist ${HOME}/.gem
17#whitelist ${HOME}/.local/share/gem
18whitelist /usr/share/gems
19whitelist /usr/share/ruby
20whitelist /usr/share/rubygems
21
22# Redirect
23include build-systems-common.profile
diff --git a/etc/profile-a-l/cargo.profile b/etc/profile-a-l/cargo.profile
index ff46cd429..4c8afd895 100644
--- a/etc/profile-a-l/cargo.profile
+++ b/etc/profile-a-l/cargo.profile
@@ -7,66 +7,18 @@ include cargo.local
7# Persistent global definitions 7# Persistent global definitions
8include globals.local 8include globals.local
9 9
10ignore noexec ${HOME} 10ignore read-only ${HOME}/.cargo/bin
11ignore noexec /tmp
12
13blacklist /tmp/.X11-unix
14blacklist ${RUNUSER}
15 11
16noblacklist ${HOME}/.cargo/credentials 12noblacklist ${HOME}/.cargo/credentials
17noblacklist ${HOME}/.cargo/credentials.toml 13noblacklist ${HOME}/.cargo/credentials.toml
18 14
19# Allows files commonly used by IDEs
20include allow-common-devel.inc
21
22# Allow ssh (blacklisted by disable-common.inc)
23#include allow-ssh.inc
24
25include disable-common.inc
26include disable-exec.inc
27include disable-interpreters.inc
28include disable-programs.inc
29include disable-xdg.inc
30
31#mkdir ${HOME}/.cargo
32#whitelist ${HOME}/YOUR_CARGO_PROJECTS
33#whitelist ${HOME}/.cargo 15#whitelist ${HOME}/.cargo
34#whitelist ${HOME}/.rustup 16#whitelist ${HOME}/.rustup
35#include whitelist-common.inc
36whitelist /usr/share/pkgconfig
37include whitelist-runuser-common.inc
38include whitelist-usr-share-common.inc
39include whitelist-var-common.inc
40 17
41caps.drop all
42ipc-namespace
43machine-id
44netfilter
45no3d
46nodvd
47nogroups
48noinput
49nonewprivs
50noroot
51nosound
52notv
53nou2f
54novideo
55protocol unix,inet,inet6
56seccomp
57seccomp.block-secondary
58shell none
59tracelog
60
61disable-mnt
62#private-bin cargo,rustc 18#private-bin cargo,rustc
63private-cache
64private-dev
65private-etc alternatives,ca-certificates,crypto-policies,group,host.conf,hostname,hosts,ld.so.cache,ld.so.conf,ld.so.conf.d,ld.so.preload,locale,locale.alias,locale.conf,localtime,magic,magic.mgc,nsswitch.conf,passwd,pki,protocols,resolv.conf,rpc,services,ssl 19private-etc alternatives,ca-certificates,crypto-policies,group,host.conf,hostname,hosts,ld.so.cache,ld.so.conf,ld.so.conf.d,ld.so.preload,locale,locale.alias,locale.conf,localtime,magic,magic.mgc,nsswitch.conf,passwd,pki,protocols,resolv.conf,rpc,services,ssl
66private-tmp
67
68dbus-user none
69dbus-system none
70 20
71memory-deny-write-execute 21memory-deny-write-execute
72read-write ${HOME}/.cargo/bin 22
23# Redirect
24include build-systems-common.profile
diff --git a/etc/profile-a-l/cmake.profile b/etc/profile-a-l/cmake.profile
new file mode 100644
index 000000000..26cc2a00a
--- /dev/null
+++ b/etc/profile-a-l/cmake.profile
@@ -0,0 +1,13 @@
1# Firejail profile for cargo
2# Description: The Rust package manager
3# This file is overwritten after every install/update
4quiet
5# Persistent local customizations
6include cargo.local
7# Persistent global definitions
8include globals.local
9
10memory-deny-write-execute
11
12# Redirect
13include build-systems-common.profile
diff --git a/etc/profile-m-z/make.profile b/etc/profile-m-z/make.profile
new file mode 100644
index 000000000..7e9638fe4
--- /dev/null
+++ b/etc/profile-m-z/make.profile
@@ -0,0 +1,13 @@
1# Firejail profile for make
2# Description: GNU make utility to maintain groups of programs
3# This file is overwritten after every install/update
4quiet
5# Persistent local customizations
6include make.local
7# Persistent global definitions
8include globals.local
9
10memory-deny-write-execute
11
12# Redirect
13include build-systems-common.profile
diff --git a/etc/profile-m-z/meson.profile b/etc/profile-m-z/meson.profile
new file mode 100644
index 000000000..b4909a9d8
--- /dev/null
+++ b/etc/profile-m-z/meson.profile
@@ -0,0 +1,14 @@
1# Firejail profile for meson
2# Description: A high productivity build system
3# This file is overwritten after every install/update
4quiet
5# Persistent local customizations
6include meson.local
7# Persistent global definitions
8include globals.local
9
10# Allow python3 (blacklisted by disable-interpreters.inc)
11include allow-python3.inc
12
13# Redirect
14include build-systems-common.profile
diff --git a/etc/profile-m-z/pip.profile b/etc/profile-m-z/pip.profile
new file mode 100644
index 000000000..a0926371f
--- /dev/null
+++ b/etc/profile-m-z/pip.profile
@@ -0,0 +1,18 @@
1# Firejail profile for pip
2# Description: package manager for Python packages
3# This file is overwritten after every install/update
4quiet
5# Persistent local customizations
6include meson.local
7# Persistent global definitions
8include globals.local
9
10ignore read-only ${HOME}/.local/lib
11
12# Allow python3 (blacklisted by disable-interpreters.inc)
13include allow-python3.inc
14
15#whitelist ${HOME}/.local/lib/python*
16
17# Redirect
18include build-systems-common.profile
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 2a7d88575..730c37aed 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -563,7 +563,7 @@ typedef struct {
563 563
564// mountinfo.c 564// mountinfo.c
565MountData *get_last_mount(void); 565MountData *get_last_mount(void);
566int get_mount_id(const char *path); 566int get_mount_id(int fd);
567char **build_mount_array(const int mount_id, const char *path); 567char **build_mount_array(const int mount_id, const char *path);
568 568
569// fs_var.c 569// fs_var.c
@@ -621,7 +621,8 @@ void caps_print_filter(pid_t pid) __attribute__((noreturn));
621void caps_drop_dac_override(void); 621void caps_drop_dac_override(void);
622 622
623// fs_trace.c 623// fs_trace.c
624void fs_trace_preload(void); 624void fs_trace_touch_preload(void);
625void fs_trace_touch_or_store_preload(void);
625void fs_tracefile(void); 626void fs_tracefile(void);
626void fs_trace(void); 627void fs_trace(void);
627 628
@@ -801,6 +802,7 @@ enum {
801 CFG_NAME_CHANGE, 802 CFG_NAME_CHANGE,
802 CFG_SECCOMP_ERROR_ACTION, 803 CFG_SECCOMP_ERROR_ACTION,
803 // 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,
804 CFG_MAX // this should always be the last entry 806 CFG_MAX // this should always be the last entry
805}; 807};
806extern char *xephyr_screen; 808extern char *xephyr_screen;
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index 6d01b5e5d..3144156a3 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -633,34 +633,30 @@ out:
633} 633}
634 634
635// remount recursively; requires a resolved path 635// remount recursively; requires a resolved path
636static void fs_remount_rec(const char *dir, OPERATION op) { 636static void fs_remount_rec(const char *path, OPERATION op) {
637 EUID_ASSERT(); 637 EUID_ASSERT();
638 assert(dir); 638 assert(op < OPERATION_MAX);
639 assert(path);
639 640
640 struct stat s; 641 // no need to search /proc/self/mountinfo for submounts if not a directory
641 if (stat(dir, &s) != 0) 642 int fd = open(path, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
642 return; 643 if (fd < 0) {
643 if (!S_ISDIR(s.st_mode)) { 644 fs_remount_simple(path, op);
644 // no need to search in /proc/self/mountinfo for submounts if not a directory
645 fs_remount_simple(dir, op);
646 return; 645 return;
647 } 646 }
648 // get mount point of the directory 647
649 int mountid = get_mount_id(dir); 648 // get mount id of the directory
650 if (mountid == -1) 649 int mountid = get_mount_id(fd);
651 return; 650 close(fd);
652 if (mountid == -2) { 651 if (mountid < 0) {
653 // falling back to a simple remount on old kernels 652 // falling back to a simple remount
654 static int mount_warning = 0; 653 fwarning("%s %s not applied recursively\n", opstr[op], path);
655 if (!mount_warning) { 654 fs_remount_simple(path, op);
656 fwarning("read-only, read-write and noexec options are not applied recursively\n");
657 mount_warning = 1;
658 }
659 fs_remount_simple(dir, op);
660 return; 655 return;
661 } 656 }
657
662 // build array with all mount points that need to get remounted 658 // build array with all mount points that need to get remounted
663 char **arr = build_mount_array(mountid, dir); 659 char **arr = build_mount_array(mountid, path);
664 assert(arr); 660 assert(arr);
665 // remount 661 // remount
666 char **tmp = arr; 662 char **tmp = arr;
diff --git a/src/firejail/fs_trace.c b/src/firejail/fs_trace.c
index 475a391ec..718786cdc 100644
--- a/src/firejail/fs_trace.c
+++ b/src/firejail/fs_trace.c
@@ -26,19 +26,26 @@
26#include <fcntl.h> 26#include <fcntl.h>
27#include <pwd.h> 27#include <pwd.h>
28 28
29void fs_trace_preload(void) { 29// create an empty /etc/ld.so.preload
30void fs_trace_touch_preload(void) {
31 create_empty_file_as_root("/etc/ld.so.preload", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
32}
33
34void fs_trace_touch_or_store_preload(void) {
30 struct stat s; 35 struct stat s;
31 36
32 // create an empty /etc/ld.so.preload 37 if (stat("/etc/ld.so.preload", &s) != 0) {
33 if (stat("/etc/ld.so.preload", &s)) { 38 fs_trace_touch_preload();
34 if (arg_debug) 39 return;
35 printf("Creating an empty /etc/ld.so.preload file\n"); 40 }
36 FILE *fp = fopen("/etc/ld.so.preload", "wxe"); 41
37 if (!fp) 42 if (s.st_size == 0)
38 errExit("fopen"); 43 return;
39 SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); 44
40 fclose(fp); 45 // create a copy of /etc/ld.so.preload
41 fs_logger("touch /etc/ld.so.preload"); 46 if (copy_file("/etc/ld.so.preload", RUN_LDPRELOAD_FILE, 0, 0, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) {
47 fprintf(stderr, "Error: cannot copy /etc/ld.so.preload file\n");
48 exit(1);
42 } 49 }
43} 50}
44 51
@@ -83,7 +90,7 @@ void fs_trace(void) {
83 if (arg_debug) 90 if (arg_debug)
84 printf("Create the new ld.so.preload file\n"); 91 printf("Create the new ld.so.preload file\n");
85 92
86 FILE *fp = fopen(RUN_LDPRELOAD_FILE, "we"); 93 FILE *fp = fopen(RUN_LDPRELOAD_FILE, "ae");
87 if (!fp) 94 if (!fp)
88 errExit("fopen"); 95 errExit("fopen");
89 const char *prefix = RUN_FIREJAIL_LIB_DIR; 96 const char *prefix = RUN_FIREJAIL_LIB_DIR;
diff --git a/src/firejail/mountinfo.c b/src/firejail/mountinfo.c
index 64a94bd84..304f80eee 100644
--- a/src/firejail/mountinfo.c
+++ b/src/firejail/mountinfo.c
@@ -19,6 +19,7 @@
19*/ 19*/
20 20
21#include "firejail.h" 21#include "firejail.h"
22#include <errno.h>
22 23
23#include <fcntl.h> 24#include <fcntl.h>
24#ifndef O_PATH 25#ifndef O_PATH
@@ -151,53 +152,71 @@ MountData *get_last_mount(void) {
151 return &mdata; 152 return &mdata;
152} 153}
153 154
154// Extract the mount id from /proc/self/fdinfo and return it. 155// Returns mount id, or -1 if fd refers to a procfs or sysfs file
155int get_mount_id(const char *path) { 156static int get_mount_id_from_handle(int fd) {
156 EUID_ASSERT(); 157 EUID_ASSERT();
157 assert(path);
158 158
159 int fd = open(path, O_PATH|O_CLOEXEC); 159 char *proc;
160 if (fd == -1) 160 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
161 return -1; 161 errExit("asprintf");
162 struct file_handle *fh = malloc(sizeof *fh);
163 if (!fh)
164 errExit("malloc");
165 fh->handle_bytes = 0;
166
167 int rv = -1;
168 int tmp;
169 if (name_to_handle_at(-1, proc, fh, &tmp, AT_SYMLINK_FOLLOW) != -1) {
170 fprintf(stderr, "Error: unexpected result from name_to_handle_at\n");
171 exit(1);
172 }
173 if (errno == EOVERFLOW && fh->handle_bytes)
174 rv = tmp;
175
176 free(proc);
177 free(fh);
178 return rv;
179}
180
181// Returns mount id, or -1 on kernels < 3.15
182static int get_mount_id_from_fdinfo(int fd) {
183 EUID_ASSERT();
184 int rv = -1;
162 185
163 char *fdinfo; 186 char *proc;
164 if (asprintf(&fdinfo, "/proc/self/fdinfo/%d", fd) == -1) 187 if (asprintf(&proc, "/proc/self/fdinfo/%d", fd) == -1)
165 errExit("asprintf"); 188 errExit("asprintf");
166 EUID_ROOT(); 189 EUID_ROOT();
167 FILE *fp = fopen(fdinfo, "re"); 190 FILE *fp = fopen(proc, "re");
168 EUID_USER(); 191 EUID_USER();
169 free(fdinfo);
170 if (!fp) 192 if (!fp)
171 goto errexit; 193 goto errexit;
172 194
173 // read the file
174 char buf[MAX_BUF]; 195 char buf[MAX_BUF];
175 if (fgets(buf, MAX_BUF, fp) == NULL) 196 while (fgets(buf, MAX_BUF, fp)) {
176 goto errexit;
177 do {
178 if (strncmp(buf, "mnt_id:", 7) == 0) { 197 if (strncmp(buf, "mnt_id:", 7) == 0) {
179 char *ptr = buf + 7; 198 if (sscanf(buf + 7, "%d", &rv) != 1)
180 while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
181 ptr++;
182 }
183 if (*ptr == '\0')
184 goto errexit; 199 goto errexit;
185 fclose(fp); 200 break;
186 close(fd);
187 return atoi(ptr);
188 } 201 }
189 } while (fgets(buf, MAX_BUF, fp)); 202 }
190 203
191 // fallback, kernels older than 3.15 don't expose the mount id in this place 204 free(proc);
192 fclose(fp); 205 fclose(fp);
193 close(fd); 206 return rv;
194 return -2;
195 207
196errexit: 208errexit:
197 fprintf(stderr, "Error: cannot read proc file\n"); 209 fprintf(stderr, "Error: cannot read proc file\n");
198 exit(1); 210 exit(1);
199} 211}
200 212
213int get_mount_id(int fd) {
214 int rv = get_mount_id_from_fdinfo(fd);
215 if (rv < 0)
216 rv = get_mount_id_from_handle(fd);
217 return rv;
218}
219
201// Check /proc/self/mountinfo if path contains any mounts points. 220// Check /proc/self/mountinfo if path contains any mounts points.
202// Returns an array that can be iterated over for recursive remounting. 221// Returns an array that can be iterated over for recursive remounting.
203char **build_mount_array(const int mount_id, const char *path) { 222char **build_mount_array(const int mount_id, const char *path) {
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index 059100fcb..5390249ea 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -175,6 +175,10 @@ static int check_allow_drm(void) {
175 return checkcfg(CFG_BROWSER_ALLOW_DRM) != 0; 175 return checkcfg(CFG_BROWSER_ALLOW_DRM) != 0;
176} 176}
177 177
178static int check_allow_tray(void) {
179 return checkcfg(CFG_ALLOW_TRAY) != 0;
180}
181
178Cond conditionals[] = { 182Cond conditionals[] = {
179 {"HAS_APPIMAGE", check_appimage}, 183 {"HAS_APPIMAGE", check_appimage},
180 {"HAS_NET", check_netoptions}, 184 {"HAS_NET", check_netoptions},
@@ -184,6 +188,7 @@ Cond conditionals[] = {
184 {"HAS_X11", check_x11}, 188 {"HAS_X11", check_x11},
185 {"BROWSER_DISABLE_U2F", check_disable_u2f}, 189 {"BROWSER_DISABLE_U2F", check_disable_u2f},
186 {"BROWSER_ALLOW_DRM", check_allow_drm}, 190 {"BROWSER_ALLOW_DRM", check_allow_drm},
191 {"ALLOW_TRAY", check_allow_tray},
187 { NULL, NULL } 192 { NULL, NULL }
188}; 193};
189 194
@@ -630,7 +635,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
630#endif 635#endif
631 return 0; 636 return 0;
632 } 637 }
633 else if (strncmp(ptr, "netns ", 6) == 0) { 638 else if (strncmp(ptr, "netns ", 6) == 0) {
634#ifdef HAVE_NETWORK 639#ifdef HAVE_NETWORK
635 if (checkcfg(CFG_NETWORK)) { 640 if (checkcfg(CFG_NETWORK)) {
636 arg_netns = ptr + 6; 641 arg_netns = ptr + 6;
@@ -981,10 +986,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
981 warning_feature_disabled("seccomp"); 986 warning_feature_disabled("seccomp");
982 return 0; 987 return 0;
983 } 988 }
984 if (strncmp(ptr, "seccomp.32.drop ", 13) == 0) { 989 if (strncmp(ptr, "seccomp.32.drop ", 16) == 0) {
985 if (checkcfg(CFG_SECCOMP)) { 990 if (checkcfg(CFG_SECCOMP)) {
986 arg_seccomp32 = 1; 991 arg_seccomp32 = 1;
987 cfg.seccomp_list_drop32 = seccomp_check_list(ptr + 13); 992 cfg.seccomp_list_drop32 = seccomp_check_list(ptr + 16);
988 } 993 }
989 else 994 else
990 warning_feature_disabled("seccomp"); 995 warning_feature_disabled("seccomp");
@@ -1001,10 +1006,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
1001 warning_feature_disabled("seccomp"); 1006 warning_feature_disabled("seccomp");
1002 return 0; 1007 return 0;
1003 } 1008 }
1004 if (strncmp(ptr, "seccomp.32.keep ", 13) == 0) { 1009 if (strncmp(ptr, "seccomp.32.keep ", 16) == 0) {
1005 if (checkcfg(CFG_SECCOMP)) { 1010 if (checkcfg(CFG_SECCOMP)) {
1006 arg_seccomp32 = 1; 1011 arg_seccomp32 = 1;
1007 cfg.seccomp_list_keep32 = seccomp_check_list(ptr + 13); 1012 cfg.seccomp_list_keep32 = seccomp_check_list(ptr + 16);
1008 } 1013 }
1009 else 1014 else
1010 warning_feature_disabled("seccomp"); 1015 warning_feature_disabled("seccomp");
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 83e50aee2..b776a0cc5 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -798,7 +798,7 @@ int sandbox(void* sandbox_arg) {
798 798
799 // trace pre-install 799 // trace pre-install
800 if (need_preload) 800 if (need_preload)
801 fs_trace_preload(); 801 fs_trace_touch_or_store_preload();
802 802
803 // store hosts file 803 // store hosts file
804 if (cfg.hosts_file) 804 if (cfg.hosts_file)
@@ -814,8 +814,11 @@ int sandbox(void* sandbox_arg) {
814 //**************************** 814 //****************************
815 // trace pre-install, this time inside chroot 815 // trace pre-install, this time inside chroot
816 //**************************** 816 //****************************
817 if (need_preload) 817 if (need_preload) {
818 fs_trace_preload(); 818 int rv = unlink(RUN_LDPRELOAD_FILE);
819 (void) rv;
820 fs_trace_touch_or_store_preload();
821 }
819 } 822 }
820 else 823 else
821#endif 824#endif
@@ -992,7 +995,7 @@ int sandbox(void* sandbox_arg) {
992 995
993 // create /etc/ld.so.preload file again 996 // create /etc/ld.so.preload file again
994 if (need_preload) 997 if (need_preload)
995 fs_trace_preload(); 998 fs_trace_touch_preload();
996 999
997 // openSUSE configuration is split between /etc and /usr/etc 1000 // openSUSE configuration is split between /etc and /usr/etc
998 // process private-etc a second time 1001 // process private-etc a second time
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt
index a76fd3765..a1eccaa5e 100644
--- a/src/man/firejail-profile.txt
+++ b/src/man/firejail-profile.txt
@@ -174,7 +174,7 @@ Example: "?HAS_APPIMAGE: whitelist ${HOME}/special/appimage/dir"
174 174
175This example will load the whitelist profile line only if the \-\-appimage option has been specified on the command line. 175This example will load the whitelist profile line only if the \-\-appimage option has been specified on the command line.
176 176
177Currently the only conditionals supported this way are HAS_APPIMAGE, HAS_NET, HAS_NODBUS, HAS_NOSOUND, HAS_PRIVATE and HAS_X11. The conditionals BROWSER_DISABLE_U2F and BROWSER_ALLOW_DRM 177Currently the only conditionals supported this way are HAS_APPIMAGE, HAS_NET, HAS_NODBUS, HAS_NOSOUND, HAS_PRIVATE and HAS_X11. The conditionals ALLOW_TRAY, BROWSER_DISABLE_U2F and BROWSER_ALLOW_DRM
178can be enabled or disabled globally in Firejail's configuration file. 178can be enabled or disabled globally in Firejail's configuration file.
179 179
180The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines. 180The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines.