aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README2
-rw-r--r--README.md84
-rwxr-xr-xconfigure54
-rw-r--r--configure.ac9
-rw-r--r--etc/inc/disable-proc.inc82
-rw-r--r--etc/inc/whitelist-run-common.inc1
-rw-r--r--etc/profile-a-l/Books.profile5
-rw-r--r--etc/profile-a-l/alienarena.profile1
-rw-r--r--etc/profile-a-l/amarok.profile2
-rw-r--r--etc/profile-a-l/blobwars.profile2
-rw-r--r--etc/profile-a-l/flameshot.profile4
-rw-r--r--etc/profile-a-l/frozen-bubble.profile1
-rw-r--r--etc/profile-a-l/funnyboat.profile1
-rw-r--r--etc/profile-a-l/gl-117.profile1
-rw-r--r--etc/profile-a-l/glaxium.profile1
-rw-r--r--etc/profile-a-l/jumpnbump-menu.profile2
-rw-r--r--etc/profile-a-l/jumpnbump.profile1
-rw-r--r--etc/profile-a-l/keepassxc.profile5
-rw-r--r--etc/profile-m-z/mrrescue.profile1
-rw-r--r--etc/profile-m-z/neochat.profile2
-rw-r--r--etc/profile-m-z/nextcloud.profile3
-rw-r--r--etc/profile-m-z/nheko.profile3
-rw-r--r--etc/profile-m-z/open-invaders.profile1
-rw-r--r--etc/profile-m-z/openclonk.profile1
-rw-r--r--etc/profile-m-z/spectral.profile8
-rw-r--r--etc/profile-m-z/supertux2.profile1
-rw-r--r--etc/profile-m-z/teeworlds.profile1
-rw-r--r--etc/profile-m-z/telegram.profile2
-rw-r--r--etc/profile-m-z/torcs.profile1
-rw-r--r--etc/profile-m-z/tremulous.profile5
-rw-r--r--etc/profile-m-z/warsow.profile8
-rw-r--r--etc/profile-m-z/xonotic.profile1
-rw-r--r--etc/templates/profile.template1
-rw-r--r--src/fbuilder/build_fs.c3
-rw-r--r--src/firejail/cgroup.c83
-rw-r--r--src/firejail/chroot.c2
-rw-r--r--src/firejail/env.c1
-rw-r--r--src/firejail/firejail.h18
-rw-r--r--src/firejail/fs.c378
-rw-r--r--src/firejail/fs_dev.c1
-rw-r--r--src/firejail/fs_home.c1
-rw-r--r--src/firejail/fs_hostname.c5
-rw-r--r--src/firejail/fs_overlayfs.c470
-rw-r--r--src/firejail/fs_trace.c5
-rw-r--r--src/firejail/fs_var.c7
-rw-r--r--src/firejail/join.c2
-rw-r--r--src/firejail/ls.c2
-rw-r--r--src/firejail/main.c16
-rw-r--r--src/firejail/mountinfo.c149
-rw-r--r--src/firejail/profile.c15
-rw-r--r--src/firejail/restrict_users.c1
-rw-r--r--src/firejail/sandbox.c2
-rw-r--r--src/firejail/util.c166
-rw-r--r--src/libtrace/libtrace.c14
-rw-r--r--src/man/firejail.txt18
55 files changed, 908 insertions, 748 deletions
diff --git a/README b/README
index 3f8eb6136..04d2c7001 100644
--- a/README
+++ b/README
@@ -310,6 +310,8 @@ DiGitHubCap (https://github.com/DiGitHubCap)
310 - fix qt5ct colour schemes and QSS 310 - fix qt5ct colour schemes and QSS
311Disconnect3d (https://github.com/disconnect3d) 311Disconnect3d (https://github.com/disconnect3d)
312 - code cleanup 312 - code cleanup
313dm9pZCAq (https://github.com/dm9pZCAq)
314 - fix for compilation under musl
313dmfreemon (https://github.com/dmfreemon) 315dmfreemon (https://github.com/dmfreemon)
314 - add sandbox name or name of private directory to the window title when xpra is used 316 - add sandbox name or name of private directory to the window title when xpra is used
315 - handle malloc() failures; use gnu_basename() instead of basenaem() 317 - handle malloc() failures; use gnu_basename() instead of basenaem()
diff --git a/README.md b/README.md
index 40c6e9d98..cf9d9563e 100644
--- a/README.md
+++ b/README.md
@@ -22,43 +22,23 @@ implemented directly in Linux kernel and available on any Linux computer.
22<table><tr> 22<table><tr>
23 23
24<td> 24<td>
25<a href="http://www.youtube.com/watch?feature=player_embedded&v=8jfXL0ePV7U 25<a href="https://www.brighteon.com/1928415c-2bce-40b2-a81f-7861a3734913" target="_blank">
26" target="_blank"><img src="http://img.youtube.com/vi/8jfXL0ePV7U/0.jpg" 26<img src="https://video.brighteon.com/file/Brighteon-staging/thumbnail/682ae17c-3fd8-4813-9c4e-6917c7cd2a5c.0000001.jpg"
27alt="Firejail Introduction" width="240" height="180" border="10" /><br/>Firejail Intro</a> 27alt="Introduction" width="240" height="142" border="10" /><br/>Introduction</a>
28</td> 28</td>
29 29
30<td> 30<td>
31<a href="http://www.youtube.com/watch?feature=player_embedded&v=J1ZsXrpAgBU 31<a href="https://www.brighteon.com/c20c32ac-1953-438f-8640-a414dcb318d6" target="_blank">
32" target="_blank"><img src="http://img.youtube.com/vi/J1ZsXrpAgBU/0.jpg" 32<img src="https://photos.brighteon.com/thumbnail/ecd8b0ca-7564-4993-a676-bbe4aa21cffc"
33alt="Firejail Demo" width="240" height="180" border="10" /><br/>Firejail Demo</a> 33alt="Technology" width="240" height="142" border="10" /><br/>Technology</a>
34</td> 34</td>
35 35
36<td> 36<td>
37<a href="http://www.youtube.com/watch?feature=player_embedded&v=EyEz65RYfw4 37<a href="https://www.brighteon.com/94ae1731-2352-4cda-bb48-7cc7a6ad32f8" target="_blank">
38" target="_blank"><img src="http://img.youtube.com/vi/EyEz65RYfw4/0.jpg" 38<img src="https://photos.brighteon.com/thumbnail/5c90254c-61f3-4927-ac57-ae279dc543cf"
39alt="Debian Install" width="240" height="180" border="10" /><br/>Debian Install</a> 39alt="Deep Dive" width="240" height="142" border="10" /><br/>Deep Dive</a>
40</td> 40</td>
41 41
42
43</tr><tr>
44<td>
45<a href="http://www.youtube.com/watch?feature=player_embedded&v=Uy2ZTHc4s0w
46" target="_blank"><img src="http://img.youtube.com/vi/Uy2ZTHc4s0w/0.jpg"
47alt="Arch Linux Install" width="240" height="180" border="10" /><br/>Arch Linux Install</a>
48
49</td>
50<td>
51<a href="http://www.youtube.com/watch?feature=player_embedded&v=xuMxRx0zSfQ
52" target="_blank"><img src="http://img.youtube.com/vi/xuMxRx0zSfQ/0.jpg"
53alt="Disable Network Access" width="240" height="180" border="10" /><br/>Disable Network Access</a>
54
55</td>
56<td>
57<a href="http://www.youtube.com/watch?feature=player_embedded&v=N-Mso2bSr3o
58" target="_blank"><img src="http://img.youtube.com/vi/N-Mso2bSr3o/0.jpg"
59alt="Firejail Security Deep Dive" width="240" height="180" border="10" /><br/>Firejail Security Deep Dive</a>
60
61</td>
62</tr></table> 42</tr></table>
63 43
64Project webpage: https://firejail.wordpress.com/ 44Project webpage: https://firejail.wordpress.com/
@@ -239,30 +219,30 @@ A small tool to print profile statistics. Compile as usual and run in /etc/profi
239$ sudo cp src/profstats/profstats /etc/firejail/. 219$ sudo cp src/profstats/profstats /etc/firejail/.
240$ cd /etc/firejail 220$ cd /etc/firejail
241$ ./profstats *.profile 221$ ./profstats *.profile
242 profiles 1150 222 profiles 1167
243 include local profile 1150 (include profile-name.local) 223 include local profile 1167 (include profile-name.local)
244 include globals 1120 (include globals.local) 224 include globals 1136 (include globals.local)
245 blacklist ~/.ssh 1026 (include disable-common.inc) 225 blacklist ~/.ssh 1042 (include disable-common.inc)
246 seccomp 1050 226 seccomp 1062
247 capabilities 1146 227 capabilities 1163
248 noexec 1030 (include disable-exec.inc) 228 noexec 1049 (include disable-exec.inc)
249 noroot 959 229 noroot 971
250 memory-deny-write-execute 253 230 memory-deny-write-execute 256
251 apparmor 681 231 apparmor 693
252 private-bin 667 232 private-bin 677
253 private-dev 1009 233 private-dev 1027
254 private-etc 523 234 private-etc 532
255 private-tmp 883 235 private-tmp 897
256 whitelist home directory 547 236 whitelist home directory 557
257 whitelist var 818 (include whitelist-var-common.inc) 237 whitelist var 836 (include whitelist-var-common.inc)
258 whitelist run/user 616 (include whitelist-runuser-common.inc 238 whitelist run/user 1137 (include whitelist-runuser-common.inc
259 or blacklist ${RUNUSER}) 239 or blacklist ${RUNUSER})
260 whitelist usr/share 591 (include whitelist-usr-share-common.inc 240 whitelist usr/share 609 (include whitelist-usr-share-common.inc
261 net none 391 241 net none 396
262 dbus-user none 641 242 dbus-user none 656
263 dbus-user filter 105 243 dbus-user filter 108
264 dbus-system none 792 244 dbus-system none 808
265 dbus-system filter 7 245 dbus-system filter 10
266``` 246```
267 247
268### New profiles: 248### New profiles:
diff --git a/configure b/configure
index 33a4ca9fb..557f5beb2 100755
--- a/configure
+++ b/configure
@@ -711,6 +711,7 @@ ac_subst_files=''
711ac_user_opts=' 711ac_user_opts='
712enable_option_checking 712enable_option_checking
713enable_analyzer 713enable_analyzer
714enable_sanitizer
714enable_apparmor 715enable_apparmor
715enable_selinux 716enable_selinux
716enable_dbusproxy 717enable_dbusproxy
@@ -1368,6 +1369,8 @@ Optional Features:
1368 --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) 1369 --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
1369 --enable-FEATURE[=ARG] include FEATURE [ARG=yes] 1370 --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
1370 --enable-analyzer enable GCC static analyzer 1371 --enable-analyzer enable GCC static analyzer
1372 --enable-sanitizer=[address | memory | undefined]
1373 enable a compiler-based sanitizer (debug)
1371 --enable-apparmor enable apparmor 1374 --enable-apparmor enable apparmor
1372 --enable-selinux SELinux labeling support 1375 --enable-selinux SELinux labeling support
1373 --disable-dbusproxy disable dbus proxy 1376 --disable-dbusproxy disable dbus proxy
@@ -3294,6 +3297,57 @@ if test "x$enable_analyzer" = "xyes"; then :
3294 3297
3295fi 3298fi
3296 3299
3300# Check whether --enable-sanitizer was given.
3301if test "${enable_sanitizer+set}" = set; then :
3302 enableval=$enable_sanitizer;
3303else
3304 enable_sanitizer=no
3305fi
3306
3307if test "x$enable_sanitizer" != "xno" ; then :
3308 as_CACHEVAR=`$as_echo "ax_cv_check_cflags__-fsanitize=$enable_sanitizer" | $as_tr_sh`
3309{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fsanitize=$enable_sanitizer" >&5
3310$as_echo_n "checking whether C compiler accepts -fsanitize=$enable_sanitizer... " >&6; }
3311if eval \${$as_CACHEVAR+:} false; then :
3312 $as_echo_n "(cached) " >&6
3313else
3314
3315 ax_check_save_flags=$CFLAGS
3316 CFLAGS="$CFLAGS -fsanitize=$enable_sanitizer"
3317 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
3318/* end confdefs.h. */
3319
3320int
3321main ()
3322{
3323
3324 ;
3325 return 0;
3326}
3327_ACEOF
3328if ac_fn_c_try_compile "$LINENO"; then :
3329 eval "$as_CACHEVAR=yes"
3330else
3331 eval "$as_CACHEVAR=no"
3332fi
3333rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
3334 CFLAGS=$ax_check_save_flags
3335fi
3336eval ac_res=\$$as_CACHEVAR
3337 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
3338$as_echo "$ac_res" >&6; }
3339if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
3340
3341 EXTRA_CFLAGS="$EXTRA_CFLAGS -fsanitize=$enable_sanitizer -fno-omit-frame-pointer"
3342 EXTRA_LDFLAGS="$EXTRA_LDFLAGS -fsanitize=$enable_sanitizer"
3343
3344else
3345 as_fn_error $? "sanitizer not supported: $enable_sanitizer" "$LINENO" 5
3346
3347fi
3348
3349fi
3350
3297HAVE_APPARMOR="" 3351HAVE_APPARMOR=""
3298# Check whether --enable-apparmor was given. 3352# Check whether --enable-apparmor was given.
3299if test "${enable_apparmor+set}" = set; then : 3353if test "${enable_apparmor+set}" = set; then :
diff --git a/configure.ac b/configure.ac
index 5fde6d402..fc5823143 100644
--- a/configure.ac
+++ b/configure.ac
@@ -45,6 +45,15 @@ AS_IF([test "x$enable_analyzer" = "xyes"], [
45 EXTRA_CFLAGS="$EXTRA_CFLAGS -fanalyzer -Wno-analyzer-malloc-leak" 45 EXTRA_CFLAGS="$EXTRA_CFLAGS -fanalyzer -Wno-analyzer-malloc-leak"
46]) 46])
47 47
48AC_ARG_ENABLE([sanitizer],
49 AS_HELP_STRING([--enable-sanitizer=@<:@address | memory | undefined@:>@], [enable a compiler-based sanitizer (debug)]), [], [enable_sanitizer=no])
50AS_IF([test "x$enable_sanitizer" != "xno" ],
51 [AX_CHECK_COMPILE_FLAG([-fsanitize=$enable_sanitizer], [
52 EXTRA_CFLAGS="$EXTRA_CFLAGS -fsanitize=$enable_sanitizer -fno-omit-frame-pointer"
53 EXTRA_LDFLAGS="$EXTRA_LDFLAGS -fsanitize=$enable_sanitizer"
54 ], [AC_MSG_ERROR([sanitizer not supported: $enable_sanitizer])]
55)])
56
48HAVE_APPARMOR="" 57HAVE_APPARMOR=""
49AC_ARG_ENABLE([apparmor], 58AC_ARG_ENABLE([apparmor],
50 AS_HELP_STRING([--enable-apparmor], [enable apparmor])) 59 AS_HELP_STRING([--enable-apparmor], [enable apparmor]))
diff --git a/etc/inc/disable-proc.inc b/etc/inc/disable-proc.inc
new file mode 100644
index 000000000..81a8883f3
--- /dev/null
+++ b/etc/inc/disable-proc.inc
@@ -0,0 +1,82 @@
1# This file is overwritten during software install.
2# Persistent customizations should go in a .local file.
3include disable-proc.local
4
5blacklist /proc/acpi
6blacklist /proc/asound
7blacklist /proc/bootconfig
8blacklist /proc/buddyinfo
9blacklist /proc/cgroups
10blacklist /proc/cmdline
11blacklist /proc/config.gz
12blacklist /proc/consoles
13#blacklist /proc/cpuinfo
14blacklist /proc/crypto
15blacklist /proc/devices
16blacklist /proc/diskstats
17blacklist /proc/dma
18#blacklist /proc/driver
19blacklist /proc/dynamic_debug
20blacklist /proc/execdomains
21blacklist /proc/fb
22#blacklist /proc/filesystems
23blacklist /proc/fs
24blacklist /proc/i8k
25blacklist /proc/interrupts
26blacklist /proc/iomem
27blacklist /proc/ioports
28blacklist /proc/irq
29blacklist /proc/kallsyms
30blacklist /proc/kcore
31blacklist /proc/keys
32blacklist /proc/key-users
33blacklist /proc/kmsg
34blacklist /proc/kpagecgroup
35blacklist /proc/kpagecount
36blacklist /proc/kpageflags
37blacklist /proc/latency_stats
38#blacklist /proc/loadavg
39blacklist /proc/locks
40blacklist /proc/mdstat
41#blacklist /proc/meminfo
42blacklist /proc/misc
43#blacklist /proc/modules
44#blacklist /proc/mounts
45blacklist /proc/mtrr
46#blacklist /proc/net
47blacklist /proc/partitions
48blacklist /proc/pressure
49blacklist /proc/sched_debug
50blacklist /proc/schedstat
51blacklist /proc/scsi
52#blacklist /proc/self
53blacklist /proc/slabinfo
54blacklist /proc/softirqs
55blacklist /proc/spl
56#blacklist /proc/stat
57blacklist /proc/swaps
58#blacklist /proc/sys
59blacklist /proc/sysrq-trigger
60blacklist /proc/sysvipc
61#blacklist /proc/thread-self
62blacklist /proc/timer_list
63blacklist /proc/tty
64#blacklist /proc/uptime
65#blacklist /proc/version
66blacklist /proc/version_signature
67blacklist /proc/vmallocinfo
68#blacklist /proc/vmstat
69#blacklist /proc/zoneinfo
70
71blacklist /proc/sys/abi
72blacklist /proc/sys/crypto
73blacklist /proc/sys/debug
74blacklist /proc/sys/dev
75blacklist /proc/sys/fs
76blacklist /proc/sys/net
77blacklist /proc/sys/user
78blacklist /proc/sys/vm
79
80noblacklist /proc/sys/kernel/osrelease
81noblacklist /proc/sys/kernel/yama
82blacklist /proc/sys/*/*
diff --git a/etc/inc/whitelist-run-common.inc b/etc/inc/whitelist-run-common.inc
index 224d21064..0d87657a9 100644
--- a/etc/inc/whitelist-run-common.inc
+++ b/etc/inc/whitelist-run-common.inc
@@ -7,5 +7,6 @@ whitelist /run/cups/cups.sock
7whitelist /run/dbus/system_bus_socket 7whitelist /run/dbus/system_bus_socket
8whitelist /run/media 8whitelist /run/media
9whitelist /run/resolvconf/resolv.conf 9whitelist /run/resolvconf/resolv.conf
10whitelist /run/shm
10whitelist /run/systemd/resolve/resolv.conf 11whitelist /run/systemd/resolve/resolv.conf
11whitelist /run/systemd/resolve/stub-resolv.conf 12whitelist /run/systemd/resolve/stub-resolv.conf
diff --git a/etc/profile-a-l/Books.profile b/etc/profile-a-l/Books.profile
index 76fd21d32..a256e942f 100644
--- a/etc/profile-a-l/Books.profile
+++ b/etc/profile-a-l/Books.profile
@@ -1,5 +1,10 @@
1# Firejail profile for gnome-books 1# Firejail profile for gnome-books
2# This file is overwritten after every install/update 2# This file is overwritten after every install/update
3# Persistent local customizations
4include Books.local
5# Persistent global definitions
6# added by included profile
7#include globals.local
3 8
4 9
5# Temporary fix for https://github.com/netblue30/firejail/issues/2624 10# Temporary fix for https://github.com/netblue30/firejail/issues/2624
diff --git a/etc/profile-a-l/alienarena.profile b/etc/profile-a-l/alienarena.profile
index 62857a3e2..68512e37b 100644
--- a/etc/profile-a-l/alienarena.profile
+++ b/etc/profile-a-l/alienarena.profile
@@ -29,7 +29,6 @@ caps.drop all
29netfilter 29netfilter
30nodvd 30nodvd
31nogroups 31nogroups
32noinput
33nonewprivs 32nonewprivs
34noroot 33noroot
35notv 34notv
diff --git a/etc/profile-a-l/amarok.profile b/etc/profile-a-l/amarok.profile
index e7b78f7d0..7d8ec481d 100644
--- a/etc/profile-a-l/amarok.profile
+++ b/etc/profile-a-l/amarok.profile
@@ -39,7 +39,7 @@ dbus-user.own org.kde.amarok
39dbus-user.own org.mpris.amarok 39dbus-user.own org.mpris.amarok
40dbus-user.own org.mpris.MediaPlayer2.amarok 40dbus-user.own org.mpris.MediaPlayer2.amarok
41dbus-user.talk org.freedesktop.Notifications 41dbus-user.talk org.freedesktop.Notifications
42dbus-user.talk org.kde.StatusNotifierWatcher 42?ALLOW_TRAY: dbus-user.talk org.kde.StatusNotifierWatcher
43# If you're not on kde-plasma add the next lines to your amarok.local. 43# If you're not on kde-plasma add the next lines to your amarok.local.
44#dbus-user.own org.kde.kded 44#dbus-user.own org.kde.kded
45#dbus-user.own org.kde.klauncher 45#dbus-user.own org.kde.klauncher
diff --git a/etc/profile-a-l/blobwars.profile b/etc/profile-a-l/blobwars.profile
index 683a7858b..66f38b358 100644
--- a/etc/profile-a-l/blobwars.profile
+++ b/etc/profile-a-l/blobwars.profile
@@ -19,6 +19,7 @@ include disable-xdg.inc
19mkdir ${HOME}/.parallelrealities/blobwars 19mkdir ${HOME}/.parallelrealities/blobwars
20whitelist ${HOME}/.parallelrealities/blobwars 20whitelist ${HOME}/.parallelrealities/blobwars
21whitelist /usr/share/blobwars 21whitelist /usr/share/blobwars
22whitelist /usr/share/games/blobwars
22include whitelist-common.inc 23include whitelist-common.inc
23include whitelist-usr-share-common.inc 24include whitelist-usr-share-common.inc
24include whitelist-var-common.inc 25include whitelist-var-common.inc
@@ -28,7 +29,6 @@ caps.drop all
28net none 29net none
29nodvd 30nodvd
30nogroups 31nogroups
31noinput
32nonewprivs 32nonewprivs
33noroot 33noroot
34notv 34notv
diff --git a/etc/profile-a-l/flameshot.profile b/etc/profile-a-l/flameshot.profile
index 5c7bc03d8..862ef6ab6 100644
--- a/etc/profile-a-l/flameshot.profile
+++ b/etc/profile-a-l/flameshot.profile
@@ -63,6 +63,6 @@ dbus-user.talk org.freedesktop.Notifications
63dbus-user.talk org.freedesktop.portal.Desktop 63dbus-user.talk org.freedesktop.portal.Desktop
64dbus-user.talk org.gnome.Shell 64dbus-user.talk org.gnome.Shell
65dbus-user.talk org.kde.KWin 65dbus-user.talk org.kde.KWin
66dbus-user.talk org.kde.StatusNotifierWatcher 66?ALLOW_TRAY: dbus-user.talk org.kde.StatusNotifierWatcher
67dbus-user.own org.kde.* 67?ALLOW_TRAY: dbus-user.own org.kde.*
68dbus-system none 68dbus-system none
diff --git a/etc/profile-a-l/frozen-bubble.profile b/etc/profile-a-l/frozen-bubble.profile
index bb35c9447..88943760a 100644
--- a/etc/profile-a-l/frozen-bubble.profile
+++ b/etc/profile-a-l/frozen-bubble.profile
@@ -30,7 +30,6 @@ caps.drop all
30net none 30net none
31nodvd 31nodvd
32nogroups 32nogroups
33noinput
34nonewprivs 33nonewprivs
35noroot 34noroot
36notv 35notv
diff --git a/etc/profile-a-l/funnyboat.profile b/etc/profile-a-l/funnyboat.profile
index 1009f345b..4a08fca9b 100644
--- a/etc/profile-a-l/funnyboat.profile
+++ b/etc/profile-a-l/funnyboat.profile
@@ -35,7 +35,6 @@ ipc-namespace
35netfilter 35netfilter
36nodvd 36nodvd
37nogroups 37nogroups
38noinput
39nonewprivs 38nonewprivs
40noroot 39noroot
41notv 40notv
diff --git a/etc/profile-a-l/gl-117.profile b/etc/profile-a-l/gl-117.profile
index 35d969e6d..edb85048b 100644
--- a/etc/profile-a-l/gl-117.profile
+++ b/etc/profile-a-l/gl-117.profile
@@ -29,7 +29,6 @@ caps.drop all
29net none 29net none
30nodvd 30nodvd
31nogroups 31nogroups
32noinput
33nonewprivs 32nonewprivs
34noroot 33noroot
35notv 34notv
diff --git a/etc/profile-a-l/glaxium.profile b/etc/profile-a-l/glaxium.profile
index dec0daef2..b5f98b411 100644
--- a/etc/profile-a-l/glaxium.profile
+++ b/etc/profile-a-l/glaxium.profile
@@ -29,7 +29,6 @@ caps.drop all
29net none 29net none
30nodvd 30nodvd
31nogroups 31nogroups
32noinput
33nonewprivs 32nonewprivs
34noroot 33noroot
35notv 34notv
diff --git a/etc/profile-a-l/jumpnbump-menu.profile b/etc/profile-a-l/jumpnbump-menu.profile
index 8d391b90f..59d762f55 100644
--- a/etc/profile-a-l/jumpnbump-menu.profile
+++ b/etc/profile-a-l/jumpnbump-menu.profile
@@ -10,7 +10,7 @@ include jumpnbump-menu.local
10# Allow python (blacklisted by disable-interpreters.inc) 10# Allow python (blacklisted by disable-interpreters.inc)
11include allow-python3.inc 11include allow-python3.inc
12 12
13private-bin jumpnbump-menu,python3* 13private-bin env,jumpnbump-menu,python3*
14 14
15# Redirect 15# Redirect
16include jumpnbump.profile 16include jumpnbump.profile
diff --git a/etc/profile-a-l/jumpnbump.profile b/etc/profile-a-l/jumpnbump.profile
index b9bc8f219..9726ff6fe 100644
--- a/etc/profile-a-l/jumpnbump.profile
+++ b/etc/profile-a-l/jumpnbump.profile
@@ -27,7 +27,6 @@ caps.drop all
27net none 27net none
28nodvd 28nodvd
29nogroups 29nogroups
30noinput
31nonewprivs 30nonewprivs
32noroot 31noroot
33notv 32notv
diff --git a/etc/profile-a-l/keepassxc.profile b/etc/profile-a-l/keepassxc.profile
index 0f3e6605b..45a707071 100644
--- a/etc/profile-a-l/keepassxc.profile
+++ b/etc/profile-a-l/keepassxc.profile
@@ -98,11 +98,10 @@ dbus-user.talk org.freedesktop.ScreenSaver
98dbus-user.talk org.gnome.ScreenSaver 98dbus-user.talk org.gnome.ScreenSaver
99dbus-user.talk org.gnome.SessionManager 99dbus-user.talk org.gnome.SessionManager
100dbus-user.talk org.xfce.ScreenSaver 100dbus-user.talk org.xfce.ScreenSaver
101?ALLOW_TRAY: dbus-user.talk org.kde.StatusNotifierWatcher
102?ALLOW_TRAY: dbus-user.own org.kde.*
101# Add the next line to your keepassxc.local to allow notifications. 103# Add the next line to your keepassxc.local to allow notifications.
102#dbus-user.talk org.freedesktop.Notifications 104#dbus-user.talk org.freedesktop.Notifications
103# Add the next line to your keepassxc.local to allow the tray menu.
104#dbus-user.talk org.kde.StatusNotifierWatcher
105#dbus-user.own org.kde.*
106dbus-system filter 105dbus-system filter
107dbus-system.talk org.freedesktop.login1 106dbus-system.talk org.freedesktop.login1
108 107
diff --git a/etc/profile-m-z/mrrescue.profile b/etc/profile-m-z/mrrescue.profile
index 16dc97d0c..5b5902563 100644
--- a/etc/profile-m-z/mrrescue.profile
+++ b/etc/profile-m-z/mrrescue.profile
@@ -37,7 +37,6 @@ caps.drop all
37net none 37net none
38nodvd 38nodvd
39nogroups 39nogroups
40noinput
41nonewprivs 40nonewprivs
42noroot 41noroot
43notv 42notv
diff --git a/etc/profile-m-z/neochat.profile b/etc/profile-m-z/neochat.profile
index 58cc716d9..0f55b674f 100644
--- a/etc/profile-m-z/neochat.profile
+++ b/etc/profile-m-z/neochat.profile
@@ -60,6 +60,6 @@ private-tmp
60dbus-user filter 60dbus-user filter
61dbus-user.own org.kde.neochat 61dbus-user.own org.kde.neochat
62dbus-user.talk org.freedesktop.Notifications 62dbus-user.talk org.freedesktop.Notifications
63dbus-user.talk org.kde.StatusNotifierWatcher 63?ALLOW_TRAY: dbus-user.talk org.kde.StatusNotifierWatcher
64dbus-user.talk org.kde.kwalletd5 64dbus-user.talk org.kde.kwalletd5
65dbus-system none 65dbus-system none
diff --git a/etc/profile-m-z/nextcloud.profile b/etc/profile-m-z/nextcloud.profile
index d0eef9704..354d3351e 100644
--- a/etc/profile-m-z/nextcloud.profile
+++ b/etc/profile-m-z/nextcloud.profile
@@ -67,6 +67,5 @@ private-tmp
67 67
68dbus-user filter 68dbus-user filter
69dbus-user.talk org.freedesktop.secrets 69dbus-user.talk org.freedesktop.secrets
70# Add the next line to your nextcloud.local for tray icon support 70?ALLOW_TRAY: dbus-user.talk org.kde.StatusNotifierWatcher
71#dbus-user.talk org.kde.StatusNotifierWatcher
72dbus-system none 71dbus-system none
diff --git a/etc/profile-m-z/nheko.profile b/etc/profile-m-z/nheko.profile
index 2f305dae9..89a146a09 100644
--- a/etc/profile-m-z/nheko.profile
+++ b/etc/profile-m-z/nheko.profile
@@ -53,8 +53,7 @@ private-tmp
53 53
54dbus-user filter 54dbus-user filter
55dbus-user.talk org.freedesktop.secrets 55dbus-user.talk org.freedesktop.secrets
56?ALLOW_TRAY: dbus-user.talk org.kde.StatusNotifierWatcher
56# Add the next line to your nheko.local to enable notification support. 57# Add the next line to your nheko.local to enable notification support.
57#dbus-user.talk org.freedesktop.Notifications 58#dbus-user.talk org.freedesktop.Notifications
58# Add the next line to your nheko.local to enable tray icon support.
59#dbus-user.talk org.kde.StatusNotifierWatcher
60dbus-system none 59dbus-system none
diff --git a/etc/profile-m-z/open-invaders.profile b/etc/profile-m-z/open-invaders.profile
index 12c7ea3d0..c2c22f42d 100644
--- a/etc/profile-m-z/open-invaders.profile
+++ b/etc/profile-m-z/open-invaders.profile
@@ -25,7 +25,6 @@ caps.drop all
25net none 25net none
26nodvd 26nodvd
27nogroups 27nogroups
28noinput
29nonewprivs 28nonewprivs
30noroot 29noroot
31notv 30notv
diff --git a/etc/profile-m-z/openclonk.profile b/etc/profile-m-z/openclonk.profile
index 253465991..68362cbc8 100644
--- a/etc/profile-m-z/openclonk.profile
+++ b/etc/profile-m-z/openclonk.profile
@@ -28,7 +28,6 @@ ipc-namespace
28netfilter 28netfilter
29nodvd 29nodvd
30nogroups 30nogroups
31noinput
32nonewprivs 31nonewprivs
33noroot 32noroot
34notv 33notv
diff --git a/etc/profile-m-z/spectral.profile b/etc/profile-m-z/spectral.profile
index 5f17b73dc..3f7f68009 100644
--- a/etc/profile-m-z/spectral.profile
+++ b/etc/profile-m-z/spectral.profile
@@ -49,10 +49,8 @@ private-dev
49private-etc alsa,alternatives,asound.conf,ca-certificates,crypto-policies,fonts,gtk-2.0,gtk-3.0,host.conf,hostname,hosts,ld.so.cache,ld.so.conf,ld.so.conf.d,ld.so.preload,locale,locale.alias,locale.conf,mime.types,nsswitch.conf,pki,pulse,resolv.conf,selinux,ssl,X11,xdg 49private-etc alsa,alternatives,asound.conf,ca-certificates,crypto-policies,fonts,gtk-2.0,gtk-3.0,host.conf,hostname,hosts,ld.so.cache,ld.so.conf,ld.so.conf.d,ld.so.preload,locale,locale.alias,locale.conf,mime.types,nsswitch.conf,pki,pulse,resolv.conf,selinux,ssl,X11,xdg
50private-tmp 50private-tmp
51 51
52dbus-user none 52dbus-user filter
53# Add the next lines to your spectral.local to enable notification support. 53?ALLOW_TRAY: dbus-user.talk org.kde.StatusNotifierWatcher
54#ignore dbus-user none 54# Add the next line to your spectral.local to enable notification support.
55#dbus-user filter
56#dbus-user.talk org.freedesktop.Notifications 55#dbus-user.talk org.freedesktop.Notifications
57#dbus-user.talk org.kde.StatusNotifierWatcher
58dbus-system none 56dbus-system none
diff --git a/etc/profile-m-z/supertux2.profile b/etc/profile-m-z/supertux2.profile
index 323849e35..d48065c4b 100644
--- a/etc/profile-m-z/supertux2.profile
+++ b/etc/profile-m-z/supertux2.profile
@@ -30,7 +30,6 @@ caps.drop all
30net none 30net none
31nodvd 31nodvd
32nogroups 32nogroups
33noinput
34nonewprivs 33nonewprivs
35noroot 34noroot
36notv 35notv
diff --git a/etc/profile-m-z/teeworlds.profile b/etc/profile-m-z/teeworlds.profile
index df54fb9ba..d0fb0d43e 100644
--- a/etc/profile-m-z/teeworlds.profile
+++ b/etc/profile-m-z/teeworlds.profile
@@ -26,7 +26,6 @@ ipc-namespace
26netfilter 26netfilter
27nodvd 27nodvd
28nogroups 28nogroups
29noinput
30nonewprivs 29nonewprivs
31noroot 30noroot
32notv 31notv
diff --git a/etc/profile-m-z/telegram.profile b/etc/profile-m-z/telegram.profile
index fd4b82524..dc1f77664 100644
--- a/etc/profile-m-z/telegram.profile
+++ b/etc/profile-m-z/telegram.profile
@@ -50,7 +50,7 @@ private-tmp
50dbus-user filter 50dbus-user filter
51dbus-user.own org.telegram.desktop.* 51dbus-user.own org.telegram.desktop.*
52dbus-user.talk org.freedesktop.Notifications 52dbus-user.talk org.freedesktop.Notifications
53dbus-user.talk org.kde.StatusNotifierWatcher 53?ALLOW_TRAY: dbus-user.talk org.kde.StatusNotifierWatcher
54dbus-user.talk org.gnome.Mutter.IdleMonitor 54dbus-user.talk org.gnome.Mutter.IdleMonitor
55dbus-user.talk org.freedesktop.ScreenSaver 55dbus-user.talk org.freedesktop.ScreenSaver
56dbus-system none 56dbus-system none
diff --git a/etc/profile-m-z/torcs.profile b/etc/profile-m-z/torcs.profile
index a7ebaf2af..19e586db4 100644
--- a/etc/profile-m-z/torcs.profile
+++ b/etc/profile-m-z/torcs.profile
@@ -28,7 +28,6 @@ ipc-namespace
28net none 28net none
29nodvd 29nodvd
30nogroups 30nogroups
31noinput
32nonewprivs 31nonewprivs
33noroot 32noroot
34notv 33notv
diff --git a/etc/profile-m-z/tremulous.profile b/etc/profile-m-z/tremulous.profile
index 4e16df553..96541ae25 100644
--- a/etc/profile-m-z/tremulous.profile
+++ b/etc/profile-m-z/tremulous.profile
@@ -8,6 +8,9 @@ include globals.local
8 8
9noblacklist ${HOME}/.tremulous 9noblacklist ${HOME}/.tremulous
10 10
11# Allow /bin/sh (blacklisted by disable-shell.inc)
12include allow-bin-sh.inc
13
11include disable-common.inc 14include disable-common.inc
12include disable-devel.inc 15include disable-devel.inc
13include disable-exec.inc 16include disable-exec.inc
@@ -41,7 +44,7 @@ shell none
41tracelog 44tracelog
42 45
43disable-mnt 46disable-mnt
44private-bin tremded,tremulous,tremulous-wrapper 47private-bin env,sh,tremded,tremulous,tremulous-wrapper
45private-cache 48private-cache
46private-dev 49private-dev
47private-tmp 50private-tmp
diff --git a/etc/profile-m-z/warsow.profile b/etc/profile-m-z/warsow.profile
index 5659ec69c..2f818b733 100644
--- a/etc/profile-m-z/warsow.profile
+++ b/etc/profile-m-z/warsow.profile
@@ -11,6 +11,9 @@ ignore noexec ${HOME}
11noblacklist ${HOME}/.cache/warsow-2.1 11noblacklist ${HOME}/.cache/warsow-2.1
12noblacklist ${HOME}/.local/share/warsow-2.1 12noblacklist ${HOME}/.local/share/warsow-2.1
13 13
14# Allow /bin/sh (blacklisted by disable-shell.inc)
15include allow-bin-sh.inc
16
14include disable-common.inc 17include disable-common.inc
15include disable-devel.inc 18include disable-devel.inc
16include disable-exec.inc 19include disable-exec.inc
@@ -34,19 +37,18 @@ ipc-namespace
34netfilter 37netfilter
35nodvd 38nodvd
36nogroups 39nogroups
37noinput
38nonewprivs 40nonewprivs
39noroot 41noroot
40notv 42notv
41nou2f 43nou2f
42novideo 44novideo
43protocol unix,inet,inet6 45protocol unix,inet,inet6,netlink
44seccomp 46seccomp
45shell none 47shell none
46tracelog 48tracelog
47 49
48disable-mnt 50disable-mnt
49private-bin warsow 51private-bin basename,bash,dirname,sed,sh,uname,warsow
50private-cache 52private-cache
51private-dev 53private-dev
52private-tmp 54private-tmp
diff --git a/etc/profile-m-z/xonotic.profile b/etc/profile-m-z/xonotic.profile
index 6ffe9ece9..7c2b38d1d 100644
--- a/etc/profile-m-z/xonotic.profile
+++ b/etc/profile-m-z/xonotic.profile
@@ -32,7 +32,6 @@ caps.drop all
32netfilter 32netfilter
33nodvd 33nodvd
34nogroups 34nogroups
35noinput
36nonewprivs 35nonewprivs
37noroot 36noroot
38notv 37notv
diff --git a/etc/templates/profile.template b/etc/templates/profile.template
index 7628313e0..44197b547 100644
--- a/etc/templates/profile.template
+++ b/etc/templates/profile.template
@@ -116,6 +116,7 @@ include globals.local
116#include disable-devel.inc 116#include disable-devel.inc
117#include disable-exec.inc 117#include disable-exec.inc
118#include disable-interpreters.inc 118#include disable-interpreters.inc
119#include disable-proc.inc
119#include disable-programs.inc 120#include disable-programs.inc
120#include disable-shell.inc 121#include disable-shell.inc
121#include disable-write-mnt.inc 122#include disable-write-mnt.inc
diff --git a/src/fbuilder/build_fs.c b/src/fbuilder/build_fs.c
index 8700e0ba1..a1847284c 100644
--- a/src/fbuilder/build_fs.c
+++ b/src/fbuilder/build_fs.c
@@ -236,9 +236,6 @@ void build_share(const char *fname, FILE *fp) {
236//******************************************* 236//*******************************************
237static FileDB *tmp_out = NULL; 237static FileDB *tmp_out = NULL;
238static void tmp_callback(char *ptr) { 238static void tmp_callback(char *ptr) {
239 // skip strace file
240 if (strncmp(ptr, "/tmp/firejail-strace", 20) == 0)
241 return;
242 if (strncmp(ptr, "/tmp/runtime-", 13) == 0) 239 if (strncmp(ptr, "/tmp/runtime-", 13) == 0)
243 return; 240 return;
244 if (strcmp(ptr, "/tmp") == 0) 241 if (strcmp(ptr, "/tmp") == 0)
diff --git a/src/firejail/cgroup.c b/src/firejail/cgroup.c
index e7ffbca36..38b3c32d3 100644
--- a/src/firejail/cgroup.c
+++ b/src/firejail/cgroup.c
@@ -18,7 +18,8 @@
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/ 19*/
20#include "firejail.h" 20#include "firejail.h"
21#include <sys/stat.h> 21#include <sys/wait.h>
22#include <errno.h>
22 23
23#define MAXBUF 4096 24#define MAXBUF 4096
24 25
@@ -68,52 +69,60 @@ errout:
68 fclose(fp); 69 fclose(fp);
69} 70}
70 71
72static int is_cgroup_path(const char *fname) {
73 // path starts with /sys/fs/cgroup
74 if (strncmp(fname, "/sys/fs/cgroup", 14) != 0)
75 return 0;
71 76
72void set_cgroup(const char *path) { 77 // no .. traversal
73 EUID_ASSERT(); 78 char *ptr = strstr(fname, "..");
79 if (ptr)
80 return 0;
74 81
75 invalid_filename(path, 0); // no globbing 82 return 1;
83}
76 84
77 // path starts with /sys/fs/cgroup 85void check_cgroup_file(const char *fname) {
78 if (strncmp(path, "/sys/fs/cgroup", 14) != 0) 86 assert(fname);
79 goto errout; 87 invalid_filename(fname, 0); // no globbing
80 88
81 // path ends in tasks 89 if (!is_cgroup_path(fname))
82 char *ptr = strstr(path, "tasks");
83 if (!ptr)
84 goto errout;
85 if (*(ptr + 5) != '\0')
86 goto errout; 90 goto errout;
87 91
88 // no .. traversal 92 const char *base = gnu_basename(fname);
89 ptr = strstr(path, ".."); 93 if (strcmp(base, "tasks") != 0 && // cgroup v1
90 if (ptr) 94 strcmp(base, "cgroup.procs") != 0)
91 goto errout; 95 goto errout;
92 96
93 // tasks file exists 97 if (access(fname, W_OK) == 0)
94 FILE *fp = fopen(path, "ae"); 98 return;
95 if (!fp)
96 goto errout;
97 // task file belongs to the user running the sandbox
98 int fd = fileno(fp);
99 if (fd == -1)
100 errExit("fileno");
101 struct stat s;
102 if (fstat(fd, &s) == -1)
103 errExit("fstat");
104 if (s.st_uid != getuid() && s.st_gid != getgid())
105 goto errout2;
106 // add the task to cgroup
107 pid_t pid = getpid();
108 int rv = fprintf(fp, "%d\n", pid);
109 (void) rv;
110 fclose(fp);
111 return;
112 99
113errout: 100errout:
114 fprintf(stderr, "Error: invalid cgroup\n"); 101 fprintf(stderr, "Error: invalid cgroup\n");
115 exit(1); 102 exit(1);
116errout2: 103}
117 fprintf(stderr, "Error: you don't have permissions to use this control group\n"); 104
118 exit(1); 105static void do_set_cgroup(const char *fname, pid_t pid) {
106 FILE *fp = fopen(fname, "ae");
107 if (!fp) {
108 fwarning("cannot open %s for writing: %s\n", fname, strerror(errno));
109 return;
110 }
111
112 int rv = fprintf(fp, "%d\n", pid);
113 (void) rv;
114 fclose(fp);
115}
116
117void set_cgroup(const char *fname, pid_t pid) {
118 pid_t child = fork();
119 if (child < 0)
120 errExit("fork");
121 if (child == 0) {
122 drop_privs(0);
123
124 do_set_cgroup(fname, pid);
125 _exit(0);
126 }
127 waitpid(child, NULL, 0);
119} 128}
diff --git a/src/firejail/chroot.c b/src/firejail/chroot.c
index 37ec22117..9425638ea 100644
--- a/src/firejail/chroot.c
+++ b/src/firejail/chroot.c
@@ -86,7 +86,7 @@ static void update_file(int parentfd, const char *relpath) {
86 if (arg_debug) 86 if (arg_debug)
87 printf("Updating chroot /%s\n", relpath); 87 printf("Updating chroot /%s\n", relpath);
88 unlinkat(parentfd, relpath, 0); 88 unlinkat(parentfd, relpath, 0);
89 int out = openat(parentfd, relpath, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); 89 int out = openat(parentfd, relpath, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
90 if (out == -1) { 90 if (out == -1) {
91 close(in); 91 close(in);
92 goto errout; 92 goto errout;
diff --git a/src/firejail/env.c b/src/firejail/env.c
index ad16de037..4c0d729a1 100644
--- a/src/firejail/env.c
+++ b/src/firejail/env.c
@@ -22,6 +22,7 @@
22#include <sys/stat.h> 22#include <sys/stat.h>
23#include <unistd.h> 23#include <unistd.h>
24#include <dirent.h> 24#include <dirent.h>
25#include <limits.h>
25 26
26typedef struct env_t { 27typedef struct env_t {
27 struct env_t *next; 28 struct env_t *next;
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 730c37aed..a6924b830 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -22,6 +22,7 @@
22#include "../include/common.h" 22#include "../include/common.h"
23#include "../include/euid_common.h" 23#include "../include/euid_common.h"
24#include "../include/rundefs.h" 24#include "../include/rundefs.h"
25#include <linux/limits.h> // Note: Plain limits.h may break ARG_MAX (see #4583)
25#include <stdarg.h> 26#include <stdarg.h>
26#include <sys/stat.h> 27#include <sys/stat.h>
27 28
@@ -433,13 +434,15 @@ void fs_proc_sys_dev_boot(void);
433void disable_config(void); 434void disable_config(void);
434// build a basic read-only filesystem 435// build a basic read-only filesystem
435void fs_basic_fs(void); 436void fs_basic_fs(void);
436// mount overlayfs on top of / directory
437char *fs_check_overlay_dir(const char *subdirname, int allow_reuse);
438void fs_overlayfs(void);
439void fs_private_tmp(void); 437void fs_private_tmp(void);
440void fs_private_cache(void); 438void fs_private_cache(void);
441void fs_mnt(const int enforce); 439void fs_mnt(const int enforce);
442 440
441// fs_overlayfs.c
442char *fs_check_overlay_dir(const char *subdirname, int allow_reuse);
443void fs_overlayfs(void);
444int remove_overlay_directory(void);
445
443// chroot.c 446// chroot.c
444// chroot into an existing directory; mount existing /dev and update /etc/resolv.conf 447// chroot into an existing directory; mount existing /dev and update /etc/resolv.conf
445void fs_check_chroot_dir(void); 448void fs_check_chroot_dir(void);
@@ -516,6 +519,7 @@ void touch_file_as_user(const char *fname, mode_t mode);
516int is_dir(const char *fname); 519int is_dir(const char *fname);
517int is_link(const char *fname); 520int is_link(const char *fname);
518char *realpath_as_user(const char *fname); 521char *realpath_as_user(const char *fname);
522ssize_t readlink_as_user(const char *fname, char *buf, size_t sz);
519int stat_as_user(const char *fname, struct stat *s); 523int stat_as_user(const char *fname, struct stat *s);
520int lstat_as_user(const char *fname, struct stat *s); 524int lstat_as_user(const char *fname, struct stat *s);
521void trim_trailing_slash_or_dot(char *path); 525void trim_trailing_slash_or_dot(char *path);
@@ -529,8 +533,7 @@ void update_map(char *mapping, char *map_file);
529void wait_for_other(int fd); 533void wait_for_other(int fd);
530void notify_other(int fd); 534void notify_other(int fd);
531uid_t pid_get_uid(pid_t pid); 535uid_t pid_get_uid(pid_t pid);
532uid_t get_group_id(const char *group); 536gid_t get_group_id(const char *groupname);
533int remove_overlay_directory(void);
534void flush_stdin(void); 537void flush_stdin(void);
535int create_empty_dir_as_user(const char *dir, mode_t mode); 538int create_empty_dir_as_user(const char *dir, mode_t mode);
536void create_empty_dir_as_root(const char *dir, mode_t mode); 539void create_empty_dir_as_root(const char *dir, mode_t mode);
@@ -564,7 +567,7 @@ typedef struct {
564// mountinfo.c 567// mountinfo.c
565MountData *get_last_mount(void); 568MountData *get_last_mount(void);
566int get_mount_id(int fd); 569int get_mount_id(int fd);
567char **build_mount_array(const int mount_id, const char *path); 570char **build_mount_array(const int mountid, const char *path);
568 571
569// fs_var.c 572// fs_var.c
570void fs_var_log(void); // mounting /var/log 573void fs_var_log(void); // mounting /var/log
@@ -645,7 +648,8 @@ void cpu_print_filter(pid_t pid) __attribute__((noreturn));
645// cgroup.c 648// cgroup.c
646void save_cgroup(void); 649void save_cgroup(void);
647void load_cgroup(const char *fname); 650void load_cgroup(const char *fname);
648void set_cgroup(const char *path); 651void check_cgroup_file(const char *fname);
652void set_cgroup(const char *fname, pid_t pid);
649 653
650// output.c 654// output.c
651void check_output(int argc, char **argv); 655void check_output(int argc, char **argv);
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index 3144156a3..9c1b889ed 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -20,10 +20,7 @@
20#include "firejail.h" 20#include "firejail.h"
21#include "../include/gcov_wrapper.h" 21#include "../include/gcov_wrapper.h"
22#include <sys/mount.h> 22#include <sys/mount.h>
23#include <sys/stat.h>
24#include <sys/statvfs.h> 23#include <sys/statvfs.h>
25#include <sys/wait.h>
26#include <linux/limits.h>
27#include <fnmatch.h> 24#include <fnmatch.h>
28#include <glob.h> 25#include <glob.h>
29#include <dirent.h> 26#include <dirent.h>
@@ -35,7 +32,7 @@
35#endif 32#endif
36 33
37#define MAX_BUF 4096 34#define MAX_BUF 4096
38#define EMPTY_STRING ("") 35
39// check noblacklist statements not matched by a proper blacklist in disable-*.inc files 36// check noblacklist statements not matched by a proper blacklist in disable-*.inc files
40//#define TEST_NO_BLACKLIST_MATCHING 37//#define TEST_NO_BLACKLIST_MATCHING
41 38
@@ -657,12 +654,13 @@ static void fs_remount_rec(const char *path, OPERATION op) {
657 654
658 // build array with all mount points that need to get remounted 655 // build array with all mount points that need to get remounted
659 char **arr = build_mount_array(mountid, path); 656 char **arr = build_mount_array(mountid, path);
660 assert(arr); 657 if (!arr)
658 return;
661 // remount 659 // remount
662 char **tmp = arr; 660 int i;
663 while (*tmp) { 661 for (i = 0; arr[i]; i++) {
664 fs_remount_simple(*tmp, op); 662 fs_remount_simple(arr[i], op);
665 free(*tmp++); 663 free(arr[i]);
666 } 664 }
667 free(arr); 665 free(arr);
668} 666}
@@ -897,367 +895,6 @@ void fs_basic_fs(void) {
897} 895}
898 896
899 897
900
901#ifdef HAVE_OVERLAYFS
902char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) {
903 assert(subdirname);
904 EUID_ASSERT();
905 struct stat s;
906 char *dirname;
907
908 if (asprintf(&dirname, "%s/.firejail", cfg.homedir) == -1)
909 errExit("asprintf");
910 // check if ~/.firejail already exists
911 if (lstat(dirname, &s) == 0) {
912 if (!S_ISDIR(s.st_mode)) {
913 if (S_ISLNK(s.st_mode))
914 fprintf(stderr, "Error: %s is a symbolic link\n", dirname);
915 else
916 fprintf(stderr, "Error: %s is not a directory\n", dirname);
917 exit(1);
918 }
919 if (s.st_uid != getuid()) {
920 fprintf(stderr, "Error: %s is not owned by the current user\n", dirname);
921 exit(1);
922 }
923 }
924 else {
925 // create ~/.firejail directory
926 create_empty_dir_as_user(dirname, 0700);
927 if (stat(dirname, &s) == -1) {
928 fprintf(stderr, "Error: cannot create directory %s\n", dirname);
929 exit(1);
930 }
931 }
932 free(dirname);
933
934 // check overlay directory
935 if (asprintf(&dirname, "%s/.firejail/%s", cfg.homedir, subdirname) == -1)
936 errExit("asprintf");
937 if (lstat(dirname, &s) == 0) {
938 if (!S_ISDIR(s.st_mode)) {
939 if (S_ISLNK(s.st_mode))
940 fprintf(stderr, "Error: %s is a symbolic link\n", dirname);
941 else
942 fprintf(stderr, "Error: %s is not a directory\n", dirname);
943 exit(1);
944 }
945 if (s.st_uid != 0) {
946 fprintf(stderr, "Error: overlay directory %s is not owned by the root user\n", dirname);
947 exit(1);
948 }
949 if (allow_reuse == 0) {
950 fprintf(stderr, "Error: overlay directory exists, but reuse is not allowed\n");
951 exit(1);
952 }
953 }
954
955 return dirname;
956}
957
958
959
960// mount overlayfs on top of / directory
961// mounting an overlay and chrooting into it:
962//
963// Old Ubuntu kernel
964// # cd ~
965// # mkdir -p overlay/root
966// # mkdir -p overlay/diff
967// # mount -t overlayfs -o lowerdir=/,upperdir=/root/overlay/diff overlayfs /root/overlay/root
968// # chroot /root/overlay/root
969// to shutdown, first exit the chroot and then unmount the overlay
970// # exit
971// # umount /root/overlay/root
972//
973// Kernels 3.18+
974// # cd ~
975// # mkdir -p overlay/root
976// # mkdir -p overlay/diff
977// # mkdir -p overlay/work
978// # mount -t overlay -o lowerdir=/,upperdir=/root/overlay/diff,workdir=/root/overlay/work overlay /root/overlay/root
979// # cat /etc/mtab | grep overlay
980// /root/overlay /root/overlay/root overlay rw,relatime,lowerdir=/,upperdir=/root/overlay/diff,workdir=/root/overlay/work 0 0
981// # chroot /root/overlay/root
982// to shutdown, first exit the chroot and then unmount the overlay
983// # exit
984// # umount /root/overlay/root
985
986
987// to do: fix the code below; also, it might work without /dev, but consider keeping /dev/shm; add locking mechanism for overlay-clean
988#include <sys/utsname.h>
989void fs_overlayfs(void) {
990 struct stat s;
991
992 // check kernel version
993 struct utsname u;
994 int rv = uname(&u);
995 if (rv != 0)
996 errExit("uname");
997 int major;
998 int minor;
999 if (2 != sscanf(u.release, "%d.%d", &major, &minor)) {
1000 fprintf(stderr, "Error: cannot extract Linux kernel version: %s\n", u.version);
1001 exit(1);
1002 }
1003
1004 if (arg_debug)
1005 printf("Linux kernel version %d.%d\n", major, minor);
1006 int oldkernel = 0;
1007 if (major < 3) {
1008 fprintf(stderr, "Error: minimum kernel version required 3.x\n");
1009 exit(1);
1010 }
1011 if (major == 3 && minor < 18)
1012 oldkernel = 1;
1013
1014 // mounting an overlayfs on top of / seems to be broken for kernels > 4.19
1015 // we disable overlayfs for now, pending fixing
1016 if (major >= 4 &&minor >= 19) {
1017 fprintf(stderr, "Error: OverlayFS disabled for Linux kernels 4.19 and newer, pending fixing.\n");
1018 exit(1);
1019 }
1020
1021 char *oroot = RUN_OVERLAY_ROOT;
1022 mkdir_attr(oroot, 0755, 0, 0);
1023
1024 // set base for working and diff directories
1025 char *basedir = RUN_MNT_DIR;
1026 int basefd = -1;
1027
1028 if (arg_overlay_keep) {
1029 basedir = cfg.overlay_dir;
1030 assert(basedir);
1031 // get a file descriptor for ~/.firejail, fails if there is any symlink
1032 char *firejail;
1033 if (asprintf(&firejail, "%s/.firejail", cfg.homedir) == -1)
1034 errExit("asprintf");
1035 int fd = safer_openat(-1, firejail, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
1036 if (fd == -1)
1037 errExit("safer_openat");
1038 free(firejail);
1039 // create basedir if it doesn't exist
1040 // the new directory will be owned by root
1041 const char *dirname = gnu_basename(basedir);
1042 if (mkdirat(fd, dirname, 0755) == -1 && errno != EEXIST) {
1043 perror("mkdir");
1044 fprintf(stderr, "Error: cannot create overlay directory %s\n", basedir);
1045 exit(1);
1046 }
1047 // open basedir
1048 basefd = openat(fd, dirname, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
1049 close(fd);
1050 }
1051 else {
1052 basefd = open(basedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
1053 }
1054 if (basefd == -1) {
1055 perror("open");
1056 fprintf(stderr, "Error: cannot open overlay directory %s\n", basedir);
1057 exit(1);
1058 }
1059
1060 // confirm once more base is owned by root
1061 if (fstat(basefd, &s) == -1)
1062 errExit("fstat");
1063 if (s.st_uid != 0) {
1064 fprintf(stderr, "Error: overlay directory %s is not owned by the root user\n", basedir);
1065 exit(1);
1066 }
1067 // confirm permissions of base are 0755
1068 if (((S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) & s.st_mode) != (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) {
1069 fprintf(stderr, "Error: invalid permissions on overlay directory %s\n", basedir);
1070 exit(1);
1071 }
1072
1073 // create diff and work directories inside base
1074 // no need to check arg_overlay_reuse
1075 char *odiff;
1076 if (asprintf(&odiff, "%s/odiff", basedir) == -1)
1077 errExit("asprintf");
1078 // the new directory will be owned by root
1079 if (mkdirat(basefd, "odiff", 0755) == -1 && errno != EEXIST) {
1080 perror("mkdir");
1081 fprintf(stderr, "Error: cannot create overlay directory %s\n", odiff);
1082 exit(1);
1083 }
1084 ASSERT_PERMS(odiff, 0, 0, 0755);
1085
1086 char *owork;
1087 if (asprintf(&owork, "%s/owork", basedir) == -1)
1088 errExit("asprintf");
1089 // the new directory will be owned by root
1090 if (mkdirat(basefd, "owork", 0755) == -1 && errno != EEXIST) {
1091 perror("mkdir");
1092 fprintf(stderr, "Error: cannot create overlay directory %s\n", owork);
1093 exit(1);
1094 }
1095 ASSERT_PERMS(owork, 0, 0, 0755);
1096
1097 // mount overlayfs
1098 if (arg_debug)
1099 printf("Mounting OverlayFS\n");
1100 char *option;
1101 if (oldkernel) { // old Ubuntu/OpenSUSE kernels
1102 if (arg_overlay_keep) {
1103 fprintf(stderr, "Error: option --overlay= not available for kernels older than 3.18\n");
1104 exit(1);
1105 }
1106 if (asprintf(&option, "lowerdir=/,upperdir=%s", odiff) == -1)
1107 errExit("asprintf");
1108 if (mount("overlayfs", oroot, "overlayfs", MS_MGC_VAL, option) < 0)
1109 errExit("mounting overlayfs");
1110 }
1111 else { // kernel 3.18 or newer
1112 if (asprintf(&option, "lowerdir=/,upperdir=%s,workdir=%s", odiff, owork) == -1)
1113 errExit("asprintf");
1114 if (mount("overlay", oroot, "overlay", MS_MGC_VAL, option) < 0) {
1115 fprintf(stderr, "Debug: running on kernel version %d.%d\n", major, minor);
1116 errExit("mounting overlayfs");
1117 }
1118
1119 //***************************
1120 // issue #263 start code
1121 // My setup has a separate mount point for /home. When the overlay is mounted,
1122 // the overlay does not contain the original /home contents.
1123 // I added code to create a second overlay for /home if the overlay home dir is empty and this seems to work
1124 // @dshmgh, Jan 2016
1125 {
1126 char *overlayhome;
1127 struct stat s;
1128 char *hroot;
1129 char *hdiff;
1130 char *hwork;
1131
1132 // dons add debug
1133 if (arg_debug) printf ("DEBUG: chroot dirs are oroot %s odiff %s owork %s\n",oroot,odiff,owork);
1134
1135 // BEFORE NEXT, WE NEED TO TEST IF /home has any contents or do we need to mount it?
1136 // must create var for oroot/cfg.homedir
1137 if (asprintf(&overlayhome, "%s%s", oroot, cfg.homedir) == -1)
1138 errExit("asprintf");
1139 if (arg_debug) printf ("DEBUG: overlayhome var holds ##%s##\n", overlayhome);
1140
1141 // if no homedir in overlay -- create another overlay for /home
1142 if (stat(cfg.homedir, &s) == 0 && stat(overlayhome, &s) == -1) {
1143
1144 // no need to check arg_overlay_reuse
1145 if (asprintf(&hdiff, "%s/hdiff", basedir) == -1)
1146 errExit("asprintf");
1147 // the new directory will be owned by root
1148 if (mkdirat(basefd, "hdiff", 0755) == -1 && errno != EEXIST) {
1149 perror("mkdir");
1150 fprintf(stderr, "Error: cannot create overlay directory %s\n", hdiff);
1151 exit(1);
1152 }
1153 ASSERT_PERMS(hdiff, 0, 0, 0755);
1154
1155 // no need to check arg_overlay_reuse
1156 if (asprintf(&hwork, "%s/hwork", basedir) == -1)
1157 errExit("asprintf");
1158 // the new directory will be owned by root
1159 if (mkdirat(basefd, "hwork", 0755) == -1 && errno != EEXIST) {
1160 perror("mkdir");
1161 fprintf(stderr, "Error: cannot create overlay directory %s\n", hwork);
1162 exit(1);
1163 }
1164 ASSERT_PERMS(hwork, 0, 0, 0755);
1165
1166 // no homedir in overlay so now mount another overlay for /home
1167 if (asprintf(&hroot, "%s/home", oroot) == -1)
1168 errExit("asprintf");
1169 if (asprintf(&option, "lowerdir=/home,upperdir=%s,workdir=%s", hdiff, hwork) == -1)
1170 errExit("asprintf");
1171 if (mount("overlay", hroot, "overlay", MS_MGC_VAL, option) < 0)
1172 errExit("mounting overlayfs for mounted home directory");
1173
1174 printf("OverlayFS for /home configured in %s directory\n", basedir);
1175 free(hroot);
1176 free(hdiff);
1177 free(hwork);
1178
1179 } // stat(overlayhome)
1180 free(overlayhome);
1181 }
1182 // issue #263 end code
1183 //***************************
1184 }
1185 fmessage("OverlayFS configured in %s directory\n", basedir);
1186 close(basefd);
1187
1188 // /dev, /run and /tmp are not covered by the overlay
1189 // mount-bind dev directory
1190 if (arg_debug)
1191 printf("Mounting /dev\n");
1192 char *dev;
1193 if (asprintf(&dev, "%s/dev", oroot) == -1)
1194 errExit("asprintf");
1195 if (mount("/dev", dev, NULL, MS_BIND|MS_REC, NULL) < 0)
1196 errExit("mounting /dev");
1197 fs_logger("whitelist /dev");
1198
1199 // mount-bind run directory
1200 if (arg_debug)
1201 printf("Mounting /run\n");
1202 char *run;
1203 if (asprintf(&run, "%s/run", oroot) == -1)
1204 errExit("asprintf");
1205 if (mount("/run", run, NULL, MS_BIND|MS_REC, NULL) < 0)
1206 errExit("mounting /run");
1207 fs_logger("whitelist /run");
1208
1209 // mount-bind tmp directory
1210 if (arg_debug)
1211 printf("Mounting /tmp\n");
1212 char *tmp;
1213 if (asprintf(&tmp, "%s/tmp", oroot) == -1)
1214 errExit("asprintf");
1215 if (mount("/tmp", tmp, NULL, MS_BIND|MS_REC, NULL) < 0)
1216 errExit("mounting /tmp");
1217 fs_logger("whitelist /tmp");
1218
1219 // chroot in the new filesystem
1220 __gcov_flush();
1221
1222 if (chroot(oroot) == -1)
1223 errExit("chroot");
1224
1225 // mount a new proc filesystem
1226 if (arg_debug)
1227 printf("Mounting /proc filesystem representing the PID namespace\n");
1228 if (mount("proc", "/proc", "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_REC, NULL) < 0)
1229 errExit("mounting /proc");
1230
1231 // update /var directory in order to support multiple sandboxes running on the same root directory
1232// if (!arg_private_dev)
1233// fs_dev_shm();
1234 fs_var_lock();
1235 if (!arg_keep_var_tmp)
1236 fs_var_tmp();
1237 if (!arg_writable_var_log)
1238 fs_var_log();
1239 fs_var_lib();
1240 fs_var_cache();
1241 fs_var_utmp();
1242 fs_machineid();
1243
1244 // don't leak user information
1245 restrict_users();
1246
1247 // when starting as root, firejail config is not disabled;
1248 if (getuid() != 0)
1249 disable_config();
1250
1251 // cleanup and exit
1252 free(option);
1253 free(odiff);
1254 free(owork);
1255 free(dev);
1256 free(run);
1257 free(tmp);
1258}
1259#endif
1260
1261// this function is called from sandbox.c before blacklist/whitelist functions 898// this function is called from sandbox.c before blacklist/whitelist functions
1262void fs_private_tmp(void) { 899void fs_private_tmp(void) {
1263 EUID_ASSERT(); 900 EUID_ASSERT();
@@ -1281,7 +918,6 @@ void fs_private_tmp(void) {
1281 918
1282 // whitelist x11 directory 919 // whitelist x11 directory
1283 profile_add("whitelist /tmp/.X11-unix"); 920 profile_add("whitelist /tmp/.X11-unix");
1284 // read-only x11 directory
1285 profile_add("read-only /tmp/.X11-unix"); 921 profile_add("read-only /tmp/.X11-unix");
1286 922
1287 // whitelist sndio directory 923 // whitelist sndio directory
diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c
index a43b18344..694d0a379 100644
--- a/src/firejail/fs_dev.c
+++ b/src/firejail/fs_dev.c
@@ -20,7 +20,6 @@
20#include "firejail.h" 20#include "firejail.h"
21#include <sys/mount.h> 21#include <sys/mount.h>
22#include <sys/stat.h> 22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h> 23#include <glob.h>
25#include <dirent.h> 24#include <dirent.h>
26#include <fcntl.h> 25#include <fcntl.h>
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c
index 590337da1..8d8530d81 100644
--- a/src/firejail/fs_home.c
+++ b/src/firejail/fs_home.c
@@ -19,7 +19,6 @@
19*/ 19*/
20#include "firejail.h" 20#include "firejail.h"
21#include <sys/mount.h> 21#include <sys/mount.h>
22#include <linux/limits.h>
23#include <dirent.h> 22#include <dirent.h>
24#include <errno.h> 23#include <errno.h>
25#include <sys/stat.h> 24#include <sys/stat.h>
diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c
index 7d320e90b..8b7e94f51 100644
--- a/src/firejail/fs_hostname.c
+++ b/src/firejail/fs_hostname.c
@@ -20,7 +20,6 @@
20#include "firejail.h" 20#include "firejail.h"
21#include <sys/mount.h> 21#include <sys/mount.h>
22#include <sys/stat.h> 22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h> 23#include <glob.h>
25#include <dirent.h> 24#include <dirent.h>
26#include <fcntl.h> 25#include <fcntl.h>
@@ -33,7 +32,7 @@ void fs_hostname(const char *hostname) {
33 if (arg_debug) 32 if (arg_debug)
34 printf("Creating a new /etc/hostname file\n"); 33 printf("Creating a new /etc/hostname file\n");
35 34
36 create_empty_file_as_root(RUN_HOSTNAME_FILE, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); 35 create_empty_file_as_root(RUN_HOSTNAME_FILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
37 36
38 // bind-mount the file on top of /etc/hostname 37 // bind-mount the file on top of /etc/hostname
39 if (mount(RUN_HOSTNAME_FILE, "/etc/hostname", NULL, MS_BIND|MS_REC, NULL) < 0) 38 if (mount(RUN_HOSTNAME_FILE, "/etc/hostname", NULL, MS_BIND|MS_REC, NULL) < 0)
@@ -75,7 +74,7 @@ void fs_hostname(const char *hostname) {
75 } 74 }
76 fclose(fp1); 75 fclose(fp1);
77 // mode and owner 76 // mode and owner
78 SET_PERMS_STREAM(fp2, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); 77 SET_PERMS_STREAM(fp2, 0, 0, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
79 fclose(fp2); 78 fclose(fp2);
80 79
81 // bind-mount the file on top of /etc/hostname 80 // bind-mount the file on top of /etc/hostname
diff --git a/src/firejail/fs_overlayfs.c b/src/firejail/fs_overlayfs.c
new file mode 100644
index 000000000..fe3761cb6
--- /dev/null
+++ b/src/firejail/fs_overlayfs.c
@@ -0,0 +1,470 @@
1/*
2 * Copyright (C) 2014-2021 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#ifdef HAVE_OVERLAYFS
22#include "firejail.h"
23#include "../include/gcov_wrapper.h"
24#include <sys/mount.h>
25#include <sys/wait.h>
26#include <ftw.h>
27#include <errno.h>
28
29#include <fcntl.h>
30#ifndef O_PATH
31#define O_PATH 010000000
32#endif
33
34
35char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) {
36 assert(subdirname);
37 EUID_ASSERT();
38 struct stat s;
39 char *dirname;
40
41 if (asprintf(&dirname, "%s/.firejail", cfg.homedir) == -1)
42 errExit("asprintf");
43 // check if ~/.firejail already exists
44 if (lstat(dirname, &s) == 0) {
45 if (!S_ISDIR(s.st_mode)) {
46 if (S_ISLNK(s.st_mode))
47 fprintf(stderr, "Error: %s is a symbolic link\n", dirname);
48 else
49 fprintf(stderr, "Error: %s is not a directory\n", dirname);
50 exit(1);
51 }
52 if (s.st_uid != getuid()) {
53 fprintf(stderr, "Error: %s is not owned by the current user\n", dirname);
54 exit(1);
55 }
56 }
57 else {
58 // create ~/.firejail directory
59 create_empty_dir_as_user(dirname, 0700);
60 if (stat(dirname, &s) == -1) {
61 fprintf(stderr, "Error: cannot create directory %s\n", dirname);
62 exit(1);
63 }
64 }
65 free(dirname);
66
67 // check overlay directory
68 if (asprintf(&dirname, "%s/.firejail/%s", cfg.homedir, subdirname) == -1)
69 errExit("asprintf");
70 if (lstat(dirname, &s) == 0) {
71 if (!S_ISDIR(s.st_mode)) {
72 if (S_ISLNK(s.st_mode))
73 fprintf(stderr, "Error: %s is a symbolic link\n", dirname);
74 else
75 fprintf(stderr, "Error: %s is not a directory\n", dirname);
76 exit(1);
77 }
78 if (s.st_uid != 0) {
79 fprintf(stderr, "Error: overlay directory %s is not owned by the root user\n", dirname);
80 exit(1);
81 }
82 if (allow_reuse == 0) {
83 fprintf(stderr, "Error: overlay directory exists, but reuse is not allowed\n");
84 exit(1);
85 }
86 }
87
88 return dirname;
89}
90
91
92// mount overlayfs on top of / directory
93// mounting an overlay and chrooting into it:
94//
95// Old Ubuntu kernel
96// # cd ~
97// # mkdir -p overlay/root
98// # mkdir -p overlay/diff
99// # mount -t overlayfs -o lowerdir=/,upperdir=/root/overlay/diff overlayfs /root/overlay/root
100// # chroot /root/overlay/root
101// to shutdown, first exit the chroot and then unmount the overlay
102// # exit
103// # umount /root/overlay/root
104//
105// Kernels 3.18+
106// # cd ~
107// # mkdir -p overlay/root
108// # mkdir -p overlay/diff
109// # mkdir -p overlay/work
110// # mount -t overlay -o lowerdir=/,upperdir=/root/overlay/diff,workdir=/root/overlay/work overlay /root/overlay/root
111// # cat /etc/mtab | grep overlay
112// /root/overlay /root/overlay/root overlay rw,relatime,lowerdir=/,upperdir=/root/overlay/diff,workdir=/root/overlay/work 0 0
113// # chroot /root/overlay/root
114// to shutdown, first exit the chroot and then unmount the overlay
115// # exit
116// # umount /root/overlay/root
117
118// to do: fix the code below
119#include <sys/utsname.h>
120void fs_overlayfs(void) {
121 struct stat s;
122
123 // check kernel version
124 struct utsname u;
125 int rv = uname(&u);
126 if (rv != 0)
127 errExit("uname");
128 int major;
129 int minor;
130 if (2 != sscanf(u.release, "%d.%d", &major, &minor)) {
131 fprintf(stderr, "Error: cannot extract Linux kernel version: %s\n", u.version);
132 exit(1);
133 }
134
135 if (arg_debug)
136 printf("Linux kernel version %d.%d\n", major, minor);
137 int oldkernel = 0;
138 if (major < 3) {
139 fprintf(stderr, "Error: minimum kernel version required 3.x\n");
140 exit(1);
141 }
142 if (major == 3 && minor < 18)
143 oldkernel = 1;
144
145 // mounting an overlayfs on top of / seems to be broken for kernels > 4.19
146 // we disable overlayfs for now, pending fixing
147 if (major >= 4 &&minor >= 19) {
148 fprintf(stderr, "Error: OverlayFS disabled for Linux kernels 4.19 and newer, pending fixing.\n");
149 exit(1);
150 }
151
152 char *oroot = RUN_OVERLAY_ROOT;
153 mkdir_attr(oroot, 0755, 0, 0);
154
155 // set base for working and diff directories
156 char *basedir = RUN_MNT_DIR;
157 int basefd = -1;
158
159 if (arg_overlay_keep) {
160 basedir = cfg.overlay_dir;
161 assert(basedir);
162 // get a file descriptor for ~/.firejail, fails if there is any symlink
163 char *firejail;
164 if (asprintf(&firejail, "%s/.firejail", cfg.homedir) == -1)
165 errExit("asprintf");
166 int fd = safer_openat(-1, firejail, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
167 if (fd == -1)
168 errExit("safer_openat");
169 free(firejail);
170 // create basedir if it doesn't exist
171 // the new directory will be owned by root
172 const char *dirname = gnu_basename(basedir);
173 if (mkdirat(fd, dirname, 0755) == -1 && errno != EEXIST) {
174 perror("mkdir");
175 fprintf(stderr, "Error: cannot create overlay directory %s\n", basedir);
176 exit(1);
177 }
178 // open basedir
179 basefd = openat(fd, dirname, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
180 close(fd);
181 }
182 else {
183 basefd = open(basedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
184 }
185 if (basefd == -1) {
186 perror("open");
187 fprintf(stderr, "Error: cannot open overlay directory %s\n", basedir);
188 exit(1);
189 }
190
191 // confirm once more base is owned by root
192 if (fstat(basefd, &s) == -1)
193 errExit("fstat");
194 if (s.st_uid != 0) {
195 fprintf(stderr, "Error: overlay directory %s is not owned by the root user\n", basedir);
196 exit(1);
197 }
198 // confirm permissions of base are 0755
199 if (((S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) & s.st_mode) != (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) {
200 fprintf(stderr, "Error: invalid permissions on overlay directory %s\n", basedir);
201 exit(1);
202 }
203
204 // create diff and work directories inside base
205 // no need to check arg_overlay_reuse
206 char *odiff;
207 if (asprintf(&odiff, "%s/odiff", basedir) == -1)
208 errExit("asprintf");
209 // the new directory will be owned by root
210 if (mkdirat(basefd, "odiff", 0755) == -1 && errno != EEXIST) {
211 perror("mkdir");
212 fprintf(stderr, "Error: cannot create overlay directory %s\n", odiff);
213 exit(1);
214 }
215 ASSERT_PERMS(odiff, 0, 0, 0755);
216
217 char *owork;
218 if (asprintf(&owork, "%s/owork", basedir) == -1)
219 errExit("asprintf");
220 // the new directory will be owned by root
221 if (mkdirat(basefd, "owork", 0755) == -1 && errno != EEXIST) {
222 perror("mkdir");
223 fprintf(stderr, "Error: cannot create overlay directory %s\n", owork);
224 exit(1);
225 }
226 ASSERT_PERMS(owork, 0, 0, 0755);
227
228 // mount overlayfs
229 if (arg_debug)
230 printf("Mounting OverlayFS\n");
231 char *option;
232 if (oldkernel) { // old Ubuntu/OpenSUSE kernels
233 if (arg_overlay_keep) {
234 fprintf(stderr, "Error: option --overlay= not available for kernels older than 3.18\n");
235 exit(1);
236 }
237 if (asprintf(&option, "lowerdir=/,upperdir=%s", odiff) == -1)
238 errExit("asprintf");
239 if (mount("overlayfs", oroot, "overlayfs", MS_MGC_VAL, option) < 0)
240 errExit("mounting overlayfs");
241 }
242 else { // kernel 3.18 or newer
243 if (asprintf(&option, "lowerdir=/,upperdir=%s,workdir=%s", odiff, owork) == -1)
244 errExit("asprintf");
245 if (mount("overlay", oroot, "overlay", MS_MGC_VAL, option) < 0) {
246 fprintf(stderr, "Debug: running on kernel version %d.%d\n", major, minor);
247 errExit("mounting overlayfs");
248 }
249
250 //***************************
251 // issue #263 start code
252 // My setup has a separate mount point for /home. When the overlay is mounted,
253 // the overlay does not contain the original /home contents.
254 // I added code to create a second overlay for /home if the overlay home dir is empty and this seems to work
255 // @dshmgh, Jan 2016
256 {
257 char *overlayhome;
258 struct stat s;
259 char *hroot;
260 char *hdiff;
261 char *hwork;
262
263 // dons add debug
264 if (arg_debug) printf ("DEBUG: chroot dirs are oroot %s odiff %s owork %s\n",oroot,odiff,owork);
265
266 // BEFORE NEXT, WE NEED TO TEST IF /home has any contents or do we need to mount it?
267 // must create var for oroot/cfg.homedir
268 if (asprintf(&overlayhome, "%s%s", oroot, cfg.homedir) == -1)
269 errExit("asprintf");
270 if (arg_debug) printf ("DEBUG: overlayhome var holds ##%s##\n", overlayhome);
271
272 // if no homedir in overlay -- create another overlay for /home
273 if (stat(cfg.homedir, &s) == 0 && stat(overlayhome, &s) == -1) {
274
275 // no need to check arg_overlay_reuse
276 if (asprintf(&hdiff, "%s/hdiff", basedir) == -1)
277 errExit("asprintf");
278 // the new directory will be owned by root
279 if (mkdirat(basefd, "hdiff", 0755) == -1 && errno != EEXIST) {
280 perror("mkdir");
281 fprintf(stderr, "Error: cannot create overlay directory %s\n", hdiff);
282 exit(1);
283 }
284 ASSERT_PERMS(hdiff, 0, 0, 0755);
285
286 // no need to check arg_overlay_reuse
287 if (asprintf(&hwork, "%s/hwork", basedir) == -1)
288 errExit("asprintf");
289 // the new directory will be owned by root
290 if (mkdirat(basefd, "hwork", 0755) == -1 && errno != EEXIST) {
291 perror("mkdir");
292 fprintf(stderr, "Error: cannot create overlay directory %s\n", hwork);
293 exit(1);
294 }
295 ASSERT_PERMS(hwork, 0, 0, 0755);
296
297 // no homedir in overlay so now mount another overlay for /home
298 if (asprintf(&hroot, "%s/home", oroot) == -1)
299 errExit("asprintf");
300 if (asprintf(&option, "lowerdir=/home,upperdir=%s,workdir=%s", hdiff, hwork) == -1)
301 errExit("asprintf");
302 if (mount("overlay", hroot, "overlay", MS_MGC_VAL, option) < 0)
303 errExit("mounting overlayfs for mounted home directory");
304
305 printf("OverlayFS for /home configured in %s directory\n", basedir);
306 free(hroot);
307 free(hdiff);
308 free(hwork);
309
310 } // stat(overlayhome)
311 free(overlayhome);
312 }
313 // issue #263 end code
314 //***************************
315 }
316 fmessage("OverlayFS configured in %s directory\n", basedir);
317 close(basefd);
318
319 // /dev, /run and /tmp are not covered by the overlay
320 // mount-bind dev directory
321 if (arg_debug)
322 printf("Mounting /dev\n");
323 char *dev;
324 if (asprintf(&dev, "%s/dev", oroot) == -1)
325 errExit("asprintf");
326 if (mount("/dev", dev, NULL, MS_BIND|MS_REC, NULL) < 0)
327 errExit("mounting /dev");
328 fs_logger("whitelist /dev");
329
330 // mount-bind run directory
331 if (arg_debug)
332 printf("Mounting /run\n");
333 char *run;
334 if (asprintf(&run, "%s/run", oroot) == -1)
335 errExit("asprintf");
336 if (mount("/run", run, NULL, MS_BIND|MS_REC, NULL) < 0)
337 errExit("mounting /run");
338 fs_logger("whitelist /run");
339
340 // mount-bind tmp directory
341 if (arg_debug)
342 printf("Mounting /tmp\n");
343 char *tmp;
344 if (asprintf(&tmp, "%s/tmp", oroot) == -1)
345 errExit("asprintf");
346 if (mount("/tmp", tmp, NULL, MS_BIND|MS_REC, NULL) < 0)
347 errExit("mounting /tmp");
348 fs_logger("whitelist /tmp");
349
350 // chroot in the new filesystem
351 __gcov_flush();
352
353 if (chroot(oroot) == -1)
354 errExit("chroot");
355
356 // mount a new proc filesystem
357 if (arg_debug)
358 printf("Mounting /proc filesystem representing the PID namespace\n");
359 if (mount("proc", "/proc", "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_REC, NULL) < 0)
360 errExit("mounting /proc");
361
362 // update /var directory in order to support multiple sandboxes running on the same root directory
363// if (!arg_private_dev)
364// fs_dev_shm();
365 fs_var_lock();
366 if (!arg_keep_var_tmp)
367 fs_var_tmp();
368 if (!arg_writable_var_log)
369 fs_var_log();
370 fs_var_lib();
371 fs_var_cache();
372 fs_var_utmp();
373 fs_machineid();
374
375 // don't leak user information
376 restrict_users();
377
378 // when starting as root, firejail config is not disabled;
379 if (getuid() != 0)
380 disable_config();
381
382 // cleanup and exit
383 free(option);
384 free(odiff);
385 free(owork);
386 free(dev);
387 free(run);
388 free(tmp);
389}
390
391
392static int remove_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
393 (void) sb;
394 (void) typeflag;
395 (void) ftwbuf;
396 assert(fpath);
397
398 if (strcmp(fpath, ".") == 0) // rmdir would fail with EINVAL
399 return 0;
400
401 if (remove(fpath)) { // removes the link not the actual file
402 fprintf(stderr, "Error: cannot remove file: %s\n", strerror(errno));
403 exit(1);
404 }
405
406 return 0;
407}
408
409int remove_overlay_directory(void) {
410 EUID_ASSERT();
411 sleep(1);
412
413 char *path;
414 if (asprintf(&path, "%s/.firejail", cfg.homedir) == -1)
415 errExit("asprintf");
416
417 if (access(path, F_OK) == 0) {
418 pid_t child = fork();
419 if (child < 0)
420 errExit("fork");
421 if (child == 0) {
422 // open ~/.firejail
423 int fd = safer_openat(-1, path, O_PATH|O_NOFOLLOW|O_CLOEXEC);
424 if (fd == -1) {
425 fprintf(stderr, "Error: cannot open %s\n", path);
426 exit(1);
427 }
428 struct stat s;
429 if (fstat(fd, &s) == -1)
430 errExit("fstat");
431 if (!S_ISDIR(s.st_mode)) {
432 if (S_ISLNK(s.st_mode))
433 fprintf(stderr, "Error: %s is a symbolic link\n", path);
434 else
435 fprintf(stderr, "Error: %s is not a directory\n", path);
436 exit(1);
437 }
438 if (s.st_uid != getuid()) {
439 fprintf(stderr, "Error: %s is not owned by the current user\n", path);
440 exit(1);
441 }
442 // chdir to ~/.firejail
443 if (fchdir(fd) == -1)
444 errExit("fchdir");
445 close(fd);
446
447 EUID_ROOT();
448 // FTW_PHYS - do not follow symbolic links
449 if (nftw(".", remove_callback, 64, FTW_DEPTH | FTW_PHYS) == -1)
450 errExit("nftw");
451
452 EUID_USER();
453 // remove ~/.firejail
454 if (rmdir(path) == -1)
455 errExit("rmdir");
456
457 __gcov_flush();
458
459 _exit(0);
460 }
461 // wait for the child to finish
462 waitpid(child, NULL, 0);
463 // check if ~/.firejail was deleted
464 if (access(path, F_OK) == 0)
465 return 1;
466 }
467 return 0;
468}
469
470#endif // HAVE_OVERLAYFS
diff --git a/src/firejail/fs_trace.c b/src/firejail/fs_trace.c
index 718786cdc..17a7b3d23 100644
--- a/src/firejail/fs_trace.c
+++ b/src/firejail/fs_trace.c
@@ -20,7 +20,6 @@
20#include "firejail.h" 20#include "firejail.h"
21#include <sys/mount.h> 21#include <sys/mount.h>
22#include <sys/stat.h> 22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h> 23#include <glob.h>
25#include <dirent.h> 24#include <dirent.h>
26#include <fcntl.h> 25#include <fcntl.h>
@@ -54,7 +53,7 @@ void fs_tracefile(void) {
54 if (arg_debug) 53 if (arg_debug)
55 printf("Creating an empty trace log file: %s\n", arg_tracefile); 54 printf("Creating an empty trace log file: %s\n", arg_tracefile);
56 EUID_USER(); 55 EUID_USER();
57 int fd = open(arg_tracefile, O_CREAT|O_WRONLY|O_CLOEXEC, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); 56 int fd = open(arg_tracefile, O_CREAT|O_WRONLY|O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
58 if (fd == -1) { 57 if (fd == -1) {
59 perror("open"); 58 perror("open");
60 fprintf(stderr, "Error: cannot open trace log file %s for writing\n", arg_tracefile); 59 fprintf(stderr, "Error: cannot open trace log file %s for writing\n", arg_tracefile);
@@ -107,7 +106,7 @@ void fs_trace(void) {
107 fmessage("Post-exec seccomp protector enabled\n"); 106 fmessage("Post-exec seccomp protector enabled\n");
108 } 107 }
109 108
110 SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); 109 SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
111 fclose(fp); 110 fclose(fp);
112 111
113 // mount the new preload file 112 // mount the new preload file
diff --git a/src/firejail/fs_var.c b/src/firejail/fs_var.c
index 20e262d80..e19d0df96 100644
--- a/src/firejail/fs_var.c
+++ b/src/firejail/fs_var.c
@@ -20,7 +20,6 @@
20#include "firejail.h" 20#include "firejail.h"
21#include <sys/mount.h> 21#include <sys/mount.h>
22#include <sys/stat.h> 22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h> 23#include <glob.h>
25#include <dirent.h> 24#include <dirent.h>
26#include <fcntl.h> 25#include <fcntl.h>
@@ -129,7 +128,7 @@ void fs_var_log(void) {
129 /* coverity[toctou] */ 128 /* coverity[toctou] */
130 FILE *fp = fopen("/var/log/wtmp", "wxe"); 129 FILE *fp = fopen("/var/log/wtmp", "wxe");
131 if (fp) { 130 if (fp) {
132 SET_PERMS_STREAM(fp, 0, wtmp_group, S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH); 131 SET_PERMS_STREAM(fp, 0, wtmp_group, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
133 fclose(fp); 132 fclose(fp);
134 } 133 }
135 fs_logger("touch /var/log/wtmp"); 134 fs_logger("touch /var/log/wtmp");
@@ -137,7 +136,7 @@ void fs_var_log(void) {
137 // create an empty /var/log/btmp file 136 // create an empty /var/log/btmp file
138 fp = fopen("/var/log/btmp", "wxe"); 137 fp = fopen("/var/log/btmp", "wxe");
139 if (fp) { 138 if (fp) {
140 SET_PERMS_STREAM(fp, 0, wtmp_group, S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP); 139 SET_PERMS_STREAM(fp, 0, wtmp_group, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
141 fclose(fp); 140 fclose(fp);
142 } 141 }
143 fs_logger("touch /var/log/btmp"); 142 fs_logger("touch /var/log/btmp");
@@ -314,7 +313,7 @@ void fs_var_utmp(void) {
314 // save new utmp file 313 // save new utmp file
315 int rv = fwrite(&u_boot, sizeof(u_boot), 1, fp); 314 int rv = fwrite(&u_boot, sizeof(u_boot), 1, fp);
316 (void) rv; 315 (void) rv;
317 SET_PERMS_STREAM(fp, 0, utmp_group, S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH); 316 SET_PERMS_STREAM(fp, 0, utmp_group, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
318 fclose(fp); 317 fclose(fp);
319 318
320 // mount the new utmp file 319 // mount the new utmp file
diff --git a/src/firejail/join.c b/src/firejail/join.c
index a869f6b64..0e76fd944 100644
--- a/src/firejail/join.c
+++ b/src/firejail/join.c
@@ -431,7 +431,7 @@ void join(pid_t pid, int argc, char **argv, int index) {
431 431
432 // set cgroup 432 // set cgroup
433 if (cfg.cgroup) // not available for uid 0 433 if (cfg.cgroup) // not available for uid 0
434 set_cgroup(cfg.cgroup); 434 set_cgroup(cfg.cgroup, getpid());
435 435
436 // join namespaces 436 // join namespaces
437 if (arg_join_network) { 437 if (arg_join_network) {
diff --git a/src/firejail/ls.c b/src/firejail/ls.c
index 70985ba9e..53e918dde 100644
--- a/src/firejail/ls.c
+++ b/src/firejail/ls.c
@@ -305,7 +305,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
305 } 305 }
306 // create destination file if necessary 306 // create destination file if necessary
307 EUID_ASSERT(); 307 EUID_ASSERT();
308 int fd = open(dest_fname, O_WRONLY|O_CREAT|O_CLOEXEC, S_IRUSR | S_IWRITE); 308 int fd = open(dest_fname, O_WRONLY|O_CREAT|O_CLOEXEC, S_IRUSR | S_IWUSR);
309 if (fd == -1) { 309 if (fd == -1) {
310 fprintf(stderr, "Error: cannot open %s for writing\n", dest_fname); 310 fprintf(stderr, "Error: cannot open %s for writing\n", dest_fname);
311 exit(1); 311 exit(1);
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 81d148257..1ba70b0bd 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -32,7 +32,8 @@
32#include <dirent.h> 32#include <dirent.h>
33#include <pwd.h> 33#include <pwd.h>
34#include <errno.h> 34#include <errno.h>
35//#include <limits.h> 35
36#include <limits.h>
36#include <sys/file.h> 37#include <sys/file.h>
37#include <sys/prctl.h> 38#include <sys/prctl.h>
38#include <signal.h> 39#include <signal.h>
@@ -1528,15 +1529,16 @@ int main(int argc, char **argv, char **envp) {
1528 else if (strncmp(argv[i], "--cgroup=", 9) == 0) { 1529 else if (strncmp(argv[i], "--cgroup=", 9) == 0) {
1529 if (checkcfg(CFG_CGROUP)) { 1530 if (checkcfg(CFG_CGROUP)) {
1530 if (option_cgroup) { 1531 if (option_cgroup) {
1531 fprintf(stderr, "Error: only a cgroup can be defined\n"); 1532 fprintf(stderr, "Error: only one cgroup can be defined\n");
1532 exit(1); 1533 exit(1);
1533 } 1534 }
1534
1535 option_cgroup = 1;
1536 cfg.cgroup = strdup(argv[i] + 9); 1535 cfg.cgroup = strdup(argv[i] + 9);
1537 if (!cfg.cgroup) 1536 if (!cfg.cgroup)
1538 errExit("strdup"); 1537 errExit("strdup");
1539 set_cgroup(cfg.cgroup); 1538
1539 check_cgroup_file(cfg.cgroup);
1540 set_cgroup(cfg.cgroup, getpid());
1541 option_cgroup = 1;
1540 } 1542 }
1541 else 1543 else
1542 exit_err_feature("cgroup"); 1544 exit_err_feature("cgroup");
@@ -2154,6 +2156,10 @@ int main(int argc, char **argv, char **envp) {
2154 arg_novideo = 1; 2156 arg_novideo = 1;
2155 else if (strcmp(argv[i], "--no3d") == 0) 2157 else if (strcmp(argv[i], "--no3d") == 0)
2156 arg_no3d = 1; 2158 arg_no3d = 1;
2159 else if (strcmp(argv[i], "--noprinters") == 0) {
2160 profile_add("blacklist /dev/lp*");
2161 profile_add("blacklist /run/cups/cups.sock");
2162 }
2157 else if (strcmp(argv[i], "--notv") == 0) 2163 else if (strcmp(argv[i], "--notv") == 0)
2158 arg_notv = 1; 2164 arg_notv = 1;
2159 else if (strcmp(argv[i], "--nodvd") == 0) 2165 else if (strcmp(argv[i], "--nodvd") == 0)
diff --git a/src/firejail/mountinfo.c b/src/firejail/mountinfo.c
index 304f80eee..ee437e10b 100644
--- a/src/firejail/mountinfo.c
+++ b/src/firejail/mountinfo.c
@@ -33,43 +33,38 @@ static MountData mdata;
33 33
34 34
35// Convert octal escape sequence to decimal value 35// Convert octal escape sequence to decimal value
36static int read_oct(const char *path) { 36static unsigned read_oct(char *s) {
37 int dec = 0; 37 assert(s[0] == '\\');
38 int digit, i; 38 s++;
39 // there are always exactly three octal digits 39
40 for (i = 1; i < 4; i++) { 40 int i;
41 digit = *(path + i); 41 for (i = 0; i < 3; i++)
42 if (digit < '0' || digit > '7') { 42 assert(s[i] >= '0' && s[i] <= '7');
43 fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); 43
44 exit(1); 44 return ((s[0] - '0') << 6 |
45 } 45 (s[1] - '0') << 3 |
46 dec = (dec << 3) + (digit - '0'); 46 (s[2] - '0') << 0);
47 }
48 return dec;
49} 47}
50 48
51// Restore empty spaces in pathnames extracted from /proc/self/mountinfo 49// Restore empty spaces in pathnames extracted from /proc/self/mountinfo
52static void unmangle_path(char *path) { 50static void unmangle_path(char *path) {
53 char *p = strchr(path, '\\'); 51 char *r = strchr(path, '\\');
54 if (p && read_oct(p) == ' ') { 52 if (!r)
55 *p = ' '; 53 return;
56 int i = 3; 54
57 do { 55 char *w = r;
58 p++; 56 do {
59 if (*(p + i) == '\\' && read_oct(p + i) == ' ') { 57 while (*r == '\\') {
60 *p = ' '; 58 *w++ = read_oct(r);
61 i += 3; 59 r += 4;
62 } 60 }
63 else 61 *w++ = *r;
64 *p = *(p + i); 62 } while (*r++);
65 } while (*p);
66 }
67} 63}
68 64
69// Parse a line from /proc/self/mountinfo, 65// Parse a line from /proc/self/mountinfo,
70// the function does an exit(1) if anything goes wrong. 66// the function does an exit(1) if anything goes wrong.
71static void parse_line(char *line, MountData *output) { 67static void parse_line(char *line, MountData *output) {
72 assert(line && output);
73 memset(output, 0, sizeof(*output)); 68 memset(output, 0, sizeof(*output));
74 // extract mount id, filesystem name, directory and filesystem types 69 // extract mount id, filesystem name, directory and filesystem types
75 // examples: 70 // examples:
@@ -87,8 +82,6 @@ static void parse_line(char *line, MountData *output) {
87 char *ptr = strtok(line, " "); 82 char *ptr = strtok(line, " ");
88 if (!ptr) 83 if (!ptr)
89 goto errexit; 84 goto errexit;
90 if (ptr != line)
91 goto errexit;
92 output->mountid = atoi(ptr); 85 output->mountid = atoi(ptr);
93 int cnt = 1; 86 int cnt = 1;
94 87
@@ -109,10 +102,9 @@ static void parse_line(char *line, MountData *output) {
109 ptr = strtok(NULL, " "); 102 ptr = strtok(NULL, " ");
110 if (!ptr) 103 if (!ptr)
111 goto errexit; 104 goto errexit;
112 output->fstype = ptr++; 105 output->fstype = ptr;
113 106
114 107 if (output->mountid < 0 ||
115 if (output->mountid == 0 ||
116 output->fsname == NULL || 108 output->fsname == NULL ||
117 output->dir == NULL || 109 output->dir == NULL ||
118 output->fstype == NULL) 110 output->fstype == NULL)
@@ -195,9 +187,9 @@ static int get_mount_id_from_fdinfo(int fd) {
195 char buf[MAX_BUF]; 187 char buf[MAX_BUF];
196 while (fgets(buf, MAX_BUF, fp)) { 188 while (fgets(buf, MAX_BUF, fp)) {
197 if (strncmp(buf, "mnt_id:", 7) == 0) { 189 if (strncmp(buf, "mnt_id:", 7) == 0) {
198 if (sscanf(buf + 7, "%d", &rv) != 1) 190 if (sscanf(buf + 7, "%d", &rv) == 1)
199 goto errexit; 191 break;
200 break; 192 goto errexit;
201 } 193 }
202 } 194 }
203 195
@@ -219,62 +211,50 @@ int get_mount_id(int fd) {
219 211
220// Check /proc/self/mountinfo if path contains any mounts points. 212// Check /proc/self/mountinfo if path contains any mounts points.
221// Returns an array that can be iterated over for recursive remounting. 213// Returns an array that can be iterated over for recursive remounting.
222char **build_mount_array(const int mount_id, const char *path) { 214char **build_mount_array(const int mountid, const char *path) {
223 assert(path); 215 assert(path);
224 216
225 // open /proc/self/mountinfo
226 FILE *fp = fopen("/proc/self/mountinfo", "re"); 217 FILE *fp = fopen("/proc/self/mountinfo", "re");
227 if (!fp) { 218 if (!fp) {
228 fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); 219 fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n");
229 exit(1); 220 exit(1);
230 } 221 }
231 222
232 // array to be returned 223 // try to find line with mount id
233 size_t cnt = 0; 224 int found = 0;
225 MountData mntp;
226 char line[MAX_BUF];
227 while (fgets(line, MAX_BUF, fp)) {
228 parse_line(line, &mntp);
229 if (mntp.mountid == mountid) {
230 found = 1;
231 break;
232 }
233 }
234
235 if (!found) {
236 fclose(fp);
237 return NULL;
238 }
239
240 // allocate array
234 size_t size = 32; 241 size_t size = 32;
235 char **rv = malloc(size * sizeof(*rv)); 242 char **rv = malloc(size * sizeof(*rv));
236 if (!rv) 243 if (!rv)
237 errExit("malloc"); 244 errExit("malloc");
238 245
239 // read /proc/self/mountinfo 246 // add directory itself
240 size_t pathlen = strlen(path); 247 size_t cnt = 0;
241 char buf[MAX_BUF]; 248 rv[cnt] = strdup(path);
242 MountData mntp; 249 if (rv[cnt] == NULL)
243 int found = 0; 250 errExit("strdup");
244 251
245 if (fgets(buf, MAX_BUF, fp) == NULL) { 252 // and add all following mountpoints contained in this directory
246 fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); 253 size_t pathlen = strlen(path);
247 exit(1); 254 while (fgets(line, MAX_BUF, fp)) {
248 } 255 parse_line(line, &mntp);
249 do { 256 if (strncmp(mntp.dir, path, pathlen) == 0 && mntp.dir[pathlen] == '/') {
250 parse_line(buf, &mntp); 257 if (++cnt == size) {
251 // find mount point with mount id
252 if (!found) {
253 if (mntp.mountid == mount_id) {
254 // give up if mount id has been reassigned,
255 // don't remount blacklisted path
256 if (strncmp(mntp.dir, path, strlen(mntp.dir)) ||
257 strstr(mntp.fsname, "firejail.ro.dir") ||
258 strstr(mntp.fsname, "firejail.ro.file"))
259 break;
260
261 rv[cnt] = strdup(path);
262 if (rv[cnt] == NULL)
263 errExit("strdup");
264 cnt++;
265 found = 1;
266 continue;
267 }
268 continue;
269 }
270 // from here on add all mount points below path,
271 // don't remount blacklisted paths
272 if (strncmp(mntp.dir, path, pathlen) == 0 &&
273 mntp.dir[pathlen] == '/' &&
274 strstr(mntp.fsname, "firejail.ro.dir") == NULL &&
275 strstr(mntp.fsname, "firejail.ro.file") == NULL) {
276
277 if (cnt == size) {
278 size *= 2; 258 size *= 2;
279 rv = realloc(rv, size * sizeof(*rv)); 259 rv = realloc(rv, size * sizeof(*rv));
280 if (!rv) 260 if (!rv)
@@ -283,18 +263,17 @@ char **build_mount_array(const int mount_id, const char *path) {
283 rv[cnt] = strdup(mntp.dir); 263 rv[cnt] = strdup(mntp.dir);
284 if (rv[cnt] == NULL) 264 if (rv[cnt] == NULL)
285 errExit("strdup"); 265 errExit("strdup");
286 cnt++;
287 } 266 }
288 } while (fgets(buf, MAX_BUF, fp)); 267 }
268 fclose(fp);
289 269
290 if (cnt == size) { 270 // end of array
291 size++; 271 if (++cnt == size) {
272 ++size;
292 rv = realloc(rv, size * sizeof(*rv)); 273 rv = realloc(rv, size * sizeof(*rv));
293 if (!rv) 274 if (!rv)
294 errExit("realloc"); 275 errExit("realloc");
295 } 276 }
296 rv[cnt] = NULL; // end of the array 277 rv[cnt] = NULL;
297
298 fclose(fp);
299 return rv; 278 return rv;
300} 279}
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index 5390249ea..babc3941e 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -449,6 +449,11 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
449 arg_no3d = 1; 449 arg_no3d = 1;
450 return 0; 450 return 0;
451 } 451 }
452 else if (strcmp(ptr, "noprinters") == 0) {
453 profile_add("blacklist /dev/lp*");
454 profile_add("blacklist /run/cups/cups.sock");
455 return 0;
456 }
452 else if (strcmp(ptr, "noinput") == 0) { 457 else if (strcmp(ptr, "noinput") == 0) {
453 arg_noinput = 1; 458 arg_noinput = 1;
454 return 0; 459 return 0;
@@ -1129,8 +1134,14 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
1129 1134
1130 // cgroup 1135 // cgroup
1131 if (strncmp(ptr, "cgroup ", 7) == 0) { 1136 if (strncmp(ptr, "cgroup ", 7) == 0) {
1132 if (checkcfg(CFG_CGROUP)) 1137 if (checkcfg(CFG_CGROUP)) {
1133 set_cgroup(ptr + 7); 1138 cfg.cgroup = strdup(ptr + 7);
1139 if (!cfg.cgroup)
1140 errExit("strdup");
1141
1142 check_cgroup_file(cfg.cgroup);
1143 set_cgroup(cfg.cgroup, getpid());
1144 }
1134 else 1145 else
1135 warning_feature_disabled("cgroup"); 1146 warning_feature_disabled("cgroup");
1136 return 0; 1147 return 0;
diff --git a/src/firejail/restrict_users.c b/src/firejail/restrict_users.c
index 6f17231a4..59077dada 100644
--- a/src/firejail/restrict_users.c
+++ b/src/firejail/restrict_users.c
@@ -21,7 +21,6 @@
21#include "../include/firejail_user.h" 21#include "../include/firejail_user.h"
22#include <sys/mount.h> 22#include <sys/mount.h>
23#include <sys/stat.h> 23#include <sys/stat.h>
24#include <linux/limits.h>
25#include <fnmatch.h> 24#include <fnmatch.h>
26#include <glob.h> 25#include <glob.h>
27#include <dirent.h> 26#include <dirent.h>
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index b776a0cc5..d66b6c573 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -204,7 +204,7 @@ static void save_umask(void) {
204} 204}
205 205
206static char *create_join_file(void) { 206static char *create_join_file(void) {
207 int fd = open(RUN_JOIN_FILE, O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); 207 int fd = open(RUN_JOIN_FILE, O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
208 if (fd == -1) 208 if (fd == -1)
209 errExit("open"); 209 errExit("open");
210 if (ftruncate(fd, 1) == -1) 210 if (ftruncate(fd, 1) == -1)
diff --git a/src/firejail/util.c b/src/firejail/util.c
index f0df45eb2..55dcdc246 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -20,8 +20,6 @@
20#define _XOPEN_SOURCE 500 20#define _XOPEN_SOURCE 500
21#include "firejail.h" 21#include "firejail.h"
22#include "../include/gcov_wrapper.h" 22#include "../include/gcov_wrapper.h"
23#include <ftw.h>
24#include <sys/stat.h>
25#include <sys/mount.h> 23#include <sys/mount.h>
26#include <syslog.h> 24#include <syslog.h>
27#include <errno.h> 25#include <errno.h>
@@ -32,9 +30,6 @@
32#include <sys/wait.h> 30#include <sys/wait.h>
33#include <limits.h> 31#include <limits.h>
34 32
35#include <string.h>
36#include <ctype.h>
37
38#include <fcntl.h> 33#include <fcntl.h>
39#ifndef O_PATH 34#ifndef O_PATH
40#define O_PATH 010000000 35#define O_PATH 010000000
@@ -489,13 +484,6 @@ int is_link(const char *fname) {
489 if (*fname == '\0') 484 if (*fname == '\0')
490 return 0; 485 return 0;
491 486
492 int called_as_root = 0;
493 if (geteuid() == 0)
494 called_as_root = 1;
495
496 if (called_as_root)
497 EUID_USER();
498
499 // remove trailing '/' if any 487 // remove trailing '/' if any
500 char *tmp = strdup(fname); 488 char *tmp = strdup(fname);
501 if (!tmp) 489 if (!tmp)
@@ -503,12 +491,9 @@ int is_link(const char *fname) {
503 trim_trailing_slash_or_dot(tmp); 491 trim_trailing_slash_or_dot(tmp);
504 492
505 char c; 493 char c;
506 ssize_t rv = readlink(tmp, &c, 1); 494 ssize_t rv = readlink_as_user(tmp, &c, 1);
507 free(tmp); 495 free(tmp);
508 496
509 if (called_as_root)
510 EUID_ROOT();
511
512 return (rv != -1); 497 return (rv != -1);
513} 498}
514 499
@@ -530,6 +515,24 @@ char *realpath_as_user(const char *fname) {
530 return rv; 515 return rv;
531} 516}
532 517
518ssize_t readlink_as_user(const char *fname, char *buf, size_t sz) {
519 assert(fname && buf && sz);
520
521 int called_as_root = 0;
522 if (geteuid() == 0)
523 called_as_root = 1;
524
525 if (called_as_root)
526 EUID_USER();
527
528 ssize_t rv = readlink(fname, buf, sz);
529
530 if (called_as_root)
531 EUID_ROOT();
532
533 return rv;
534}
535
533int stat_as_user(const char *fname, struct stat *s) { 536int stat_as_user(const char *fname, struct stat *s) {
534 assert(fname); 537 assert(fname);
535 538
@@ -964,12 +967,9 @@ uid_t pid_get_uid(pid_t pid) {
964} 967}
965 968
966 969
967 970gid_t get_group_id(const char *groupname) {
968
969uid_t get_group_id(const char *group) {
970 // find tty group id
971 gid_t gid = 0; 971 gid_t gid = 0;
972 struct group *g = getgrnam(group); 972 struct group *g = getgrnam(groupname);
973 if (g) 973 if (g)
974 gid = g->gr_gid; 974 gid = g->gr_gid;
975 975
@@ -977,86 +977,6 @@ uid_t get_group_id(const char *group) {
977} 977}
978 978
979 979
980static int remove_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
981 (void) sb;
982 (void) typeflag;
983 (void) ftwbuf;
984 assert(fpath);
985
986 if (strcmp(fpath, ".") == 0)
987 return 0;
988
989 if (remove(fpath)) { // removes the link not the actual file
990 perror("remove");
991 fprintf(stderr, "Error: cannot remove file from user .firejail directory: %s\n", fpath);
992 exit(1);
993 }
994
995 return 0;
996}
997
998
999int remove_overlay_directory(void) {
1000 EUID_ASSERT();
1001 sleep(1);
1002
1003 char *path;
1004 if (asprintf(&path, "%s/.firejail", cfg.homedir) == -1)
1005 errExit("asprintf");
1006
1007 if (access(path, F_OK) == 0) {
1008 pid_t child = fork();
1009 if (child < 0)
1010 errExit("fork");
1011 if (child == 0) {
1012 // open ~/.firejail
1013 int fd = safer_openat(-1, path, O_PATH|O_NOFOLLOW|O_CLOEXEC);
1014 if (fd == -1) {
1015 fprintf(stderr, "Error: cannot open %s\n", path);
1016 exit(1);
1017 }
1018 struct stat s;
1019 if (fstat(fd, &s) == -1)
1020 errExit("fstat");
1021 if (!S_ISDIR(s.st_mode)) {
1022 if (S_ISLNK(s.st_mode))
1023 fprintf(stderr, "Error: %s is a symbolic link\n", path);
1024 else
1025 fprintf(stderr, "Error: %s is not a directory\n", path);
1026 exit(1);
1027 }
1028 if (s.st_uid != getuid()) {
1029 fprintf(stderr, "Error: %s is not owned by the current user\n", path);
1030 exit(1);
1031 }
1032 // chdir to ~/.firejail
1033 if (fchdir(fd) == -1)
1034 errExit("fchdir");
1035 close(fd);
1036
1037 EUID_ROOT();
1038 // FTW_PHYS - do not follow symbolic links
1039 if (nftw(".", remove_callback, 64, FTW_DEPTH | FTW_PHYS) == -1)
1040 errExit("nftw");
1041
1042 EUID_USER();
1043 // remove ~/.firejail
1044 if (rmdir(path) == -1)
1045 errExit("rmdir");
1046
1047 __gcov_flush();
1048
1049 _exit(0);
1050 }
1051 // wait for the child to finish
1052 waitpid(child, NULL, 0);
1053 // check if ~/.firejail was deleted
1054 if (access(path, F_OK) == 0)
1055 return 1;
1056 }
1057 return 0;
1058}
1059
1060// flush stdin if it is connected to a tty and has input 980// flush stdin if it is connected to a tty and has input
1061void flush_stdin(void) { 981void flush_stdin(void) {
1062 if (!isatty(STDIN_FILENO)) 982 if (!isatty(STDIN_FILENO))
@@ -1085,31 +1005,33 @@ int create_empty_dir_as_user(const char *dir, mode_t mode) {
1085 assert(dir); 1005 assert(dir);
1086 mode &= 07777; 1006 mode &= 07777;
1087 1007
1088 if (access(dir, F_OK) != 0) { 1008 if (access(dir, F_OK) == 0)
1009 return 0;
1010
1011 pid_t child = fork();
1012 if (child < 0)
1013 errExit("fork");
1014 if (child == 0) {
1015 // drop privileges
1016 drop_privs(0);
1017
1089 if (arg_debug) 1018 if (arg_debug)
1090 printf("Creating empty %s directory\n", dir); 1019 printf("Creating empty %s directory\n", dir);
1091 pid_t child = fork(); 1020 if (mkdir(dir, mode) == 0) {
1092 if (child < 0) 1021 int err = chmod(dir, mode);
1093 errExit("fork"); 1022 (void) err;
1094 if (child == 0) { 1023 }
1095 // drop privileges 1024 else if (arg_debug)
1096 drop_privs(0); 1025 printf("Directory %s not created: %s\n", dir, strerror(errno));
1097
1098 if (mkdir(dir, mode) == 0) {
1099 int err = chmod(dir, mode);
1100 (void) err;
1101 }
1102 else if (arg_debug)
1103 printf("Directory %s not created: %s\n", dir, strerror(errno));
1104 1026
1105 __gcov_flush(); 1027 __gcov_flush();
1106 1028
1107 _exit(0); 1029 _exit(0);
1108 }
1109 waitpid(child, NULL, 0);
1110 if (access(dir, F_OK) == 0)
1111 return 1;
1112 } 1030 }
1031 waitpid(child, NULL, 0);
1032
1033 if (access(dir, F_OK) == 0)
1034 return 1;
1113 return 0; 1035 return 0;
1114} 1036}
1115 1037
@@ -1499,7 +1421,7 @@ static int has_link(const char *dir) {
1499void check_homedir(const char *dir) { 1421void check_homedir(const char *dir) {
1500 assert(dir); 1422 assert(dir);
1501 if (dir[0] != '/') { 1423 if (dir[0] != '/') {
1502 fprintf(stderr, "Error: invalid user directory \"%s\"\n", cfg.homedir); 1424 fprintf(stderr, "Error: invalid user directory \"%s\"\n", dir);
1503 exit(1); 1425 exit(1);
1504 } 1426 }
1505 // symlinks are rejected in many places 1427 // symlinks are rejected in many places
diff --git a/src/libtrace/libtrace.c b/src/libtrace/libtrace.c
index d88512b0a..319902ff7 100644
--- a/src/libtrace/libtrace.c
+++ b/src/libtrace/libtrace.c
@@ -18,12 +18,12 @@
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/ 19*/
20#define _GNU_SOURCE 20#define _GNU_SOURCE
21#include <errno.h>
21#include <stdio.h> 22#include <stdio.h>
22#include <stdlib.h> 23#include <stdlib.h>
23#include <string.h> 24#include <string.h>
24#include <dlfcn.h> 25#include <dlfcn.h>
25#include <sys/types.h> 26#include <sys/types.h>
26#include <limits.h>
27#include <unistd.h> 27#include <unistd.h>
28#include <sys/socket.h> 28#include <sys/socket.h>
29#include <netinet/in.h> 29#include <netinet/in.h>
@@ -706,10 +706,14 @@ __attribute__((constructor))
706static void log_exec(int argc, char** argv) { 706static void log_exec(int argc, char** argv) {
707 (void) argc; 707 (void) argc;
708 (void) argv; 708 (void) argv;
709 static char buf[PATH_MAX + 1]; 709 char *buf = realpath("/proc/self/exe", NULL);
710 int rv = readlink("/proc/self/exe", buf, PATH_MAX); 710 if (buf == NULL) {
711 if (rv != -1) { 711 if (errno == ENOMEM) {
712 buf[rv] = '\0'; // readlink does not add a '\0' at the end 712 tprintf(ftty, "realpath: %s\n", strerror(errno));
713 exit(1);
714 }
715 } else {
713 tprintf(ftty, "%u:%s:exec %s:0\n", mypid, myname, buf); 716 tprintf(ftty, "%u:%s:exec %s:0\n", mypid, myname, buf);
717 free(buf);
714 } 718 }
715} 719}
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index 2883ab257..e724e4bb9 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -290,8 +290,8 @@ $ firejail \-\-caps.print=3272
290Print content of file from sandbox container, see FILE TRANSFER section for more details. 290Print content of file from sandbox container, see FILE TRANSFER section for more details.
291#endif 291#endif
292.TP 292.TP
293\fB\-\-cgroup=tasks-file 293\fB\-\-cgroup=file
294Place the sandbox in the specified control group. tasks-file is the full path of cgroup tasks file. 294Place the sandbox in the specified control group. file is the full path of a tasks or cgroup.procs file.
295.br 295.br
296 296
297.br 297.br
@@ -310,6 +310,11 @@ regular user, nonewprivs and a default capabilities filter are enabled.
310Example: 310Example:
311.br 311.br
312$ firejail \-\-chroot=/media/ubuntu warzone2100 312$ firejail \-\-chroot=/media/ubuntu warzone2100
313.br
314
315.br
316For automatic mounting of X11 and PulseAudio sockets set environment variables
317FIREJAIL_CHROOT_X11 and FIREJAIL_CHROOT_PULSE.
313#endif 318#endif
314.TP 319.TP
315\fB\-\-cpu=cpu-number,cpu-number,cpu-number 320\fB\-\-cpu=cpu-number,cpu-number,cpu-number
@@ -2192,6 +2197,11 @@ More information about groups can be found in /usr/share/doc/firejail/syscalls.t
2192.br 2197.br
2193 2198
2194.br 2199.br
2200The default list can be customized, see \-\-seccomp= for a description.
2201It can be customized also globally in /etc/firejail/firejail.config file.
2202.br
2203
2204.br
2195System architecture is strictly imposed only if flag 2205System architecture is strictly imposed only if flag
2196\-\-seccomp.block-secondary is used. The filter is applied at run time 2206\-\-seccomp.block-secondary is used. The filter is applied at run time
2197only if the correct architecture was detected. For the case of I386 2207only if the correct architecture was detected. For the case of I386
@@ -2206,11 +2216,7 @@ Firejail will print seccomp violations to the audit log if the kernel was compil
2206Example: 2216Example:
2207.br 2217.br
2208$ firejail \-\-seccomp 2218$ firejail \-\-seccomp
2209.br
2210 2219
2211.br
2212The default list can be customized, see \-\-seccomp= for a description. It can be customized
2213also globally in /etc/firejail/firejail.config file.
2214 2220
2215.TP 2221.TP
2216\fB\-\-seccomp=syscall,@group,!syscall2 2222\fB\-\-seccomp=syscall,@group,!syscall2