aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile.in13
-rw-r--r--README26
-rw-r--r--README.md70
-rw-r--r--RELNOTES23
-rwxr-xr-xconfigure22
-rw-r--r--configure.ac5
-rw-r--r--etc/Wire.profile22
-rw-r--r--etc/atom-beta.profile2
-rw-r--r--etc/atom.profile2
-rw-r--r--etc/atril.profile2
-rw-r--r--etc/audacity.profile2
-rw-r--r--etc/aweather.profile2
-rw-r--r--etc/cherrytree.profile13
-rw-r--r--etc/chromium.profile3
-rw-r--r--etc/disable-common.inc35
-rw-r--r--etc/disable-devel.inc2
-rw-r--r--etc/disable-programs.inc14
-rw-r--r--etc/display.profile23
-rw-r--r--etc/eog.profile22
-rw-r--r--etc/evince.profile1
-rw-r--r--etc/evolution.profile25
-rw-r--r--etc/feh.profile6
-rw-r--r--etc/file.profile17
-rw-r--r--etc/filezilla.profile5
-rw-r--r--etc/firejail-default3
-rw-r--r--etc/flowblade.profile13
-rw-r--r--etc/franz.profile6
-rw-r--r--etc/gajim.profile2
-rw-r--r--etc/gimp.profile10
-rw-r--r--etc/git.profile4
-rw-r--r--etc/gpredict.profile4
-rw-r--r--etc/gwenview.profile5
-rw-r--r--etc/gzip.profile14
-rw-r--r--etc/inkscape.profile10
-rw-r--r--etc/jitsi.profile2
-rw-r--r--etc/keepass.profile2
-rw-r--r--etc/kmail.profile2
-rw-r--r--etc/less.profile6
-rw-r--r--etc/libreoffice.profile5
-rw-r--r--etc/luminance-hdr.profile14
-rw-r--r--etc/mumble.profile26
-rw-r--r--etc/mutt.profile1
-rw-r--r--etc/okular.profile5
-rw-r--r--etc/openshot.profile13
-rw-r--r--etc/pidgin.profile2
-rw-r--r--etc/pix.profile3
-rw-r--r--etc/psi-plus.profile4
-rw-r--r--etc/qbittorrent.profile4
-rw-r--r--etc/qpdfview.profile2
-rw-r--r--etc/qtox.profile2
-rw-r--r--etc/quiterss.profile9
-rw-r--r--etc/ranger.profile3
-rw-r--r--etc/rhythmbox.profile2
-rw-r--r--etc/rtorrent.profile1
-rw-r--r--etc/server.profile11
-rw-r--r--etc/slack.profile29
-rw-r--r--etc/spotify.profile22
-rw-r--r--etc/start-tor-browser.profile20
-rw-r--r--etc/strings.profile9
-rw-r--r--etc/synfigstudio.profile6
-rw-r--r--etc/tar.profile14
-rw-r--r--etc/telegram.profile1
-rw-r--r--etc/transmission-gtk.profile2
-rw-r--r--etc/transmission-qt.profile5
-rw-r--r--etc/uget-gtk.profile13
-rw-r--r--etc/unrar.profile15
-rw-r--r--etc/unzip.profile16
-rw-r--r--etc/uudeview.profile14
-rw-r--r--etc/vim.profile3
-rw-r--r--etc/virtualbox.profile12
-rw-r--r--etc/vlc.profile1
-rw-r--r--etc/whitelist-common.inc1
-rw-r--r--etc/xiphos.profile30
-rw-r--r--etc/xpdf.profile18
-rw-r--r--etc/xplayer.profile2
-rw-r--r--etc/xzdec.profile14
-rw-r--r--etc/zathura.profile6
-rwxr-xr-xmkuid.sh2
-rw-r--r--platform/debian/conffiles16
-rwxr-xr-xplatform/rpm/old-mkrpm.sh542
-rw-r--r--src/faudit/syscall.c3
-rw-r--r--src/firecfg/firecfg.config8
-rw-r--r--src/firejail/Makefile.in4
-rw-r--r--src/firejail/appimage.c79
-rw-r--r--src/firejail/appimage_size.c160
-rw-r--r--src/firejail/arp.c186
-rw-r--r--src/firejail/errno.c13
-rw-r--r--src/firejail/firejail.h77
-rw-r--r--src/firejail/fs.c218
-rw-r--r--src/firejail/fs_bin.c7
-rw-r--r--src/firejail/fs_dev.c6
-rw-r--r--src/firejail/fs_etc.c7
-rw-r--r--src/firejail/fs_home.c10
-rw-r--r--src/firejail/fs_hostname.c2
-rw-r--r--src/firejail/fs_mkdir.c4
-rw-r--r--src/firejail/fs_trace.c3
-rw-r--r--src/firejail/fs_var.c3
-rw-r--r--src/firejail/fs_whitelist.c89
-rw-r--r--src/firejail/join.c6
-rw-r--r--src/firejail/list.c101
-rw-r--r--src/firejail/ls.c8
-rw-r--r--src/firejail/main.c119
-rw-r--r--src/firejail/netfilter.c12
-rw-r--r--src/firejail/network.c349
-rw-r--r--src/firejail/network_main.c35
-rw-r--r--src/firejail/preproc.c141
-rw-r--r--src/firejail/profile.c14
-rw-r--r--src/firejail/protocol.c247
-rw-r--r--src/firejail/pulseaudio.c1
-rw-r--r--src/firejail/restrict_users.c3
-rw-r--r--src/firejail/restricted_shell.c16
-rw-r--r--src/firejail/sandbox.c297
-rw-r--r--src/firejail/sbox.c186
-rw-r--r--src/firejail/seccomp.c880
-rw-r--r--src/firejail/util.c64
-rw-r--r--src/firejail/x11.c12
-rw-r--r--src/firemon/interface.c2
-rw-r--r--src/firemon/procevent.c2
-rw-r--r--src/fnet/Makefile.in43
-rw-r--r--src/fnet/arp.c208
-rw-r--r--src/fnet/fnet.h49
-rw-r--r--src/fnet/interface.c395
-rw-r--r--src/fnet/main.c103
-rw-r--r--src/fnet/veth.c (renamed from src/firejail/veth.c)8
-rw-r--r--src/fseccomp/Makefile.in43
-rw-r--r--src/fseccomp/errno.c204
-rw-r--r--src/fseccomp/fseccomp.h68
-rw-r--r--src/fseccomp/main.c91
-rw-r--r--src/fseccomp/protocol.c219
-rw-r--r--src/fseccomp/seccomp.c292
-rw-r--r--src/fseccomp/seccomp_file.c108
-rw-r--r--src/fseccomp/seccomp_print.c116
-rw-r--r--src/fseccomp/seccomp_secondary.c183
-rw-r--r--src/fseccomp/syscall.c (renamed from src/firejail/syscall.c)48
-rw-r--r--src/include/common.h2
-rw-r--r--src/include/seccomp.h (renamed from src/firejail/seccomp.h)0
-rw-r--r--src/include/syscall.h (renamed from src/firejail/syscall.h)1
-rw-r--r--src/lib/common.c9
-rw-r--r--src/lib/pid.c2
-rw-r--r--src/man/firejail-login.txt4
-rw-r--r--src/man/firejail-profile.txt2
-rw-r--r--src/man/firejail.txt2
-rwxr-xr-xtest/apps-x11-xorg/apps-x11-xorg.sh35
-rwxr-xr-xtest/apps-x11-xorg/firefox.exp90
-rwxr-xr-xtest/apps-x11-xorg/icedove.exp85
-rwxr-xr-xtest/apps-x11-xorg/transmission-gtk.exp85
-rwxr-xr-xtest/environment/allow-debuggers.exp18
-rwxr-xr-xtest/filters/filters.sh15
-rwxr-xr-xtest/filters/fseccomp.exp138
-rwxr-xr-xtest/filters/noroot.exp44
-rwxr-xr-xtest/fs/fs.sh3
-rwxr-xr-xtest/fs/sys_fs.exp44
153 files changed, 5018 insertions, 2475 deletions
diff --git a/.gitignore b/.gitignore
index 0d5979c8b..db523da59 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,4 +18,6 @@ src/firecfg/firecfg
18src/ftee/ftee 18src/ftee/ftee
19src/tags 19src/tags
20src/faudit/faudit 20src/faudit/faudit
21src/fnet/fnet
22src/fseccomp/fseccomp
21uids.h 23uids.h
diff --git a/Makefile.in b/Makefile.in
index 3f08c5952..86acc206c 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,6 +1,6 @@
1all: apps man 1all: apps man
2MYLIBS = src/lib 2MYLIBS = src/lib
3APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/libconnect 3APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/libconnect src/fnet src/fseccomp
4MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 4MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5
5 5
6prefix=@prefix@ 6prefix=@prefix@
@@ -76,6 +76,8 @@ realinstall:
76 install -c -m 0755 src/fshaper/fshaper.sh $(DESTDIR)/$(libdir)/firejail/. 76 install -c -m 0755 src/fshaper/fshaper.sh $(DESTDIR)/$(libdir)/firejail/.
77 install -c -m 0644 src/firecfg/firecfg.config $(DESTDIR)/$(libdir)/firejail/. 77 install -c -m 0644 src/firecfg/firecfg.config $(DESTDIR)/$(libdir)/firejail/.
78 install -c -m 0755 src/faudit/faudit $(DESTDIR)/$(libdir)/firejail/. 78 install -c -m 0755 src/faudit/faudit $(DESTDIR)/$(libdir)/firejail/.
79 install -c -m 0755 src/fnet/fnet $(DESTDIR)/$(libdir)/firejail/.
80 install -c -m 0755 src/fseccomp/fseccomp $(DESTDIR)/$(libdir)/firejail/.
79 # documents 81 # documents
80 install -m 0755 -d $(DESTDIR)/$(DOCDIR) 82 install -m 0755 -d $(DESTDIR)/$(DOCDIR)
81 install -c -m 0644 COPYING $(DESTDIR)/$(DOCDIR)/. 83 install -c -m 0644 COPYING $(DESTDIR)/$(DOCDIR)/.
@@ -124,6 +126,8 @@ install-strip: all
124 strip src/libconnect/libconnect.so 126 strip src/libconnect/libconnect.so
125 strip src/ftee/ftee 127 strip src/ftee/ftee
126 strip src/faudit/faudit 128 strip src/faudit/faudit
129 strip src/fnet/fnet
130 strip src/fseccomp/fseccomp
127 $(MAKE) realinstall 131 $(MAKE) realinstall
128 132
129uninstall: 133uninstall:
@@ -141,7 +145,7 @@ uninstall:
141 rm -f $(DESTDIR)/$(datarootdir)/bash-completion/completions/firecfg 145 rm -f $(DESTDIR)/$(datarootdir)/bash-completion/completions/firecfg
142 146
143DISTFILES = "src etc platform configure configure.ac Makefile.in install.sh mkman.sh mketc.sh mkdeb.sh mkuid.sh COPYING README RELNOTES" 147DISTFILES = "src etc platform configure configure.ac Makefile.in install.sh mkman.sh mketc.sh mkdeb.sh mkuid.sh COPYING README RELNOTES"
144DISTFILES_TEST = "test/apps test/apps-x11 test/environment test/profiles test/utils test/compile test/filters test/network test/fs test/sysutils" 148DISTFILES_TEST = "test/apps test/apps-x11 test/apps-x11-xorg test/environment test/profiles test/utils test/compile test/filters test/network test/fs test/sysutils"
145 149
146dist: 150dist:
147 mv config.status config.status.old 151 mv config.status config.status.old
@@ -195,6 +199,9 @@ test-apps:
195test-apps-x11: 199test-apps-x11:
196 cd test/apps-x11; ./apps-x11.sh | grep TESTING 200 cd test/apps-x11; ./apps-x11.sh | grep TESTING
197 201
202test-apps-x11-xorg:
203 cd test/apps-x11-xorg; ./apps-x11-xorg.sh | grep TESTING
204
198test-sysutils: 205test-sysutils:
199 cd test/sysutils; ./sysutils.sh | grep TESTING 206 cd test/sysutils; ./sysutils.sh | grep TESTING
200 207
@@ -213,5 +220,5 @@ test-network:
213test-fs: 220test-fs:
214 cd test/fs; ./fs.sh | grep TESTING 221 cd test/fs; ./fs.sh | grep TESTING
215 222
216test: test-profiles test-fs test-utils test-environment test-apps test-apps-x11 test-filters 223test: test-profiles test-fs test-utils test-environment test-apps test-apps-x11 test-apps-x11-xorg test-filters
217 echo "TEST COMPLETE" 224 echo "TEST COMPLETE"
diff --git a/README b/README
index 043e7445a..428f610f9 100644
--- a/README
+++ b/README
@@ -47,6 +47,7 @@ Aleksey Manevich (https://github.com/manevich)
47 - added --join-or-start command 47 - added --join-or-start command
48 - CVE-2016-7545 48 - CVE-2016-7545
49Fred-Barclay (https://github.com/Fred-Barclay) 49Fred-Barclay (https://github.com/Fred-Barclay)
50 - lots of profile fixes
50 - added Vivaldi, Atril profiles 51 - added Vivaldi, Atril profiles
51 - added PaleMoon profile 52 - added PaleMoon profile
52 - split Icedove and Thunderbird profiles 53 - split Icedove and Thunderbird profiles
@@ -69,7 +70,7 @@ Fred-Barclay (https://github.com/Fred-Barclay)
69 - added audacity profile 70 - added audacity profile
70 - fixed Telegram and qtox profiles 71 - fixed Telegram and qtox profiles
71 - added Atom Beta and Atom profiles 72 - added Atom Beta and Atom profiles
72 - tightened 0ad, atril, evince, gthumb, pix, qtox, and xreader profiles. 73 - tightened 0ad, atril, evince, gthumb, pix, qtox, and xreader profiles
73 - several private-bin conversions 74 - several private-bin conversions
74 - added jitsi profile 75 - added jitsi profile
75 - pidgin private-bin conversion 76 - pidgin private-bin conversion
@@ -77,13 +78,32 @@ Fred-Barclay (https://github.com/Fred-Barclay)
77 - added gnome-chess profile 78 - added gnome-chess profile
78 - added DOSBox profile 79 - added DOSBox profile
79 - evince profile enhancement 80 - evince profile enhancement
81 - tightened Spotify profile
82 - added xiphos and Tor Browser Bundle profiles
83Impyy (https://github.com/Impyy)
84 - added mumble profile
85valoq (https://github.com/valoq)
86 - LibreOffice profile fixes
87 - cherrytree profile fixes
88 - added support for /srv in --whitelist feature
89 - Eye of GNOME, Evolution, display (imagemagik) and Wire profiles
90 - blacklist suid binaries in disable-common.inc
91Vadim A. Misbakh-Soloviov (https://github.com/msva)
92 - profile fixes
93Rafael Cavalcanti (https://github.com/rccavalcanti)
94 - chromium profile fixes for Arch Linux
95Deelvesh Bunjun (https://github.com/DeelveshBunjun)
96 - added xpdf profile
97vismir2 (https://github.com/vismir2)
98 - claws-mail, mutt, git, emacs, vim profiles
99Dara Adib (https://github.com/daradib)
100 - ssh profile fix
101 - evince profile fix
80vismir2 (https://github.com/vismir2) 102vismir2 (https://github.com/vismir2)
81 - feh, ranger, 7z, keepass, keepassx and zathura profiles 103 - feh, ranger, 7z, keepass, keepassx and zathura profiles
82 - lots of profile fixes 104 - lots of profile fixes
83graywolf (https://github.com/graywolf) 105graywolf (https://github.com/graywolf)
84 - spelling fix 106 - spelling fix
85Dara Adib (https://github.com/daradib)
86 - ssh profile fix
87Tomasz Jan Góralczyk (https://github.com/tjg) 107Tomasz Jan Góralczyk (https://github.com/tjg)
88 - fixed Steam profile 108 - fixed Steam profile
89pwnage-pineapple (https://github.com/pwnage-pineapple) 109pwnage-pineapple (https://github.com/pwnage-pineapple)
diff --git a/README.md b/README.md
index 6e50a7645..c6484d3b7 100644
--- a/README.md
+++ b/README.md
@@ -40,75 +40,17 @@ FAQ: https://firejail.wordpress.com/support/frequently-asked-questions/
40If you keep your Firejail profiles in a public repository, please give us a link: 40If you keep your Firejail profiles in a public repository, please give us a link:
41 41
42* https://github.com/chiraag-nataraj/firejail-profiles 42* https://github.com/chiraag-nataraj/firejail-profiles
43`````
44 43
45````` 44* https://github.com/triceratops1/fe
46# Current development version: 0.9.43
47 45
48## X11 development 46Use this issue to request new profiles: https://github.com/netblue30/firejail/issues/825
49`````
50 --x11=none
51 Blacklist /tmp/.X11-unix directory, ${HOME}/.Xauthority and the
52 file specified in ${XAUTHORITY} environment variable. Remove
53 DISPLAY and XAUTHORITY environment variables. Stop with error
54 message if X11 abstract socket will be accessible in jail.
55
56 --x11=xorg
57 Sandbox the application using the untrusted mode implemented by
58 X11 security extension. The extension is available in Xorg
59 package and it is installed by default on most Linux distribu‐
60 tions. It provides support for a simple trusted/untrusted con‐
61 nection model. Untrusted clients are restricted in certain ways
62 to prevent them from reading window contents of other clients,
63 stealing input events, etc.
64
65 The untrusted mode has several limitations. A lot of regular
66 programs assume they are a trusted X11 clients and will crash
67 or lock up when run in untrusted mode. Chromium browser and
68 xterm are two examples. Firefox and transmission-gtk seem to be
69 working fine. A network namespace is not required for this
70 option.
71
72 Example:
73 $ firejail --x11=xorg firefox
74````` 47`````
75 48
76## Other command line options
77````` 49`````
78 --put=name|pid src-filename dest-filename 50# Current development version: 0.9.45
79 Put src-filename in sandbox container. The container is specified by name or PID.
80
81 --allusers
82 All user home directories are visible inside the sandbox. By default, only current user home
83 directory is visible.
84
85 Example:
86 $ firejail --allusers
87
88 --join-or-start=name
89 Join the sandbox identified by name or start a new one. Same as "firejail --join=name" if
90 sandbox with specified name exists, otherwise same as "firejail --name=name ..."
91 Note that in contrary to other join options there is respective profile option.
92
93 --no3d Disable 3D hardware acceleration.
94
95 Example:
96 $ firejail --no3d firefox
97
98 --veth-name=name
99 Use this name for the interface connected to the bridge for
100 --net=bridge_interface commands, instead of the default one.
101
102 Example:
103 $ firejail --net=br0 --veth-name=if0
104
105````` 51`````
106 52
107## New profile commands 53`````
108 54## New Profiles
109x11 xpra, x11 xephyr, x11 none, x11 xorg, allusers, join-or-start 55xiphos, Tor Browser Bundle, display (imagemagik), Wire, mumble
110
111## New profiles
112
113qpdfview, mupdf, Luminance HDR, Synfig Studio, Gimp, Inkscape, feh, ranger, zathura, 7z, keepass, keepassx
114 56
diff --git a/RELNOTES b/RELNOTES
index bdafb6ff0..44d313999 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -1,9 +1,19 @@
1firejail (0.9.43) baseline; urgency=low 1firejail (0.9.45) baseline; urgency=low
2 * development version, work in progress
3 * security: overwrite /etc/resolv.conf found by Martin Carpenter
4 * feature: allow root user access to /dev/shm (--noblacklist=/dev/shm)
5 * feature: split most of networking code in a separate executable
6 * new profiles: xiphos, Tor Browser Bundle, display (imagemagik), Wire
7 * bugfixes
8 -- netblue30 <netblue30@yahoo.com> Sun, 23 Oct 2016 08:00:00 -0500
9
10firejail (0.9.44) baseline; urgency=low
2 * CVE-2016-7545 submitted by Aleksey Manevich 11 * CVE-2016-7545 submitted by Aleksey Manevich
3 * development version
4 * modifs: removed man firejail-config 12 * modifs: removed man firejail-config
5 * modifs: --private-tmp whitelists /tmp/.X11-unix directory 13 * modifs: --private-tmp whitelists /tmp/.X11-unix directory
6 * modifs: Nvidia drivers added to --private-dev 14 * modifs: Nvidia drivers added to --private-dev
15 * modifs: /srv supported by --whitelist
16 * feature: allow user access to /sys/fs (--noblacklist=/sys/fs)
7 * feature: support starting/joining sandbox is a single command 17 * feature: support starting/joining sandbox is a single command
8 (--join-or-start) 18 (--join-or-start)
9 * feature: X11 detection support for --audit 19 * feature: X11 detection support for --audit
@@ -15,10 +25,15 @@ firejail (0.9.43) baseline; urgency=low
15 * feature: X11 security extension (--x11=xorg) 25 * feature: X11 security extension (--x11=xorg)
16 * feature: disable 3D hardware acceleration (--no3d) 26 * feature: disable 3D hardware acceleration (--no3d)
17 * feature: x11 xpra, x11 xephyr, x11 block, allusers, no3d profile commands 27 * feature: x11 xpra, x11 xephyr, x11 block, allusers, no3d profile commands
28 * feature: move files in sandbox (--put)
29 * feature: accept wildcard patterns in user name field of restricted
30 shell login feature
18 * new profiles: qpdfview, mupdf, Luminance HDR, Synfig Studio, Gimp, Inkscape 31 * new profiles: qpdfview, mupdf, Luminance HDR, Synfig Studio, Gimp, Inkscape
19 * new profiles: feh, ranger, zathura, 7z, keepass, keepassx 32 * new profiles: feh, ranger, zathura, 7z, keepass, keepassx,
33 * new profiles: claws-mail, mutt, git, emacs, vim, xpdf, VirtualBox, OpenShot
34 * new profiles: Flowblade, Eye of GNOME (eog), Evolution
20 * bugfixes 35 * bugfixes
21 -- netblue30 <netblue30@yahoo.com> Fri, 9 Sept 2016 08:00:00 -0500 36 -- netblue30 <netblue30@yahoo.com> Fri, 21 Oct 2016 08:00:00 -0500
22 37
23firejail (0.9.42) baseline; urgency=low 38firejail (0.9.42) baseline; urgency=low
24 * security: --whitelist deleted files, submitted by Vasya Novikov 39 * security: --whitelist deleted files, submitted by Vasya Novikov
diff --git a/configure b/configure
index 5e066a44d..a89fddbef 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
1#! /bin/sh 1#! /bin/sh
2# Guess values for system-dependent variables and create Makefiles. 2# Guess values for system-dependent variables and create Makefiles.
3# Generated by GNU Autoconf 2.69 for firejail 0.9.43. 3# Generated by GNU Autoconf 2.69 for firejail 0.9.45.
4# 4#
5# Report bugs to <netblue30@yahoo.com>. 5# Report bugs to <netblue30@yahoo.com>.
6# 6#
@@ -580,8 +580,8 @@ MAKEFLAGS=
580# Identity of this package. 580# Identity of this package.
581PACKAGE_NAME='firejail' 581PACKAGE_NAME='firejail'
582PACKAGE_TARNAME='firejail' 582PACKAGE_TARNAME='firejail'
583PACKAGE_VERSION='0.9.43' 583PACKAGE_VERSION='0.9.45'
584PACKAGE_STRING='firejail 0.9.43' 584PACKAGE_STRING='firejail 0.9.45'
585PACKAGE_BUGREPORT='netblue30@yahoo.com' 585PACKAGE_BUGREPORT='netblue30@yahoo.com'
586PACKAGE_URL='http://firejail.wordpress.com' 586PACKAGE_URL='http://firejail.wordpress.com'
587 587
@@ -1259,7 +1259,7 @@ if test "$ac_init_help" = "long"; then
1259 # Omit some internal or obsolete options to make the list less imposing. 1259 # Omit some internal or obsolete options to make the list less imposing.
1260 # This message is too long to be a string in the A/UX 3.1 sh. 1260 # This message is too long to be a string in the A/UX 3.1 sh.
1261 cat <<_ACEOF 1261 cat <<_ACEOF
1262\`configure' configures firejail 0.9.43 to adapt to many kinds of systems. 1262\`configure' configures firejail 0.9.45 to adapt to many kinds of systems.
1263 1263
1264Usage: $0 [OPTION]... [VAR=VALUE]... 1264Usage: $0 [OPTION]... [VAR=VALUE]...
1265 1265
@@ -1320,7 +1320,7 @@ fi
1320 1320
1321if test -n "$ac_init_help"; then 1321if test -n "$ac_init_help"; then
1322 case $ac_init_help in 1322 case $ac_init_help in
1323 short | recursive ) echo "Configuration of firejail 0.9.43:";; 1323 short | recursive ) echo "Configuration of firejail 0.9.45:";;
1324 esac 1324 esac
1325 cat <<\_ACEOF 1325 cat <<\_ACEOF
1326 1326
@@ -1424,7 +1424,7 @@ fi
1424test -n "$ac_init_help" && exit $ac_status 1424test -n "$ac_init_help" && exit $ac_status
1425if $ac_init_version; then 1425if $ac_init_version; then
1426 cat <<\_ACEOF 1426 cat <<\_ACEOF
1427firejail configure 0.9.43 1427firejail configure 0.9.45
1428generated by GNU Autoconf 2.69 1428generated by GNU Autoconf 2.69
1429 1429
1430Copyright (C) 2012 Free Software Foundation, Inc. 1430Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1726,7 +1726,7 @@ cat >config.log <<_ACEOF
1726This file contains any messages produced by compilers while 1726This file contains any messages produced by compilers while
1727running configure, to aid debugging if configure makes a mistake. 1727running configure, to aid debugging if configure makes a mistake.
1728 1728
1729It was created by firejail $as_me 0.9.43, which was 1729It was created by firejail $as_me 0.9.45, which was
1730generated by GNU Autoconf 2.69. Invocation command line was 1730generated by GNU Autoconf 2.69. Invocation command line was
1731 1731
1732 $ $0 $@ 1732 $ $0 $@
@@ -3759,7 +3759,7 @@ if test "$prefix" = /usr; then
3759 sysconfdir="/etc" 3759 sysconfdir="/etc"
3760fi 3760fi
3761 3761
3762ac_config_files="$ac_config_files Makefile src/lib/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile" 3762ac_config_files="$ac_config_files Makefile src/lib/Makefile src/fnet/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile src/fseccomp/Makefile"
3763 3763
3764cat >confcache <<\_ACEOF 3764cat >confcache <<\_ACEOF
3765# This file is a shell script that caches the results of configure 3765# This file is a shell script that caches the results of configure
@@ -4303,7 +4303,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
4303# report actual input values of CONFIG_FILES etc. instead of their 4303# report actual input values of CONFIG_FILES etc. instead of their
4304# values after options handling. 4304# values after options handling.
4305ac_log=" 4305ac_log="
4306This file was extended by firejail $as_me 0.9.43, which was 4306This file was extended by firejail $as_me 0.9.45, which was
4307generated by GNU Autoconf 2.69. Invocation command line was 4307generated by GNU Autoconf 2.69. Invocation command line was
4308 4308
4309 CONFIG_FILES = $CONFIG_FILES 4309 CONFIG_FILES = $CONFIG_FILES
@@ -4357,7 +4357,7 @@ _ACEOF
4357cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 4357cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
4358ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" 4358ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
4359ac_cs_version="\\ 4359ac_cs_version="\\
4360firejail config.status 0.9.43 4360firejail config.status 0.9.45
4361configured by $0, generated by GNU Autoconf 2.69, 4361configured by $0, generated by GNU Autoconf 2.69,
4362 with options \\"\$ac_cs_config\\" 4362 with options \\"\$ac_cs_config\\"
4363 4363
@@ -4470,6 +4470,7 @@ do
4470 case $ac_config_target in 4470 case $ac_config_target in
4471 "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; 4471 "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
4472 "src/lib/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib/Makefile" ;; 4472 "src/lib/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib/Makefile" ;;
4473 "src/fnet/Makefile") CONFIG_FILES="$CONFIG_FILES src/fnet/Makefile" ;;
4473 "src/firejail/Makefile") CONFIG_FILES="$CONFIG_FILES src/firejail/Makefile" ;; 4474 "src/firejail/Makefile") CONFIG_FILES="$CONFIG_FILES src/firejail/Makefile" ;;
4474 "src/firemon/Makefile") CONFIG_FILES="$CONFIG_FILES src/firemon/Makefile" ;; 4475 "src/firemon/Makefile") CONFIG_FILES="$CONFIG_FILES src/firemon/Makefile" ;;
4475 "src/libtrace/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtrace/Makefile" ;; 4476 "src/libtrace/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtrace/Makefile" ;;
@@ -4478,6 +4479,7 @@ do
4478 "src/ftee/Makefile") CONFIG_FILES="$CONFIG_FILES src/ftee/Makefile" ;; 4479 "src/ftee/Makefile") CONFIG_FILES="$CONFIG_FILES src/ftee/Makefile" ;;
4479 "src/faudit/Makefile") CONFIG_FILES="$CONFIG_FILES src/faudit/Makefile" ;; 4480 "src/faudit/Makefile") CONFIG_FILES="$CONFIG_FILES src/faudit/Makefile" ;;
4480 "src/libconnect/Makefile") CONFIG_FILES="$CONFIG_FILES src/libconnect/Makefile" ;; 4481 "src/libconnect/Makefile") CONFIG_FILES="$CONFIG_FILES src/libconnect/Makefile" ;;
4482 "src/fseccomp/Makefile") CONFIG_FILES="$CONFIG_FILES src/fseccomp/Makefile" ;;
4481 4483
4482 *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; 4484 *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
4483 esac 4485 esac
diff --git a/configure.ac b/configure.ac
index a1d65cc63..9e7680d7d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
1AC_PREREQ([2.68]) 1AC_PREREQ([2.68])
2AC_INIT(firejail, 0.9.43, netblue30@yahoo.com, , http://firejail.wordpress.com) 2AC_INIT(firejail, 0.9.45, netblue30@yahoo.com, , http://firejail.wordpress.com)
3AC_CONFIG_SRCDIR([src/firejail/main.c]) 3AC_CONFIG_SRCDIR([src/firejail/main.c])
4#AC_CONFIG_HEADERS([config.h]) 4#AC_CONFIG_HEADERS([config.h])
5 5
@@ -148,7 +148,8 @@ if test "$prefix" = /usr; then
148 sysconfdir="/etc" 148 sysconfdir="/etc"
149fi 149fi
150 150
151AC_OUTPUT(Makefile src/lib/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile) 151AC_OUTPUT(Makefile src/lib/Makefile src/fnet/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile \
152src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile src/fseccomp/Makefile)
152 153
153echo 154echo
154echo "Configuration options:" 155echo "Configuration options:"
diff --git a/etc/Wire.profile b/etc/Wire.profile
new file mode 100644
index 000000000..b488d75e4
--- /dev/null
+++ b/etc/Wire.profile
@@ -0,0 +1,22 @@
1# wire messenger profile
2
3noblacklist ~/.config/Wire
4
5include /etc/firejail/disable-common.inc
6include /etc/firejail/disable-programs.inc
7include /etc/firejail/disable-devel.inc
8include /etc/firejail/disable-passwdmgr.inc
9
10caps.drop all
11netfilter
12nonewprivs
13nogroups
14noroot
15protocol unix,inet,inet6,netlink
16seccomp
17shell none
18
19private-tmp
20private-dev
21
22# please note: the wire binary is currently identified with a capital W. This might change in future versions
diff --git a/etc/atom-beta.profile b/etc/atom-beta.profile
index 9a8d93875..fa0b316bb 100644
--- a/etc/atom-beta.profile
+++ b/etc/atom-beta.profile
@@ -8,8 +8,8 @@ include /etc/firejail/disable-passwdmgr.inc
8 8
9caps.drop all 9caps.drop all
10netfilter 10netfilter
11nonewprivs
12nogroups 11nogroups
12nonewprivs
13noroot 13noroot
14nosound 14nosound
15protocol unix,inet,inet6,netlink 15protocol unix,inet,inet6,netlink
diff --git a/etc/atom.profile b/etc/atom.profile
index 3cb86847e..61930d5c1 100644
--- a/etc/atom.profile
+++ b/etc/atom.profile
@@ -8,8 +8,8 @@ include /etc/firejail/disable-passwdmgr.inc
8 8
9caps.drop all 9caps.drop all
10netfilter 10netfilter
11nonewprivs
12nogroups 11nogroups
12nonewprivs
13noroot 13noroot
14nosound 14nosound
15protocol unix,inet,inet6,netlink 15protocol unix,inet,inet6,netlink
diff --git a/etc/atril.profile b/etc/atril.profile
index d9e10b072..fbcca0c1b 100644
--- a/etc/atril.profile
+++ b/etc/atril.profile
@@ -7,8 +7,8 @@ include /etc/firejail/disable-devel.inc
7include /etc/firejail/disable-passwdmgr.inc 7include /etc/firejail/disable-passwdmgr.inc
8 8
9caps.drop all 9caps.drop all
10nonewprivs
11nogroups 10nogroups
11nonewprivs
12noroot 12noroot
13nosound 13nosound
14protocol unix 14protocol unix
diff --git a/etc/audacity.profile b/etc/audacity.profile
index be3fac9be..827fa4301 100644
--- a/etc/audacity.profile
+++ b/etc/audacity.profile
@@ -8,8 +8,8 @@ include /etc/firejail/disable-programs.inc
8 8
9caps.drop all 9caps.drop all
10netfilter 10netfilter
11nonewprivs
12nogroups 11nogroups
12nonewprivs
13noroot 13noroot
14protocol unix 14protocol unix
15seccomp 15seccomp
diff --git a/etc/aweather.profile b/etc/aweather.profile
index 4e5c36f50..fa8654f1e 100644
--- a/etc/aweather.profile
+++ b/etc/aweather.profile
@@ -11,8 +11,8 @@ whitelist ~/.config/aweather
11 11
12caps.drop all 12caps.drop all
13netfilter 13netfilter
14nonewprivs
15nogroups 14nogroups
15nonewprivs
16noroot 16noroot
17nosound 17nosound
18protocol unix,inet,inet6 18protocol unix,inet,inet6
diff --git a/etc/cherrytree.profile b/etc/cherrytree.profile
index 7c324a34b..139dec8ec 100644
--- a/etc/cherrytree.profile
+++ b/etc/cherrytree.profile
@@ -1,6 +1,7 @@
1# cherrytree note taking application 1# cherrytree note taking application
2noblacklist /usr/bin/python2* 2noblacklist /usr/bin/python2*
3noblacklist /usr/lib/python3* 3noblacklist /usr/lib/python3*
4noblacklist ${HOME}/.config/cherrytree
4include /etc/firejail/disable-common.inc 5include /etc/firejail/disable-common.inc
5include /etc/firejail/disable-programs.inc 6include /etc/firejail/disable-programs.inc
6include /etc/firejail/disable-devel.inc 7include /etc/firejail/disable-devel.inc
@@ -8,20 +9,10 @@ include /etc/firejail/disable-passwdmgr.inc
8 9
9caps.drop all 10caps.drop all
10netfilter 11netfilter
12nogroups
11nonewprivs 13nonewprivs
12noroot 14noroot
13nosound 15nosound
14seccomp 16seccomp
15protocol unix,inet,inet6,netlink 17protocol unix,inet,inet6,netlink
16tracelog 18tracelog
17
18include /etc/firejail/whitelist-common.inc
19
20# no private-bin support for various reasons:
21#10:25:34 exec 11249 (root) NEW SANDBOX: /usr/bin/firejail /usr/bin/cherrytree
22#10:25:34 exec 11252 (netblue) /bin/bash -c "/usr/bin/cherrytree"
23#10:25:34 exec 11252 (netblue) /usr/bin/python /usr/bin/cherrytree
24#10:25:34 exec 11253 (netblue) sh -c /sbin/ldconfig -p 2>/dev/null
25#10:25:34 exec 11255 (netblue) sh -c if type gcc >/dev/null 2>&1; then CC=gcc; elif type cc >/dev/null 2>&1; then CC=cc;else exit 10; fi;LANG=C LC_ALL=C $CC -Wl,-t -o /tmp/tmpiYr44S 2>&1 -llibc
26# it requires acces to browser to show the online help
27# it doesn't play nicely with expect
diff --git a/etc/chromium.profile b/etc/chromium.profile
index 0d383aebf..4109af9a4 100644
--- a/etc/chromium.profile
+++ b/etc/chromium.profile
@@ -25,4 +25,7 @@ whitelist ~/keepassx.kdbx
25whitelist ~/.lastpass 25whitelist ~/.lastpass
26whitelist ~/.config/lastpass 26whitelist ~/.config/lastpass
27 27
28# specific to Arch
29whitelist ~/.config/chromium-flags.conf
30
28include /etc/firejail/whitelist-common.inc 31include /etc/firejail/whitelist-common.inc
diff --git a/etc/disable-common.inc b/etc/disable-common.inc
index 4f854c8d8..38a8b86d6 100644
--- a/etc/disable-common.inc
+++ b/etc/disable-common.inc
@@ -1,6 +1,7 @@
1# History files in $HOME 1# History files in $HOME
2blacklist-nolog ${HOME}/.history 2blacklist-nolog ${HOME}/.history
3blacklist-nolog ${HOME}/.*_history 3blacklist-nolog ${HOME}/.*_history
4blacklist-nolog ${HOME}/.bash_history
4blacklist ${HOME}/.local/share/systemd 5blacklist ${HOME}/.local/share/systemd
5blacklist-nolog ${HOME}/.adobe 6blacklist-nolog ${HOME}/.adobe
6blacklist-nolog ${HOME}/.macromedia 7blacklist-nolog ${HOME}/.macromedia
@@ -23,6 +24,7 @@ blacklist ${HOME}/.config/openbox/autostart
23blacklist ${HOME}/.config/openbox/environment 24blacklist ${HOME}/.config/openbox/environment
24blacklist ${HOME}/.gnomerc 25blacklist ${HOME}/.gnomerc
25blacklist /etc/X11/Xsession.d/ 26blacklist /etc/X11/Xsession.d/
27blacklist ${HOME}/.xpra
26 28
27# VirtualBox 29# VirtualBox
28blacklist ${HOME}/.VirtualBox 30blacklist ${HOME}/.VirtualBox
@@ -96,9 +98,6 @@ read-only ${HOME}/.emacs.d
96read-only ${HOME}/.nano 98read-only ${HOME}/.nano
97read-only ${HOME}/.tmux.conf 99read-only ${HOME}/.tmux.conf
98read-only ${HOME}/.iscreenrc 100read-only ${HOME}/.iscreenrc
99read-only ${HOME}/.muttrc
100read-only ${HOME}/.mutt/muttrc
101read-only ${HOME}/.msmtprc
102read-only ${HOME}/.reportbugrc 101read-only ${HOME}/.reportbugrc
103read-only ${HOME}/.xmonad 102read-only ${HOME}/.xmonad
104read-only ${HOME}/.xscreensaver 103read-only ${HOME}/.xscreensaver
@@ -137,6 +136,11 @@ blacklist /etc/gshadow+
137blacklist /etc/ssh 136blacklist /etc/ssh
138blacklist /var/backup 137blacklist /var/backup
139 138
139# system directories
140blacklist /sbin
141blacklist /usr/sbin
142blacklist /usr/local/sbin
143
140# system management 144# system management
141blacklist ${PATH}/umount 145blacklist ${PATH}/umount
142blacklist ${PATH}/mount 146blacklist ${PATH}/mount
@@ -149,11 +153,22 @@ blacklist ${PATH}/xev
149blacklist ${PATH}/strace 153blacklist ${PATH}/strace
150blacklist ${PATH}/nc 154blacklist ${PATH}/nc
151blacklist ${PATH}/ncat 155blacklist ${PATH}/ncat
152 156blacklist ${PATH}/gpasswd
153# system directories 157blacklist ${PATH}/newgidmap
154blacklist /sbin 158blacklist ${PATH}/newgrp
155blacklist /usr/sbin 159blacklist ${PATH}/newuidmap
156blacklist /usr/local/sbin 160blacklist ${PATH}/pkexec
161blacklist ${PATH}/sg
162blacklist ${PATH}/rsh
163blacklist ${PATH}/rlogin
164blacklist ${PATH}/rcp
165blacklist ${PATH}/crontab
166blacklist ${PATH}/ksu
167blacklist ${PATH}/chsh
168blacklist ${PATH}/chfn
169blacklist ${PATH}/chage
170blacklist ${PATH}/expiry
171blacklist ${PATH}/unix_chkpwd
157 172
158# prevent lxterminal connecting to an existing lxterminal session 173# prevent lxterminal connecting to an existing lxterminal session
159blacklist /tmp/.lxterminal-socket* 174blacklist /tmp/.lxterminal-socket*
@@ -172,3 +187,7 @@ blacklist ${PATH}/roxterm-config
172blacklist ${PATH}/terminix 187blacklist ${PATH}/terminix
173blacklist ${PATH}/urxvtc 188blacklist ${PATH}/urxvtc
174blacklist ${PATH}/urxvtcd 189blacklist ${PATH}/urxvtcd
190
191# kernel files
192blacklist /vmlinuz*
193blacklist /initrd*
diff --git a/etc/disable-devel.inc b/etc/disable-devel.inc
index 971857710..2ac367f37 100644
--- a/etc/disable-devel.inc
+++ b/etc/disable-devel.inc
@@ -20,7 +20,7 @@ blacklist /usr/bin/x86_64-unknown-linux-gnu-gcc*
20# clang/llvm 20# clang/llvm
21blacklist /usr/bin/clang* 21blacklist /usr/bin/clang*
22blacklist /usr/bin/llvm* 22blacklist /usr/bin/llvm*
23blacklist /usb/bin/lldb* 23blacklist /usr/bin/lldb*
24blacklist /usr/lib/llvm* 24blacklist /usr/lib/llvm*
25 25
26# tcc - Tiny C Compiler 26# tcc - Tiny C Compiler
diff --git a/etc/disable-programs.inc b/etc/disable-programs.inc
index c13885739..0d9bd1bb4 100644
--- a/etc/disable-programs.inc
+++ b/etc/disable-programs.inc
@@ -7,6 +7,8 @@ blacklist ${HOME}/.wine
7blacklist ${HOME}/.Mathematica 7blacklist ${HOME}/.Mathematica
8blacklist ${HOME}/.Wolfram Research 8blacklist ${HOME}/.Wolfram Research
9blacklist ${HOME}/.stellarium 9blacklist ${HOME}/.stellarium
10blacklist ${HOME}/.sword
11blacklist ${HOME}/.xiphos
10blacklist ${HOME}/.config/Atom 12blacklist ${HOME}/.config/Atom
11blacklist ${HOME}/.config/gthumb 13blacklist ${HOME}/.config/gthumb
12blacklist ${HOME}/.config/mupen64plus 14blacklist ${HOME}/.config/mupen64plus
@@ -33,6 +35,13 @@ blacklist ${HOME}/.synfig
33blacklist ${HOME}/.inkscape 35blacklist ${HOME}/.inkscape
34blacklist ${HOME}/.gimp* 36blacklist ${HOME}/.gimp*
35blacklist ${HOME}/.config/zathura 37blacklist ${HOME}/.config/zathura
38blacklist ${HOME}/.config/cherrytree
39blacklist ${HOME}/.xpdfrc
40blacklist ${HOME}/.openshot
41blacklist ${HOME}/.openshot_qt
42blacklist ${HOME}/.flowblade
43blacklist ${HOME}/.config/flowblade
44blacklist ${HOME}/.config/eog
36 45
37 46
38# Media players 47# Media players
@@ -70,8 +79,12 @@ blacklist ${HOME}/.8pecxstudios
70blacklist ${HOME}/.config/brave 79blacklist ${HOME}/.config/brave
71blacklist ${HOME}/.config/inox 80blacklist ${HOME}/.config/inox
72blacklist ${HOME}/.muttrc 81blacklist ${HOME}/.muttrc
82blacklist ${HOME}/.mutt
73blacklist ${HOME}/.mutt/muttrc 83blacklist ${HOME}/.mutt/muttrc
74blacklist ${HOME}/.msmtprc 84blacklist ${HOME}/.msmtprc
85blacklist ${HOME}/.config/evolution
86blacklist ${HOME}/.local/share/evolution
87blacklist ${HOME}/.cache/evolution
75 88
76# Instant Messaging 89# Instant Messaging
77blacklist ${HOME}/.config/hexchat 90blacklist ${HOME}/.config/hexchat
@@ -93,6 +106,7 @@ blacklist ${HOME}/.config/Slack
93blacklist ${HOME}/.cache/gajim 106blacklist ${HOME}/.cache/gajim
94blacklist ${HOME}/.local/share/gajim 107blacklist ${HOME}/.local/share/gajim
95blacklist ${HOME}/.config/gajim 108blacklist ${HOME}/.config/gajim
109blacklist ${HOME}/.config/Wire
96 110
97# Games 111# Games
98blacklist ${HOME}/.hedgewars 112blacklist ${HOME}/.hedgewars
diff --git a/etc/display.profile b/etc/display.profile
new file mode 100644
index 000000000..ec041bff7
--- /dev/null
+++ b/etc/display.profile
@@ -0,0 +1,23 @@
1# display (ImageMagick tool) image viewer profile
2include /etc/firejail/disable-common.inc
3include /etc/firejail/disable-programs.inc
4include /etc/firejail/disable-devel.inc
5include /etc/firejail/disable-passwdmgr.inc
6
7caps.drop all
8seccomp
9protocol unix
10netfilter
11net none
12nonewprivs
13noroot
14nogroups
15nosound
16shell none
17x11 xorg
18
19private-bin display
20private-tmp
21private-dev
22private-etc none
23
diff --git a/etc/eog.profile b/etc/eog.profile
new file mode 100644
index 000000000..7eb7fd127
--- /dev/null
+++ b/etc/eog.profile
@@ -0,0 +1,22 @@
1# eog (gnome image viewer) profile
2
3noblacklist ~/.config/eog
4
5include /etc/firejail/disable-common.inc
6include /etc/firejail/disable-programs.inc
7include /etc/firejail/disable-devel.inc
8include /etc/firejail/disable-passwdmgr.inc
9
10caps.drop all
11netfilter
12nogroups
13nonewprivs
14noroot
15protocol unix
16seccomp
17shell none
18
19private-bin eog
20private-dev
21private-etc fonts
22private-tmp
diff --git a/etc/evince.profile b/etc/evince.profile
index 374fa4aaa..894c7c70d 100644
--- a/etc/evince.profile
+++ b/etc/evince.profile
@@ -15,5 +15,4 @@ shell none
15tracelog 15tracelog
16 16
17private-bin evince,evince-previewer,evince-thumbnailer 17private-bin evince,evince-previewer,evince-thumbnailer
18whitelist /tmp/.X11-unix
19private-dev 18private-dev
diff --git a/etc/evolution.profile b/etc/evolution.profile
new file mode 100644
index 000000000..d097c0f34
--- /dev/null
+++ b/etc/evolution.profile
@@ -0,0 +1,25 @@
1# evolution profile
2
3noblacklist ~/.config/evolution
4noblacklist ~/.local/share/evolution
5noblacklist ~/.cache/evolution
6noblacklist ~/.pki
7noblacklist ~/.pki/nssdb
8noblacklist ~/.gnupg
9
10include /etc/firejail/disable-common.inc
11include /etc/firejail/disable-programs.inc
12include /etc/firejail/disable-devel.inc
13include /etc/firejail/disable-passwdmgr.inc
14
15caps.drop all
16netfilter
17nogroups
18nonewprivs
19noroot
20protocol unix,inet,inet6
21seccomp
22shell none
23
24private-dev
25private-tmp
diff --git a/etc/feh.profile b/etc/feh.profile
index 5fcb6bf25..e3b1ec528 100644
--- a/etc/feh.profile
+++ b/etc/feh.profile
@@ -5,14 +5,14 @@ include /etc/firejail/disable-devel.inc
5include /etc/firejail/disable-passwdmgr.inc 5include /etc/firejail/disable-passwdmgr.inc
6 6
7caps.drop all 7caps.drop all
8seccomp
9protocol unix
10netfilter 8netfilter
11net none 9net none
10nogroups
12nonewprivs 11nonewprivs
13noroot 12noroot
14nogroups
15nosound 13nosound
14protocol unix
15seccomp
16shell none 16shell none
17 17
18private-bin feh 18private-bin feh
diff --git a/etc/file.profile b/etc/file.profile
index 2e54030b1..199a97fad 100644
--- a/etc/file.profile
+++ b/etc/file.profile
@@ -1,16 +1,17 @@
1# file profile 1# file profile
2quiet
3ignore noroot 2ignore noroot
4include /etc/firejail/default.profile 3include /etc/firejail/default.profile
5 4
6tracelog 5blacklist /tmp/.X11-unix
6
7hostname file
7net none 8net none
9no3d
10nosound
11quiet
8shell none 12shell none
13tracelog
14
15private-dev
9private-bin file 16private-bin file
10private-etc magic.mgc,magic,localtime 17private-etc magic.mgc,magic,localtime
11hostname file
12private-dev
13nosound
14no3d
15blacklist /tmp/.X11-unix
16
diff --git a/etc/filezilla.profile b/etc/filezilla.profile
index 551c17a78..fe1d9d20d 100644
--- a/etc/filezilla.profile
+++ b/etc/filezilla.profile
@@ -13,10 +13,9 @@ noroot
13nosound 13nosound
14protocol unix,inet,inet6 14protocol unix,inet,inet6
15seccomp 15seccomp
16
17shell none 16shell none
17
18private-bin filezilla,uname,sh,python,lsb_release,fzputtygen,fzsftp 18private-bin filezilla,uname,sh,python,lsb_release,fzputtygen,fzsftp
19whitelist /tmp/.X11-unix
20private-dev 19private-dev
21nosound
22 20
21whitelist /tmp/.X11-unix
diff --git a/etc/firejail-default b/etc/firejail-default
index 0b771f834..1b0eb7658 100644
--- a/etc/firejail-default
+++ b/etc/firejail-default
@@ -31,6 +31,9 @@ profile firejail-default {
31/{,var/}run/user/**/pulse/ rw, 31/{,var/}run/user/**/pulse/ rw,
32/{,var/}run/user/**/pulse/** rw, 32/{,var/}run/user/**/pulse/** rw,
33/{,var/}run/firejail/mnt/fslogger r, 33/{,var/}run/firejail/mnt/fslogger r,
34/{,var/}run/firejail/appimage r,
35/{,var/}run/firejail/appimage/** r,
36/{,var/}run/firejail/appimage/** ix,
34/{run,dev}/shm/ r, 37/{run,dev}/shm/ r,
35/{run,dev}/shm/** rmwk, 38/{run,dev}/shm/** rmwk,
36 39
diff --git a/etc/flowblade.profile b/etc/flowblade.profile
new file mode 100644
index 000000000..12afdb0aa
--- /dev/null
+++ b/etc/flowblade.profile
@@ -0,0 +1,13 @@
1# FlowBlade profile
2noblacklist ${HOME}/.flowblade
3noblacklist ${HOME}/.config/flowblade
4include /etc/firejail/disable-common.inc
5include /etc/firejail/disable-programs.inc
6include /etc/firejail/disable-passwdmgr.inc
7
8caps.drop all
9netfilter
10nonewprivs
11noroot
12protocol unix,inet,inet6,netlink
13seccomp
diff --git a/etc/franz.profile b/etc/franz.profile
index 3cb7942ab..0b3be551b 100644
--- a/etc/franz.profile
+++ b/etc/franz.profile
@@ -6,12 +6,12 @@ include /etc/firejail/disable-programs.inc
6include /etc/firejail/disable-devel.inc 6include /etc/firejail/disable-devel.inc
7 7
8caps.drop all 8caps.drop all
9seccomp
10protocol unix,inet,inet6,netlink
11netfilter 9netfilter
12#tracelog
13nonewprivs 10nonewprivs
14noroot 11noroot
12protocol unix,inet,inet6,netlink
13seccomp
14#tracelog
15 15
16whitelist ${DOWNLOADS} 16whitelist ${DOWNLOADS}
17mkdir ~/.config/Franz 17mkdir ~/.config/Franz
diff --git a/etc/gajim.profile b/etc/gajim.profile
index 04902a734..809378ef9 100644
--- a/etc/gajim.profile
+++ b/etc/gajim.profile
@@ -22,8 +22,8 @@ include /etc/firejail/disable-devel.inc
22 22
23caps.drop all 23caps.drop all
24netfilter 24netfilter
25nonewprivs
26nogroups 25nogroups
26nonewprivs
27noroot 27noroot
28protocol unix,inet,inet6 28protocol unix,inet,inet6
29seccomp 29seccomp
diff --git a/etc/gimp.profile b/etc/gimp.profile
index 23361b771..cb441fc9d 100644
--- a/etc/gimp.profile
+++ b/etc/gimp.profile
@@ -6,13 +6,15 @@ include /etc/firejail/disable-passwdmgr.inc
6 6
7caps.drop all 7caps.drop all
8netfilter 8netfilter
9nogroups
9nonewprivs 10nonewprivs
10noroot 11noroot
12nosound
11protocol unix 13protocol unix
12seccomp 14seccomp
13private-dev 15
14private-tmp
15noexec ${HOME} 16noexec ${HOME}
16noexec /tmp 17noexec /tmp
17nogroups 18
18nosound 19private-dev
20private-tmp
diff --git a/etc/git.profile b/etc/git.profile
index 2fb55377d..73122d347 100644
--- a/etc/git.profile
+++ b/etc/git.profile
@@ -12,15 +12,15 @@ include /etc/firejail/disable-common.inc
12include /etc/firejail/disable-programs.inc 12include /etc/firejail/disable-programs.inc
13include /etc/firejail/disable-passwdmgr.inc 13include /etc/firejail/disable-passwdmgr.inc
14 14
15quiet
16 15
17caps.drop all 16caps.drop all
18netfilter 17netfilter
18nogroups
19nonewprivs 19nonewprivs
20noroot 20noroot
21nogroups
22nosound 21nosound
23protocol unix,inet,inet6 22protocol unix,inet,inet6
23quiet
24seccomp 24seccomp
25shell none 25shell none
26 26
diff --git a/etc/gpredict.profile b/etc/gpredict.profile
index 353ecceae..801304c18 100644
--- a/etc/gpredict.profile
+++ b/etc/gpredict.profile
@@ -6,13 +6,12 @@ include /etc/firejail/disable-passwdmgr.inc
6include /etc/firejail/disable-programs.inc 6include /etc/firejail/disable-programs.inc
7 7
8# Whitelist 8# Whitelist
9mkdir ~/.config/Gpredict
10whitelist ~/.config/Gpredict 9whitelist ~/.config/Gpredict
11 10
12caps.drop all 11caps.drop all
13netfilter 12netfilter
14nonewprivs
15nogroups 13nogroups
14nonewprivs
16noroot 15noroot
17nosound 16nosound
18protocol unix,inet,inet6 17protocol unix,inet,inet6
@@ -21,5 +20,6 @@ shell none
21tracelog 20tracelog
22 21
23private-bin gpredict 22private-bin gpredict
23private-etc fonts,resolv.conf
24private-dev 24private-dev
25private-tmp 25private-tmp
diff --git a/etc/gwenview.profile b/etc/gwenview.profile
index 67f10c4e1..c866c9e63 100644
--- a/etc/gwenview.profile
+++ b/etc/gwenview.profile
@@ -7,14 +7,15 @@ include /etc/firejail/disable-devel.inc
7include /etc/firejail/disable-passwdmgr.inc 7include /etc/firejail/disable-passwdmgr.inc
8 8
9caps.drop all 9caps.drop all
10nogroups
10nonewprivs 11nonewprivs
11noroot 12noroot
12nogroups
13private-dev
14protocol unix 13protocol unix
15seccomp 14seccomp
16nosound 15nosound
17 16
17private-dev
18
18#Experimental: 19#Experimental:
19#shell none 20#shell none
20#private-bin gwenview 21#private-bin gwenview
diff --git a/etc/gzip.profile b/etc/gzip.profile
index 5e73969c4..d51b9a951 100644
--- a/etc/gzip.profile
+++ b/etc/gzip.profile
@@ -1,12 +1,14 @@
1# gzip profile 1# gzip profile
2quiet
3ignore noroot 2ignore noroot
4include /etc/firejail/default.profile 3include /etc/firejail/default.profile
5tracelog 4
6net none
7shell none
8blacklist /tmp/.X11-unix 5blacklist /tmp/.X11-unix
9private-dev 6
10nosound 7net none
11no3d 8no3d
9nosound
10quiet
11shell none
12tracelog
12 13
14private-dev
diff --git a/etc/inkscape.profile b/etc/inkscape.profile
index cf885fba2..a0e86b6c9 100644
--- a/etc/inkscape.profile
+++ b/etc/inkscape.profile
@@ -6,13 +6,15 @@ include /etc/firejail/disable-passwdmgr.inc
6 6
7caps.drop all 7caps.drop all
8netfilter 8netfilter
9nogroups
9nonewprivs 10nonewprivs
10noroot 11noroot
12nosound
11protocol unix 13protocol unix
12seccomp 14seccomp
13private-dev 15
14private-tmp
15noexec ${HOME} 16noexec ${HOME}
16noexec /tmp 17noexec /tmp
17nogroups 18
18nosound 19private-dev
20private-tmp
diff --git a/etc/jitsi.profile b/etc/jitsi.profile
index c61158f8b..046499abe 100644
--- a/etc/jitsi.profile
+++ b/etc/jitsi.profile
@@ -6,8 +6,8 @@ include /etc/firejail/disable-passwdmgr.inc
6include /etc/firejail/disable-programs.inc 6include /etc/firejail/disable-programs.inc
7 7
8caps.drop all 8caps.drop all
9nonewprivs
10nogroups 9nogroups
10nonewprivs
11noroot 11noroot
12protocol unix,inet,inet6 12protocol unix,inet,inet6
13seccomp 13seccomp
diff --git a/etc/keepass.profile b/etc/keepass.profile
index b2085f53d..23f9a7b40 100644
--- a/etc/keepass.profile
+++ b/etc/keepass.profile
@@ -13,7 +13,7 @@ nogroups
13nonewprivs 13nonewprivs
14noroot 14noroot
15nosound 15nosound
16protocol unix 16protocol unix,inet,inet6
17seccomp 17seccomp
18netfilter 18netfilter
19shell none 19shell none
diff --git a/etc/kmail.profile b/etc/kmail.profile
index 8c8fd18c4..bc21ba604 100644
--- a/etc/kmail.profile
+++ b/etc/kmail.profile
@@ -8,8 +8,8 @@ include /etc/firejail/disable-passwdmgr.inc
8 8
9caps.drop all 9caps.drop all
10netfilter 10netfilter
11nonewprivs
12nogroups 11nogroups
12nonewprivs
13noroot 13noroot
14protocol unix,inet,inet6,netlink 14protocol unix,inet,inet6,netlink
15seccomp 15seccomp
diff --git a/etc/less.profile b/etc/less.profile
index 6dfae027e..08758aead 100644
--- a/etc/less.profile
+++ b/etc/less.profile
@@ -2,8 +2,10 @@
2quiet 2quiet
3ignore noroot 3ignore noroot
4include /etc/firejail/default.profile 4include /etc/firejail/default.profile
5tracelog 5
6net none 6net none
7nosound
7shell none 8shell none
9tracelog
10
8private-dev 11private-dev
9nosound
diff --git a/etc/libreoffice.profile b/etc/libreoffice.profile
index 75a52e9ff..d6aceb7a8 100644
--- a/etc/libreoffice.profile
+++ b/etc/libreoffice.profile
@@ -1,5 +1,6 @@
1# Firejail profile for LibreOffice 1# Firejail profile for LibreOffice
2noblacklist ~/.config/libreoffice 2noblacklist ~/.config/libreoffice
3noblacklist /usr/local/sbin
3include /etc/firejail/disable-common.inc 4include /etc/firejail/disable-common.inc
4include /etc/firejail/disable-programs.inc 5include /etc/firejail/disable-programs.inc
5include /etc/firejail/disable-devel.inc 6include /etc/firejail/disable-devel.inc
@@ -10,9 +11,9 @@ netfilter
10nogroups 11nogroups
11nonewprivs 12nonewprivs
12noroot 13noroot
13protocol unix,inet,inet6,netlink 14protocol unix,inet,inet6
14seccomp 15seccomp
15tracelog 16tracelog
16 17
17private-dev 18private-dev
18whitelist /tmp/.X11-unix/ 19# whitelist /tmp/.X11-unix/
diff --git a/etc/luminance-hdr.profile b/etc/luminance-hdr.profile
index 6e059ea52..76e864e0c 100644
--- a/etc/luminance-hdr.profile
+++ b/etc/luminance-hdr.profile
@@ -5,17 +5,19 @@ include /etc/firejail/disable-programs.inc
5include /etc/firejail/disable-passwdmgr.inc 5include /etc/firejail/disable-passwdmgr.inc
6 6
7caps.drop all 7caps.drop all
8ipc-namespace
8netfilter 9netfilter
9protocol unix 10nogroups
10nonewprivs 11nonewprivs
11noroot 12noroot
13nosound
14protocol unix
12seccomp 15seccomp
13shell none 16shell none
14tracelog 17tracelog
15private-tmp 18
16private-dev
17noexec ${HOME} 19noexec ${HOME}
18noexec /tmp 20noexec /tmp
19nogroups 21
20nosound 22private-tmp
21ipc-namespace 23private-dev
diff --git a/etc/mumble.profile b/etc/mumble.profile
new file mode 100644
index 000000000..ddd70822d
--- /dev/null
+++ b/etc/mumble.profile
@@ -0,0 +1,26 @@
1# mumble profile
2noblacklist ${HOME}/.config/Mumble
3noblacklist ${HOME}/.local/share/data/Mumble
4include /etc/firejail/disable-common.inc
5include /etc/firejail/disable-programs.inc
6include /etc/firejail/disable-devel.inc
7include /etc/firejail/disable-passwdmgr.inc
8
9mkdir ${HOME}/.config/Mumble
10mkdir ${HOME}/.local/share/data/Mumble
11whitelist ${HOME}/.config/Mumble
12whitelist ${HOME}/.local/share/data/Mumble
13include /etc/firejail/whitelist-common.inc
14
15caps.drop all
16netfilter
17nonewprivs
18nogroups
19noroot
20protocol unix,inet,inet6
21seccomp
22shell none
23tracelog
24
25private-bin mumble
26private-tmp
diff --git a/etc/mutt.profile b/etc/mutt.profile
index cda7fc4bf..b532ded67 100644
--- a/etc/mutt.profile
+++ b/etc/mutt.profile
@@ -2,6 +2,7 @@
2 2
3noblacklist ~/.muttrc 3noblacklist ~/.muttrc
4noblacklist ~/.mutt 4noblacklist ~/.mutt
5noblacklist ~/.mutt/muttrc
5noblacklist ~/.mailcap 6noblacklist ~/.mailcap
6noblacklist ~/.gnupg 7noblacklist ~/.gnupg
7noblacklist ~/.mail 8noblacklist ~/.mail
diff --git a/etc/okular.profile b/etc/okular.profile
index df142ccfc..b43a5fbea 100644
--- a/etc/okular.profile
+++ b/etc/okular.profile
@@ -9,14 +9,15 @@ include /etc/firejail/disable-devel.inc
9include /etc/firejail/disable-passwdmgr.inc 9include /etc/firejail/disable-passwdmgr.inc
10 10
11caps.drop all 11caps.drop all
12nonewprivs
13nogroups 12nogroups
13nonewprivs
14noroot 14noroot
15private-dev
16protocol unix 15protocol unix
17seccomp 16seccomp
18nosound 17nosound
19 18
19private-dev
20
20#Experimental: 21#Experimental:
21#net none 22#net none
22#shell none 23#shell none
diff --git a/etc/openshot.profile b/etc/openshot.profile
new file mode 100644
index 000000000..f12bd7d11
--- /dev/null
+++ b/etc/openshot.profile
@@ -0,0 +1,13 @@
1# OpenShot profile
2noblacklist ${HOME}/.openshot
3noblacklist ${HOME}/.openshot_qt
4include /etc/firejail/disable-common.inc
5include /etc/firejail/disable-programs.inc
6include /etc/firejail/disable-passwdmgr.inc
7
8caps.drop all
9netfilter
10nonewprivs
11noroot
12protocol unix,inet,inet6,netlink
13seccomp
diff --git a/etc/pidgin.profile b/etc/pidgin.profile
index 47be2b6ea..850706145 100644
--- a/etc/pidgin.profile
+++ b/etc/pidgin.profile
@@ -8,8 +8,8 @@ include /etc/firejail/disable-programs.inc
8 8
9caps.drop all 9caps.drop all
10netfilter 10netfilter
11nonewprivs
12nogroups 11nogroups
12nonewprivs
13noroot 13noroot
14protocol unix,inet,inet6 14protocol unix,inet,inet6
15seccomp 15seccomp
diff --git a/etc/pix.profile b/etc/pix.profile
index 80c05fd09..e21ddadc6 100644
--- a/etc/pix.profile
+++ b/etc/pix.profile
@@ -8,8 +8,8 @@ include /etc/firejail/disable-devel.inc
8include /etc/firejail/disable-passwdmgr.inc 8include /etc/firejail/disable-passwdmgr.inc
9 9
10caps.drop all 10caps.drop all
11nonewprivs
12nogroups 11nogroups
12nonewprivs
13noroot 13noroot
14nosound 14nosound
15protocol unix 15protocol unix
@@ -20,4 +20,3 @@ tracelog
20private-bin pix 20private-bin pix
21whitelist /tmp/.X11-unix 21whitelist /tmp/.X11-unix
22private-dev 22private-dev
23
diff --git a/etc/psi-plus.profile b/etc/psi-plus.profile
index 22c5bafc5..a9323448b 100644
--- a/etc/psi-plus.profile
+++ b/etc/psi-plus.profile
@@ -14,10 +14,10 @@ whitelist ~/.local/share/psi+
14mkdir ~/.cache/psi+ 14mkdir ~/.cache/psi+
15whitelist ~/.cache/psi+ 15whitelist ~/.cache/psi+
16 16
17include /etc/firejail/whitelist-common.inc
18
19caps.drop all 17caps.drop all
20netfilter 18netfilter
21noroot 19noroot
22protocol unix,inet,inet6 20protocol unix,inet,inet6
23seccomp 21seccomp
22
23include /etc/firejail/whitelist-common.inc
diff --git a/etc/qbittorrent.profile b/etc/qbittorrent.profile
index 138b6db55..67829c9ca 100644
--- a/etc/qbittorrent.profile
+++ b/etc/qbittorrent.profile
@@ -15,6 +15,6 @@ seccomp
15# there are some problems with "Open destination folder", see bug #536 15# there are some problems with "Open destination folder", see bug #536
16#shell none 16#shell none
17#private-bin qbittorrent 17#private-bin qbittorrent
18whitelist /tmp/.X11-unix
19private-dev 18private-dev
20nosound 19
20whitelist /tmp/.X11-unix
diff --git a/etc/qpdfview.profile b/etc/qpdfview.profile
index 07ea173e6..06c0db206 100644
--- a/etc/qpdfview.profile
+++ b/etc/qpdfview.profile
@@ -18,5 +18,5 @@ shell none
18tracelog 18tracelog
19 19
20private-bin qpdfview 20private-bin qpdfview
21private-tmp
22private-dev 21private-dev
22private-tmp
diff --git a/etc/qtox.profile b/etc/qtox.profile
index 927487037..81d8aa10e 100644
--- a/etc/qtox.profile
+++ b/etc/qtox.profile
@@ -11,8 +11,8 @@ whitelist ${DOWNLOADS}
11 11
12caps.drop all 12caps.drop all
13netfilter 13netfilter
14nonewprivs
15nogroups 14nogroups
15nonewprivs
16noroot 16noroot
17protocol unix,inet,inet6 17protocol unix,inet,inet6
18seccomp 18seccomp
diff --git a/etc/quiterss.profile b/etc/quiterss.profile
index 2ab5d8a8e..2b28fce73 100644
--- a/etc/quiterss.profile
+++ b/etc/quiterss.profile
@@ -14,16 +14,17 @@ whitelist ${HOME}/.cache/QuiteRss
14 14
15caps.drop all 15caps.drop all
16netfilter 16netfilter
17nonewprivs
18nogroups 17nogroups
18nonewprivs
19noroot 19noroot
20private-bin quiterss
21private-dev
22nosound 20nosound
23#private-etc X11,ssl
24protocol unix,inet,inet6 21protocol unix,inet,inet6
25seccomp 22seccomp
26shell none 23shell none
27tracelog 24tracelog
28 25
26private-bin quiterss
27private-dev
28#private-etc X11,ssl
29
29include /etc/firejail/whitelist-common.inc 30include /etc/firejail/whitelist-common.inc
diff --git a/etc/ranger.profile b/etc/ranger.profile
index a040cd6bc..323e64dee 100644
--- a/etc/ranger.profile
+++ b/etc/ranger.profile
@@ -12,13 +12,12 @@ include /etc/firejail/disable-passwdmgr.inc
12caps.drop all 12caps.drop all
13netfilter 13netfilter
14net none 14net none
15nogroups
15nonewprivs 16nonewprivs
16noroot 17noroot
17nogroups
18protocol unix 18protocol unix
19seccomp 19seccomp
20nosound 20nosound
21 21
22private-tmp 22private-tmp
23private-dev 23private-dev
24
diff --git a/etc/rhythmbox.profile b/etc/rhythmbox.profile
index 0e8527ae7..e5e192486 100644
--- a/etc/rhythmbox.profile
+++ b/etc/rhythmbox.profile
@@ -5,8 +5,8 @@ include /etc/firejail/disable-devel.inc
5include /etc/firejail/disable-passwdmgr.inc 5include /etc/firejail/disable-passwdmgr.inc
6 6
7caps.drop all 7caps.drop all
8nogroups
9netfilter 8netfilter
9nogroups
10nonewprivs 10nonewprivs
11noroot 11noroot
12protocol unix,inet,inet6 12protocol unix,inet,inet6
diff --git a/etc/rtorrent.profile b/etc/rtorrent.profile
index 15df2c374..1226a51cd 100644
--- a/etc/rtorrent.profile
+++ b/etc/rtorrent.profile
@@ -16,4 +16,3 @@ shell none
16private-bin rtorrent 16private-bin rtorrent
17whitelist /tmp/.X11-unix 17whitelist /tmp/.X11-unix
18private-dev 18private-dev
19nosound
diff --git a/etc/server.profile b/etc/server.profile
index 22cef0a3c..b8a34feb2 100644
--- a/etc/server.profile
+++ b/etc/server.profile
@@ -6,11 +6,12 @@ include /etc/firejail/disable-common.inc
6include /etc/firejail/disable-programs.inc 6include /etc/firejail/disable-programs.inc
7include /etc/firejail/disable-passwdmgr.inc 7include /etc/firejail/disable-passwdmgr.inc
8 8
9private
10private-dev
11nosound
12no3d
13private-tmp
14blacklist /tmp/.X11-unix 9blacklist /tmp/.X11-unix
10
11no3d
12nosound
15seccomp 13seccomp
16 14
15private
16private-dev
17private-tmp
diff --git a/etc/slack.profile b/etc/slack.profile
index 1009f7ee0..a85a28f03 100644
--- a/etc/slack.profile
+++ b/etc/slack.profile
@@ -1,3 +1,4 @@
1# Firejail profile for Slack
1noblacklist ${HOME}/.config/Slack 2noblacklist ${HOME}/.config/Slack
2noblacklist ${HOME}/Downloads 3noblacklist ${HOME}/Downloads
3 4
@@ -6,25 +7,25 @@ include /etc/firejail/disable-programs.inc
6include /etc/firejail/disable-devel.inc 7include /etc/firejail/disable-devel.inc
7include /etc/firejail/disable-passwdmgr.inc 8include /etc/firejail/disable-passwdmgr.inc
8 9
9mkdir ${HOME}/.config
10mkdir ${HOME}/.config/Slack
11whitelist ${HOME}/.config/Slack
12whitelist ${HOME}/Downloads
13
14protocol unix,inet,inet6,netlink
15private-dev
16private-tmp
17private-etc fonts,resolv.conf,ld.so.conf,ld.so.cache,localtime
18name slack
19blacklist /var 10blacklist /var
20 11
21include /etc/firejail/whitelist-common.inc
22
23caps.drop all 12caps.drop all
24seccomp 13name slack
25netfilter 14netfilter
26nonewprivs
27nogroups 15nogroups
16nonewprivs
28noroot 17noroot
18protocol unix,inet,inet6,netlink
19seccomp
29shell none 20shell none
21
30private-bin slack 22private-bin slack
23private-dev
24private-etc fonts,resolv.conf,ld.so.conf,ld.so.cache,localtime
25private-tmp
26
27mkdir ${HOME}/.config
28mkdir ${HOME}/.config/Slack
29whitelist ${HOME}/.config/Slack
30whitelist ${HOME}/Downloads
31include /etc/firejail/whitelist-common.inc
diff --git a/etc/spotify.profile b/etc/spotify.profile
index 73d427db3..6dbcc03ee 100644
--- a/etc/spotify.profile
+++ b/etc/spotify.profile
@@ -7,16 +7,13 @@ include /etc/firejail/disable-programs.inc
7include /etc/firejail/disable-devel.inc 7include /etc/firejail/disable-devel.inc
8include /etc/firejail/disable-passwdmgr.inc 8include /etc/firejail/disable-passwdmgr.inc
9 9
10# Whitelist the folders needed by Spotify - This is more restrictive 10# Whitelist the folders needed by Spotify
11# than a blacklist though, but this is all spotify requires for
12# streaming audio
13mkdir ${HOME}/.config/spotify 11mkdir ${HOME}/.config/spotify
14whitelist ${HOME}/.config/spotify 12whitelist ${HOME}/.config/spotify
15mkdir ${HOME}/.local/share/spotify 13mkdir ${HOME}/.local/share/spotify
16whitelist ${HOME}/.local/share/spotify 14whitelist ${HOME}/.local/share/spotify
17mkdir ${HOME}/.cache/spotify 15mkdir ${HOME}/.cache/spotify
18whitelist ${HOME}/.cache/spotify 16whitelist ${HOME}/.cache/spotify
19include /etc/firejail/whitelist-common.inc
20 17
21caps.drop all 18caps.drop all
22netfilter 19netfilter
@@ -27,5 +24,20 @@ protocol unix,inet,inet6,netlink
27seccomp 24seccomp
28shell none 25shell none
29 26
30#private-bin spotify 27private-bin spotify
28private-etc fonts,machine-id,pulse,resolv.conf
31private-dev 29private-dev
30private-tmp
31
32blacklist ${HOME}/.Xauthority
33blacklist ${HOME}/.bashrc
34blacklist /boot
35blacklist /lost+found
36blacklist /media
37blacklist /mnt
38blacklist /opt
39blacklist /root
40blacklist /sbin
41blacklist /srv
42blacklist /sys
43blacklist /var
diff --git a/etc/start-tor-browser.profile b/etc/start-tor-browser.profile
new file mode 100644
index 000000000..ee19cee25
--- /dev/null
+++ b/etc/start-tor-browser.profile
@@ -0,0 +1,20 @@
1# Firejail profile for the Tor Brower Bundle
2include /etc/firejail/disable-common.inc
3include /etc/firejail/disable-devel.inc
4include /etc/firejail/disable-passwdmgr.inc
5include /etc/firejail/disable-programs.inc
6
7caps.drop all
8netfilter
9nogroups
10nonewprivs
11noroot
12protocol unix,inet,inet6
13seccomp
14shell none
15tracelog
16
17private-bin bash,grep,sed,tail,env,gpg,id,readlink,dirname,test,mkdir,ln,sed,cp,rm,getconf
18private-etc fonts
19private-dev
20private-tmp
diff --git a/etc/strings.profile b/etc/strings.profile
index f99a65009..7c464bf88 100644
--- a/etc/strings.profile
+++ b/etc/strings.profile
@@ -1,10 +1,11 @@
1# strings profile 1# strings profile
2quiet
3ignore noroot 2ignore noroot
4include /etc/firejail/default.profile 3include /etc/firejail/default.profile
5tracelog 4
6net none 5net none
7shell none
8private-dev
9nosound 6nosound
7quiet
8shell none
9tracelog
10 10
11private-dev
diff --git a/etc/synfigstudio.profile b/etc/synfigstudio.profile
index d46467b99..69b2a0db2 100644
--- a/etc/synfigstudio.profile
+++ b/etc/synfigstudio.profile
@@ -11,7 +11,9 @@ nonewprivs
11noroot 11noroot
12protocol unix 12protocol unix
13seccomp 13seccomp
14private-dev 14
15private-tmp
16noexec ${HOME} 15noexec ${HOME}
17noexec /tmp 16noexec /tmp
17
18private-dev
19private-tmp
diff --git a/etc/tar.profile b/etc/tar.profile
index 663ac3805..91fdaf48d 100644
--- a/etc/tar.profile
+++ b/etc/tar.profile
@@ -1,18 +1,18 @@
1# tar profile 1# tar profile
2quiet
3ignore noroot 2ignore noroot
4include /etc/firejail/default.profile 3include /etc/firejail/default.profile
5 4
6tracelog 5blacklist /tmp/.X11-unix
6
7hostname tar
7net none 8net none
9no3d
10nosound
11quiet
8shell none 12shell none
13tracelog
9 14
10# support compressed archives 15# support compressed archives
11private-bin sh,tar,gtar,compress,gzip,lzma,xz,bzip2,lbzip2,lzip,lzop 16private-bin sh,tar,gtar,compress,gzip,lzma,xz,bzip2,lbzip2,lzip,lzop
12private-dev 17private-dev
13nosound
14no3d
15private-etc passwd,group,localtime 18private-etc passwd,group,localtime
16hostname tar
17blacklist /tmp/.X11-unix
18
diff --git a/etc/telegram.profile b/etc/telegram.profile
index 8e91e426b..7615c8eef 100644
--- a/etc/telegram.profile
+++ b/etc/telegram.profile
@@ -10,4 +10,3 @@ nonewprivs
10noroot 10noroot
11protocol unix,inet,inet6 11protocol unix,inet,inet6
12seccomp 12seccomp
13
diff --git a/etc/transmission-gtk.profile b/etc/transmission-gtk.profile
index 0cfa4fcfc..316cdfec6 100644
--- a/etc/transmission-gtk.profile
+++ b/etc/transmission-gtk.profile
@@ -18,6 +18,6 @@ shell none
18tracelog 18tracelog
19 19
20private-bin transmission-gtk 20private-bin transmission-gtk
21whitelist /tmp/.X11-unix
22private-dev 21private-dev
23 22
23whitelist /tmp/.X11-unix
diff --git a/etc/transmission-qt.profile b/etc/transmission-qt.profile
index 754211a63..51c58e224 100644
--- a/etc/transmission-qt.profile
+++ b/etc/transmission-qt.profile
@@ -14,9 +14,10 @@ noroot
14nosound 14nosound
15protocol unix,inet,inet6 15protocol unix,inet,inet6
16seccomp 16seccomp
17shell none
17tracelog 18tracelog
18 19
19shell none
20private-bin transmission-qt 20private-bin transmission-qt
21whitelist /tmp/.X11-unix
22private-dev 21private-dev
22
23whitelist /tmp/.X11-unix
diff --git a/etc/uget-gtk.profile b/etc/uget-gtk.profile
index 522b4bd1e..f42e6c69a 100644
--- a/etc/uget-gtk.profile
+++ b/etc/uget-gtk.profile
@@ -9,17 +9,16 @@ caps.drop all
9netfilter 9netfilter
10nonewprivs 10nonewprivs
11noroot 11noroot
12nosound
12protocol unix,inet,inet6 13protocol unix,inet,inet6
13seccomp 14seccomp
15shell none
14 16
17private-bin uget-gtk
18private-dev
19
20whitelist /tmp/.X11-unix
15whitelist ${DOWNLOADS} 21whitelist ${DOWNLOADS}
16mkdir ~/.config/uGet 22mkdir ~/.config/uGet
17whitelist ~/.config/uGet 23whitelist ~/.config/uGet
18include /etc/firejail/whitelist-common.inc 24include /etc/firejail/whitelist-common.inc
19
20shell none
21private-bin uget-gtk
22whitelist /tmp/.X11-unix
23private-dev
24nosound
25
diff --git a/etc/unrar.profile b/etc/unrar.profile
index f29d1b51b..0700cafe9 100644
--- a/etc/unrar.profile
+++ b/etc/unrar.profile
@@ -1,17 +1,18 @@
1# unrar profile 1# unrar profile
2quiet
3ignore noroot 2ignore noroot
4include /etc/firejail/default.profile 3include /etc/firejail/default.profile
5 4
6tracelog 5blacklist /tmp/.X11-unix
6
7hostname unrar
7net none 8net none
9no3d
10nosound
11quiet
8shell none 12shell none
13tracelog
14
9private-bin unrar 15private-bin unrar
10private-dev 16private-dev
11nosound
12no3d
13private-etc passwd,group,localtime 17private-etc passwd,group,localtime
14hostname unrar
15private-tmp 18private-tmp
16blacklist /tmp/.X11-unix
17
diff --git a/etc/unzip.profile b/etc/unzip.profile
index 07224855f..a43785795 100644
--- a/etc/unzip.profile
+++ b/etc/unzip.profile
@@ -1,16 +1,16 @@
1# unzip profile 1# unzip profile
2quiet
3ignore noroot 2ignore noroot
4include /etc/firejail/default.profile 3include /etc/firejail/default.profile
4blacklist /tmp/.X11-unix
5 5
6tracelog 6hostname unzip
7net none 7net none
8no3d
9nosound
10quiet
8shell none 11shell none
12tracelog
13
9private-bin unzip 14private-bin unzip
10private-etc passwd,group,localtime
11hostname unzip
12private-dev 15private-dev
13nosound 16private-etc passwd,group,localtime
14no3d
15blacklist /tmp/.X11-unix
16
diff --git a/etc/uudeview.profile b/etc/uudeview.profile
index 8ea9d5163..5ba0896ab 100644
--- a/etc/uudeview.profile
+++ b/etc/uudeview.profile
@@ -1,15 +1,15 @@
1# uudeview profile 1# uudeview profile
2quiet
3ignore noroot 2ignore noroot
4include /etc/firejail/default.profile 3include /etc/firejail/default.profile
5 4
6tracelog 5blacklist /etc
6
7hostname uudeview
7net none 8net none
9nosound
10quiet
8shell none 11shell none
12tracelog
13
9private-bin uudeview 14private-bin uudeview
10private-dev 15private-dev
11private-etc nonexisting_fakefile_for_empty_etc
12hostname uudeview
13nosound
14uudeview
15
diff --git a/etc/vim.profile b/etc/vim.profile
index 3c1fefe41..b161fcbb0 100644
--- a/etc/vim.profile
+++ b/etc/vim.profile
@@ -1,5 +1,4 @@
1# vim profile 1# vim profile
2
3noblacklist ~/.vim 2noblacklist ~/.vim
4noblacklist ~/.vimrc 3noblacklist ~/.vimrc
5noblacklist ~/.viminfo 4noblacklist ~/.viminfo
@@ -10,8 +9,8 @@ include /etc/firejail/disable-passwdmgr.inc
10 9
11caps.drop all 10caps.drop all
12netfilter 11netfilter
12nogroups
13nonewprivs 13nonewprivs
14noroot 14noroot
15nogroups
16protocol unix,inet,inet6 15protocol unix,inet,inet6
17seccomp 16seccomp
diff --git a/etc/virtualbox.profile b/etc/virtualbox.profile
new file mode 100644
index 000000000..148b7efc8
--- /dev/null
+++ b/etc/virtualbox.profile
@@ -0,0 +1,12 @@
1# VirtualBox profile
2
3noblacklist ${HOME}/.VirtualBox
4noblacklist ${HOME}/VirtualBox VMs
5noblacklist ${HOME}/.config/VirtualBox
6include /etc/firejail/disable-common.inc
7include /etc/firejail/disable-programs.inc
8include /etc/firejail/disable-passwdmgr.inc
9
10caps.drop all
11
12
diff --git a/etc/vlc.profile b/etc/vlc.profile
index cdd098dd5..446e47864 100644
--- a/etc/vlc.profile
+++ b/etc/vlc.profile
@@ -14,7 +14,6 @@ noroot
14protocol unix,inet,inet6 14protocol unix,inet,inet6
15seccomp 15seccomp
16shell none 16shell none
17tracelog
18 17
19private-bin vlc,cvlc,nvlc,rvlc,qvlc,svlc 18private-bin vlc,cvlc,nvlc,rvlc,qvlc,svlc
20private-dev 19private-dev
diff --git a/etc/whitelist-common.inc b/etc/whitelist-common.inc
index fd44c2528..e533fe596 100644
--- a/etc/whitelist-common.inc
+++ b/etc/whitelist-common.inc
@@ -14,6 +14,7 @@ whitelist ~/.fonts.d
14whitelist ~/.fontconfig 14whitelist ~/.fontconfig
15whitelist ~/.fonts.conf 15whitelist ~/.fonts.conf
16whitelist ~/.fonts.conf.d 16whitelist ~/.fonts.conf.d
17whitelist ~/.local/share/fonts
17whitelist ~/.config/fontconfig 18whitelist ~/.config/fontconfig
18whitelist ~/.cache/fontconfig 19whitelist ~/.cache/fontconfig
19 20
diff --git a/etc/xiphos.profile b/etc/xiphos.profile
new file mode 100644
index 000000000..b7fb6ecf3
--- /dev/null
+++ b/etc/xiphos.profile
@@ -0,0 +1,30 @@
1# Firejail profile for xiphos
2noblacklist ~/.sword
3noblacklist ~/.xiphos
4
5include /etc/firejail/disable-common.inc
6include /etc/firejail/disable-devel.inc
7include /etc/firejail/disable-passwdmgr.inc
8include /etc/firejail/disable-programs.inc
9
10blacklist ~/.bashrc
11blacklist ~/.Xauthority
12
13caps.drop all
14netfilter
15nogroups
16nonewprivs
17noroot
18nosound
19protocol unix,inet,inet6
20seccomp
21shell none
22tracelog
23
24private-bin xiphos
25private-etc fonts,resolv.conf,sword
26private-dev
27private-tmp
28
29whitelist ${HOME}/.sword
30whitelist ${HOME}/.xiphos
diff --git a/etc/xpdf.profile b/etc/xpdf.profile
new file mode 100644
index 000000000..7ea368bbe
--- /dev/null
+++ b/etc/xpdf.profile
@@ -0,0 +1,18 @@
1################################
2# xpdf application profile
3################################
4noblacklist ${HOME}/.xpdfrc
5include /etc/firejail/disable-common.inc
6include /etc/firejail/disable-programs.inc
7include /etc/firejail/disable-passwdmgr.inc
8
9caps.drop all
10net none
11nonewprivs
12noroot
13protocol unix
14shell none
15seccomp
16
17private-dev
18private-tmp
diff --git a/etc/xplayer.profile b/etc/xplayer.profile
index 54d5ed89b..191d2f67f 100644
--- a/etc/xplayer.profile
+++ b/etc/xplayer.profile
@@ -9,8 +9,8 @@ include /etc/firejail/disable-passwdmgr.inc
9 9
10caps.drop all 10caps.drop all
11netfilter 11netfilter
12nonewprivs
13nogroups 12nogroups
13nonewprivs
14noroot 14noroot
15protocol unix,inet,inet6 15protocol unix,inet,inet6
16seccomp 16seccomp
diff --git a/etc/xzdec.profile b/etc/xzdec.profile
index a9d027c38..04f98cef6 100644
--- a/etc/xzdec.profile
+++ b/etc/xzdec.profile
@@ -1,12 +1,14 @@
1# xzdec profile 1# xzdec profile
2quiet
3ignore noroot 2ignore noroot
4include /etc/firejail/default.profile 3include /etc/firejail/default.profile
5tracelog 4
6net none
7shell none
8blacklist /tmp/.X11-unix 5blacklist /tmp/.X11-unix
9private-dev 6
10nosound 7net none
11no3d 8no3d
9nosound
10quiet
11shell none
12tracelog
12 13
14private-dev
diff --git a/etc/zathura.profile b/etc/zathura.profile
index d29762889..99a8ea90d 100644
--- a/etc/zathura.profile
+++ b/etc/zathura.profile
@@ -7,14 +7,14 @@ include /etc/firejail/disable-devel.inc
7include /etc/firejail/disable-passwdmgr.inc 7include /etc/firejail/disable-passwdmgr.inc
8 8
9caps.drop all 9caps.drop all
10seccomp
11protocol unix
12netfilter 10netfilter
11nogroups
13nonewprivs 12nonewprivs
14noroot 13noroot
15nogroups
16nosound 14nosound
17shell none 15shell none
16seccomp
17protocol unix
18 18
19private-bin zathura 19private-bin zathura
20private-dev 20private-dev
diff --git a/mkuid.sh b/mkuid.sh
index c95741043..a59f58143 100755
--- a/mkuid.sh
+++ b/mkuid.sh
@@ -1,4 +1,4 @@
1#!/bin/bash 1#!/bin/sh
2 2
3echo "extracting UID_MIN and GID_MIN" 3echo "extracting UID_MIN and GID_MIN"
4echo "#ifndef FIREJAIL_UIDS_H" > uids.h 4echo "#ifndef FIREJAIL_UIDS_H" > uids.h
diff --git a/platform/debian/conffiles b/platform/debian/conffiles
index 03fb2fe75..df660ab4f 100644
--- a/platform/debian/conffiles
+++ b/platform/debian/conffiles
@@ -155,3 +155,19 @@
155/etc/firejail/7z.profile 155/etc/firejail/7z.profile
156/etc/firejail/keepass.profile 156/etc/firejail/keepass.profile
157/etc/firejail/keepassx.profile 157/etc/firejail/keepassx.profile
158/etc/firejail/claws-mail.profile
159/etc/firejail/mutt.profile
160/etc/firejail/git.profile
161/etc/firejail/emacs.profile
162/etc/firejail/vim.profile
163/etc/firejail/xpdf.profile
164/etc/firejail/virtualbox.profile
165/etc/firejail/openshot.profile
166/etc/firejail/flowblade.profile
167/etc/firejail/eog.profile
168/etc/firejail/evolution.profile
169/etc/firejail/start-tor-browser.profile
170/etc/firejail/xiphos.profile
171/etc/firejail/display.profile
172/etc/firejail/Wire.profile
173/etc/firejail/mumble.profile
diff --git a/platform/rpm/old-mkrpm.sh b/platform/rpm/old-mkrpm.sh
new file mode 100755
index 000000000..017d5e1c3
--- /dev/null
+++ b/platform/rpm/old-mkrpm.sh
@@ -0,0 +1,542 @@
1#!/bin/bash
2VERSION="0.9.44"
3rm -fr ~/rpmbuild
4rm -f firejail-$VERSION-1.x86_64.rpm
5
6mkdir -p ~/rpmbuild/{RPMS,SRPMS,BUILD,SOURCES,SPECS,tmp}
7cat <<EOF >~/.rpmmacros
8%_topdir %(echo $HOME)/rpmbuild
9%_tmppath %{_topdir}/tmp
10EOF
11
12cd ~/rpmbuild
13echo "building directory tree"
14
15mkdir -p firejail-$VERSION/usr/bin
16install -m 755 /usr/bin/firejail firejail-$VERSION/usr/bin/.
17install -m 755 /usr/bin/firemon firejail-$VERSION/usr/bin/.
18install -m 755 /usr/bin/firecfg firejail-$VERSION/usr/bin/.
19
20mkdir -p firejail-$VERSION/usr/lib/firejail
21install -m 755 /usr/lib/firejail/faudit firejail-$VERSION/usr/lib/firejail/.
22install -m 644 /usr/lib/firejail/firecfg.config firejail-$VERSION/usr/lib/firejail/.
23install -m 755 /usr/lib/firejail/fshaper.sh firejail-$VERSION/usr/lib/firejail/.
24install -m 755 /usr/lib/firejail/ftee firejail-$VERSION/usr/lib/firejail/.
25install -m 644 /usr/lib/firejail/libtrace.so firejail-$VERSION/usr/lib/firejail/.
26install -m 644 /usr/lib/firejail/libtracelog.so firejail-$VERSION/usr/lib/firejail/.
27install -m 644 /usr/lib/firejail/libconnect.so firejail-$VERSION/usr/lib/firejail/.
28
29mkdir -p firejail-$VERSION/usr/share/man/man1
30install -m 644 /usr/share/man/man1/firejail.1.gz firejail-$VERSION/usr/share/man/man1/.
31install -m 644 /usr/share/man/man1/firemon.1.gz firejail-$VERSION/usr/share/man/man1/.
32install -m 644 /usr/share/man/man1/firecfg.1.gz firejail-$VERSION/usr/share/man/man1/.
33
34mkdir -p firejail-$VERSION/usr/share/man/man5
35install -m 644 /usr/share/man/man5/firejail-profile.5.gz firejail-$VERSION/usr/share/man/man5/.
36install -m 644 /usr/share/man/man5/firejail-login.5.gz firejail-$VERSION/usr/share/man/man5/.
37
38mkdir -p firejail-$VERSION/usr/share/doc/packages/firejail
39install -m 644 /usr/share/doc/firejail/COPYING firejail-$VERSION/usr/share/doc/packages/firejail/.
40install -m 644 /usr/share/doc/firejail/README firejail-$VERSION/usr/share/doc/packages/firejail/.
41install -m 644 /usr/share/doc/firejail/RELNOTES firejail-$VERSION/usr/share/doc/packages/firejail/.
42
43mkdir -p firejail-$VERSION/etc/firejail
44install -m 644 /etc/firejail/0ad.profile firejail-$VERSION/etc/firejail/.
45install -m 644 /etc/firejail/abrowser.profile firejail-$VERSION/etc/firejail/.
46install -m 644 /etc/firejail/atom-beta.profile firejail-$VERSION/etc/firejail/.
47install -m 644 /etc/firejail/atom.profile firejail-$VERSION/etc/firejail/.
48install -m 644 /etc/firejail/atril.profile firejail-$VERSION/etc/firejail/.
49install -m 644 /etc/firejail/audacious.profile firejail-$VERSION/etc/firejail/.
50install -m 644 /etc/firejail/audacity.profile firejail-$VERSION/etc/firejail/.
51install -m 644 /etc/firejail/aweather.profile firejail-$VERSION/etc/firejail/.
52install -m 644 /etc/firejail/bitlbee.profile firejail-$VERSION/etc/firejail/.
53install -m 644 /etc/firejail/brave.profile firejail-$VERSION/etc/firejail/.
54install -m 644 /etc/firejail/cherrytree.profile firejail-$VERSION/etc/firejail/.
55install -m 644 /etc/firejail/chromium-browser.profile firejail-$VERSION/etc/firejail/.
56install -m 644 /etc/firejail/chromium.profile firejail-$VERSION/etc/firejail/.
57install -m 644 /etc/firejail/clementine.profile firejail-$VERSION/etc/firejail/.
58install -m 644 /etc/firejail/cmus.profile firejail-$VERSION/etc/firejail/.
59install -m 644 /etc/firejail/conkeror.profile firejail-$VERSION/etc/firejail/.
60install -m 644 /etc/firejail/corebird.profile firejail-$VERSION/etc/firejail/.
61install -m 644 /etc/firejail/cpio.profile firejail-$VERSION/etc/firejail/.
62install -m 644 /etc/firejail/cyberfox.profile firejail-$VERSION/etc/firejail/.
63install -m 644 /etc/firejail/Cyberfox.profile firejail-$VERSION/etc/firejail/.
64install -m 644 /etc/firejail/deadbeef.profile firejail-$VERSION/etc/firejail/.
65install -m 644 /etc/firejail/default.profile firejail-$VERSION/etc/firejail/.
66install -m 644 /etc/firejail/deluge.profile firejail-$VERSION/etc/firejail/.
67install -m 644 /etc/firejail/dillo.profile firejail-$VERSION/etc/firejail/.
68install -m 644 /etc/firejail/disable-common.inc firejail-$VERSION/etc/firejail/.
69install -m 644 /etc/firejail/disable-devel.inc firejail-$VERSION/etc/firejail/.
70install -m 644 /etc/firejail/disable-passwdmgr.inc firejail-$VERSION/etc/firejail/.
71install -m 644 /etc/firejail/disable-programs.inc firejail-$VERSION/etc/firejail/.
72install -m 644 /etc/firejail/dnscrypt-proxy.profile firejail-$VERSION/etc/firejail/.
73install -m 644 /etc/firejail/dnsmasq.profile firejail-$VERSION/etc/firejail/.
74install -m 644 /etc/firejail/dosbox.profile firejail-$VERSION/etc/firejail/.
75install -m 644 /etc/firejail/dropbox.profile firejail-$VERSION/etc/firejail/.
76install -m 644 /etc/firejail/empathy.profile firejail-$VERSION/etc/firejail/.
77install -m 644 /etc/firejail/eom.profile firejail-$VERSION/etc/firejail/.
78install -m 644 /etc/firejail/epiphany.profile firejail-$VERSION/etc/firejail/.
79install -m 644 /etc/firejail/evince.profile firejail-$VERSION/etc/firejail/.
80install -m 644 /etc/firejail/fbreader.profile firejail-$VERSION/etc/firejail/.
81install -m 644 /etc/firejail/file.profile firejail-$VERSION/etc/firejail/.
82install -m 644 /etc/firejail/filezilla.profile firejail-$VERSION/etc/firejail/.
83install -m 644 /etc/firejail/firefox-esr.profile firejail-$VERSION/etc/firejail/.
84install -m 644 /etc/firejail/firefox.profile firejail-$VERSION/etc/firejail/.
85install -m 644 /etc/firejail/firejail.config firejail-$VERSION/etc/firejail/.
86install -m 644 /etc/firejail/flashpeak-slimjet.profile firejail-$VERSION/etc/firejail/.
87install -m 644 /etc/firejail/franz.profile firejail-$VERSION/etc/firejail/.
88install -m 644 /etc/firejail/gajim.profile firejail-$VERSION/etc/firejail/.
89install -m 644 /etc/firejail/gitter.profile firejail-$VERSION/etc/firejail/.
90install -m 644 /etc/firejail/gnome-chess.profile firejail-$VERSION/etc/firejail/.
91install -m 644 /etc/firejail/gnome-mplayer.profile firejail-$VERSION/etc/firejail/.
92install -m 644 /etc/firejail/google-chrome-beta.profile firejail-$VERSION/etc/firejail/.
93install -m 644 /etc/firejail/google-chrome.profile firejail-$VERSION/etc/firejail/.
94install -m 644 /etc/firejail/google-chrome-stable.profile firejail-$VERSION/etc/firejail/.
95install -m 644 /etc/firejail/google-chrome-unstable.profile firejail-$VERSION/etc/firejail/.
96install -m 644 /etc/firejail/google-play-music-desktop-player.profile firejail-$VERSION/etc/firejail/.
97install -m 644 /etc/firejail/gpredict.profile firejail-$VERSION/etc/firejail/.
98install -m 644 /etc/firejail/gtar.profile firejail-$VERSION/etc/firejail/.
99install -m 644 /etc/firejail/gthumb.profile firejail-$VERSION/etc/firejail/.
100install -m 644 /etc/firejail/gwenview.profile firejail-$VERSION/etc/firejail/.
101install -m 644 /etc/firejail/gzip.profile firejail-$VERSION/etc/firejail/.
102install -m 644 /etc/firejail/hedgewars.profile firejail-$VERSION/etc/firejail/.
103install -m 644 /etc/firejail/hexchat.profile firejail-$VERSION/etc/firejail/.
104install -m 644 /etc/firejail/icecat.profile firejail-$VERSION/etc/firejail/.
105install -m 644 /etc/firejail/icedove.profile firejail-$VERSION/etc/firejail/.
106install -m 644 /etc/firejail/iceweasel.profile firejail-$VERSION/etc/firejail/.
107install -m 644 /etc/firejail/inox.profile firejail-$VERSION/etc/firejail/.
108install -m 644 /etc/firejail/jitsi.profile firejail-$VERSION/etc/firejail/.
109install -m 644 /etc/firejail/kmail.profile firejail-$VERSION/etc/firejail/.
110install -m 644 /etc/firejail/konversation.profile firejail-$VERSION/etc/firejail/.
111install -m 644 /etc/firejail/less.profile firejail-$VERSION/etc/firejail/.
112install -m 644 /etc/firejail/libreoffice.profile firejail-$VERSION/etc/firejail/.
113install -m 644 /etc/firejail/localc.profile firejail-$VERSION/etc/firejail/.
114install -m 644 /etc/firejail/lodraw.profile firejail-$VERSION/etc/firejail/.
115install -m 644 /etc/firejail/loffice.profile firejail-$VERSION/etc/firejail/.
116install -m 644 /etc/firejail/lofromtemplate.profile firejail-$VERSION/etc/firejail/.
117install -m 644 /etc/firejail/login.users firejail-$VERSION/etc/firejail/.
118install -m 644 /etc/firejail/loimpress.profile firejail-$VERSION/etc/firejail/.
119install -m 644 /etc/firejail/lomath.profile firejail-$VERSION/etc/firejail/.
120install -m 644 /etc/firejail/loweb.profile firejail-$VERSION/etc/firejail/.
121install -m 644 /etc/firejail/lowriter.profile firejail-$VERSION/etc/firejail/.
122install -m 644 /etc/firejail/lxterminal.profile firejail-$VERSION/etc/firejail/.
123install -m 644 /etc/firejail/mathematica.profile firejail-$VERSION/etc/firejail/.
124install -m 644 /etc/firejail/Mathematica.profile firejail-$VERSION/etc/firejail/.
125install -m 644 /etc/firejail/mcabber.profile firejail-$VERSION/etc/firejail/.
126install -m 644 /etc/firejail/midori.profile firejail-$VERSION/etc/firejail/.
127install -m 644 /etc/firejail/mpv.profile firejail-$VERSION/etc/firejail/.
128install -m 644 /etc/firejail/mupen64plus.profile firejail-$VERSION/etc/firejail/.
129install -m 644 /etc/firejail/netsurf.profile firejail-$VERSION/etc/firejail/.
130install -m 644 /etc/firejail/nolocal.net firejail-$VERSION/etc/firejail/.
131install -m 644 /etc/firejail/okular.profile firejail-$VERSION/etc/firejail/.
132install -m 644 /etc/firejail/openbox.profile firejail-$VERSION/etc/firejail/.
133install -m 644 /etc/firejail/opera-beta.profile firejail-$VERSION/etc/firejail/.
134install -m 644 /etc/firejail/opera.profile firejail-$VERSION/etc/firejail/.
135install -m 644 /etc/firejail/palemoon.profile firejail-$VERSION/etc/firejail/.
136install -m 644 /etc/firejail/parole.profile firejail-$VERSION/etc/firejail/.
137install -m 644 /etc/firejail/pidgin.profile firejail-$VERSION/etc/firejail/.
138install -m 644 /etc/firejail/pix.profile firejail-$VERSION/etc/firejail/.
139install -m 644 /etc/firejail/polari.profile firejail-$VERSION/etc/firejail/.
140install -m 644 /etc/firejail/psi-plus.profile firejail-$VERSION/etc/firejail/.
141install -m 644 /etc/firejail/qbittorrent.profile firejail-$VERSION/etc/firejail/.
142install -m 644 /etc/firejail/qtox.profile firejail-$VERSION/etc/firejail/.
143install -m 644 /etc/firejail/quassel.profile firejail-$VERSION/etc/firejail/.
144install -m 644 /etc/firejail/quiterss.profile firejail-$VERSION/etc/firejail/.
145install -m 644 /etc/firejail/qutebrowser.profile firejail-$VERSION/etc/firejail/.
146install -m 644 /etc/firejail/rhythmbox.profile firejail-$VERSION/etc/firejail/.
147install -m 644 /etc/firejail/rtorrent.profile firejail-$VERSION/etc/firejail/.
148install -m 644 /etc/firejail/seamonkey-bin.profile firejail-$VERSION/etc/firejail/.
149install -m 644 /etc/firejail/seamonkey.profile firejail-$VERSION/etc/firejail/.
150install -m 644 /etc/firejail/server.profile firejail-$VERSION/etc/firejail/.
151install -m 644 /etc/firejail/skypeforlinux.profile firejail-$VERSION/etc/firejail/.
152install -m 644 /etc/firejail/skype.profile firejail-$VERSION/etc/firejail/.
153install -m 644 /etc/firejail/slack.profile firejail-$VERSION/etc/firejail/.
154install -m 644 /etc/firejail/snap.profile firejail-$VERSION/etc/firejail/.
155install -m 644 /etc/firejail/soffice.profile firejail-$VERSION/etc/firejail/.
156install -m 644 /etc/firejail/spotify.profile firejail-$VERSION/etc/firejail/.
157install -m 644 /etc/firejail/ssh.profile firejail-$VERSION/etc/firejail/.
158install -m 644 /etc/firejail/steam.profile firejail-$VERSION/etc/firejail/.
159install -m 644 /etc/firejail/stellarium.profile firejail-$VERSION/etc/firejail/.
160install -m 644 /etc/firejail/strings.profile firejail-$VERSION/etc/firejail/.
161install -m 644 /etc/firejail/tar.profile firejail-$VERSION/etc/firejail/.
162install -m 644 /etc/firejail/telegram.profile firejail-$VERSION/etc/firejail/.
163install -m 644 /etc/firejail/Telegram.profile firejail-$VERSION/etc/firejail/.
164install -m 644 /etc/firejail/thunderbird.profile firejail-$VERSION/etc/firejail/.
165install -m 644 /etc/firejail/totem.profile firejail-$VERSION/etc/firejail/.
166install -m 644 /etc/firejail/transmission-gtk.profile firejail-$VERSION/etc/firejail/.
167install -m 644 /etc/firejail/transmission-qt.profile firejail-$VERSION/etc/firejail/.
168install -m 644 /etc/firejail/uget-gtk.profile firejail-$VERSION/etc/firejail/.
169install -m 644 /etc/firejail/unbound.profile firejail-$VERSION/etc/firejail/.
170install -m 644 /etc/firejail/unrar.profile firejail-$VERSION/etc/firejail/.
171install -m 644 /etc/firejail/unzip.profile firejail-$VERSION/etc/firejail/.
172install -m 644 /etc/firejail/uudeview.profile firejail-$VERSION/etc/firejail/.
173install -m 644 /etc/firejail/vivaldi-beta.profile firejail-$VERSION/etc/firejail/.
174install -m 644 /etc/firejail/vivaldi.profile firejail-$VERSION/etc/firejail/.
175install -m 644 /etc/firejail/vlc.profile firejail-$VERSION/etc/firejail/.
176install -m 644 /etc/firejail/warzone2100.profile firejail-$VERSION/etc/firejail/.
177install -m 644 /etc/firejail/webserver.net firejail-$VERSION/etc/firejail/.
178install -m 644 /etc/firejail/weechat-curses.profile firejail-$VERSION/etc/firejail/.
179install -m 644 /etc/firejail/weechat.profile firejail-$VERSION/etc/firejail/.
180install -m 644 /etc/firejail/wesnoth.profile firejail-$VERSION/etc/firejail/.
181install -m 644 /etc/firejail/whitelist-common.inc firejail-$VERSION/etc/firejail/.
182install -m 644 /etc/firejail/wine.profile firejail-$VERSION/etc/firejail/.
183install -m 644 /etc/firejail/xchat.profile firejail-$VERSION/etc/firejail/.
184install -m 644 /etc/firejail/xplayer.profile firejail-$VERSION/etc/firejail/.
185install -m 644 /etc/firejail/xreader.profile firejail-$VERSION/etc/firejail/.
186install -m 644 /etc/firejail/xviewer.profile firejail-$VERSION/etc/firejail/.
187install -m 644 /etc/firejail/xzdec.profile firejail-$VERSION/etc/firejail/.
188install -m 644 /etc/firejail/xz.profile firejail-$VERSION/etc/firejail/.
189install -m 644 /etc/firejail/zathura.profile firejail-$VERSION/etc/firejail/.
190install -m 644 /etc/firejail/7z.profile firejail-$VERSION/etc/firejail/.
191install -m 644 /etc/firejail/keepass.profile firejail-$VERSION/etc/firejail/.
192install -m 644 /etc/firejail/keepassx.profile firejail-$VERSION/etc/firejail/.
193install -m 644 /etc/firejail/claws-mail.profile firejail-$VERSION/etc/firejail/.
194install -m 644 /etc/firejail/mutt.profile firejail-$VERSION/etc/firejail/.
195install -m 644 /etc/firejail/git.profile firejail-$VERSION/etc/firejail/.
196install -m 644 /etc/firejail/emacs.profile firejail-$VERSION/etc/firejail/.
197install -m 644 /etc/firejail/vim.profile firejail-$VERSION/etc/firejail/.
198install -m 644 /etc/firejail/xpdf.profile firejail-$VERSION/etc/firejail/.
199install -m 644 /etc/firejail/virtualbox.profile firejail-$VERSION/etc/firejail/.
200install -m 644 /etc/firejail/openshot.profile firejail-$VERSION/etc/firejail/.
201install -m 644 /etc/firejail/flowblade.profile firejail-$VERSION/etc/firejail/.
202install -m 644 /etc/firejail/eog.profile firejail-$VERSION/etc/firejail/.
203install -m 644 /etc/firejail/evolution.profile firejail-$VERSION/etc/firejail/.
204install -m 644 /etc/firejail/feh.profile firejail-$VERSION/etc/firejail/.
205install -m 644 /etc/firejail/gimp.profile firejail-$VERSION/etc/firejail/.
206install -m 644 /etc/firejail/inkscape.profile firejail-$VERSION/etc/firejail/.
207install -m 644 /etc/firejail/luminance-hdr.profile firejail-$VERSION/etc/firejail/.
208install -m 644 /etc/firejail/mupdf.profile firejail-$VERSION/etc/firejail/.
209install -m 644 /etc/firejail/qpdfview.profile firejail-$VERSION/etc/firejail/.
210install -m 644 /etc/firejail/ranger.profile firejail-$VERSION/etc/firejail/.
211install -m 644 /etc/firejail/synfigstudio.profile firejail-$VERSION/etc/firejail/.
212
213
214mkdir -p firejail-$VERSION/usr/share/bash-completion/completions
215install -m 644 /usr/share/bash-completion/completions/firejail firejail-$VERSION/usr/share/bash-completion/completions/.
216install -m 644 /usr/share/bash-completion/completions/firemon firejail-$VERSION/usr/share/bash-completion/completions/.
217install -m 644 /usr/share/bash-completion/completions/firecfg firejail-$VERSION/usr/share/bash-completion/completions/.
218
219echo "building tar.gz archive"
220tar -czvf firejail-$VERSION.tar.gz firejail-$VERSION
221
222cp firejail-$VERSION.tar.gz SOURCES/.
223
224echo "building config spec"
225cat <<EOF > SPECS/firejail.spec
226%define __spec_install_post %{nil}
227%define debug_package %{nil}
228%define __os_install_post %{_dbpath}/brp-compress
229
230Summary: Linux namepaces sandbox program
231Name: firejail
232Version: $VERSION
233Release: 1
234License: GPL+
235Group: Development/Tools
236SOURCE0 : %{name}-%{version}.tar.gz
237URL: http://firejail.wordpress.com
238
239BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
240
241%description
242Firejail is a SUID sandbox program that reduces the risk of security
243breaches by restricting the running environment of untrusted applications
244using Linux namespaces. It includes a sandbox profile for Mozilla Firefox.
245
246%prep
247%setup -q
248
249%build
250
251%install
252rm -rf %{buildroot}
253mkdir -p %{buildroot}
254
255cp -a * %{buildroot}
256
257
258%clean
259rm -rf %{buildroot}
260
261
262%files
263%defattr(-,root,root,-)
264%config(noreplace) %{_sysconfdir}/%{name}/0ad.profile
265%config(noreplace) %{_sysconfdir}/%{name}/abrowser.profile
266%config(noreplace) %{_sysconfdir}/%{name}/atom-beta.profile
267%config(noreplace) %{_sysconfdir}/%{name}/atom.profile
268%config(noreplace) %{_sysconfdir}/%{name}/atril.profile
269%config(noreplace) %{_sysconfdir}/%{name}/audacious.profile
270%config(noreplace) %{_sysconfdir}/%{name}/audacity.profile
271%config(noreplace) %{_sysconfdir}/%{name}/aweather.profile
272%config(noreplace) %{_sysconfdir}/%{name}/bitlbee.profile
273%config(noreplace) %{_sysconfdir}/%{name}/brave.profile
274%config(noreplace) %{_sysconfdir}/%{name}/cherrytree.profile
275%config(noreplace) %{_sysconfdir}/%{name}/chromium-browser.profile
276%config(noreplace) %{_sysconfdir}/%{name}/chromium.profile
277%config(noreplace) %{_sysconfdir}/%{name}/clementine.profile
278%config(noreplace) %{_sysconfdir}/%{name}/cmus.profile
279%config(noreplace) %{_sysconfdir}/%{name}/conkeror.profile
280%config(noreplace) %{_sysconfdir}/%{name}/corebird.profile
281%config(noreplace) %{_sysconfdir}/%{name}/cpio.profile
282%config(noreplace) %{_sysconfdir}/%{name}/cyberfox.profile
283%config(noreplace) %{_sysconfdir}/%{name}/Cyberfox.profile
284%config(noreplace) %{_sysconfdir}/%{name}/deadbeef.profile
285%config(noreplace) %{_sysconfdir}/%{name}/default.profile
286%config(noreplace) %{_sysconfdir}/%{name}/deluge.profile
287%config(noreplace) %{_sysconfdir}/%{name}/dillo.profile
288%config(noreplace) %{_sysconfdir}/%{name}/disable-common.inc
289%config(noreplace) %{_sysconfdir}/%{name}/disable-devel.inc
290%config(noreplace) %{_sysconfdir}/%{name}/disable-passwdmgr.inc
291%config(noreplace) %{_sysconfdir}/%{name}/disable-programs.inc
292%config(noreplace) %{_sysconfdir}/%{name}/dnscrypt-proxy.profile
293%config(noreplace) %{_sysconfdir}/%{name}/dnsmasq.profile
294%config(noreplace) %{_sysconfdir}/%{name}/dosbox.profile
295%config(noreplace) %{_sysconfdir}/%{name}/dropbox.profile
296%config(noreplace) %{_sysconfdir}/%{name}/empathy.profile
297%config(noreplace) %{_sysconfdir}/%{name}/eom.profile
298%config(noreplace) %{_sysconfdir}/%{name}/epiphany.profile
299%config(noreplace) %{_sysconfdir}/%{name}/evince.profile
300%config(noreplace) %{_sysconfdir}/%{name}/fbreader.profile
301%config(noreplace) %{_sysconfdir}/%{name}/file.profile
302%config(noreplace) %{_sysconfdir}/%{name}/filezilla.profile
303%config(noreplace) %{_sysconfdir}/%{name}/firefox-esr.profile
304%config(noreplace) %{_sysconfdir}/%{name}/firefox.profile
305%config(noreplace) %{_sysconfdir}/%{name}/firejail.config
306%config(noreplace) %{_sysconfdir}/%{name}/flashpeak-slimjet.profile
307%config(noreplace) %{_sysconfdir}/%{name}/franz.profile
308%config(noreplace) %{_sysconfdir}/%{name}/gajim.profile
309%config(noreplace) %{_sysconfdir}/%{name}/gitter.profile
310%config(noreplace) %{_sysconfdir}/%{name}/gnome-chess.profile
311%config(noreplace) %{_sysconfdir}/%{name}/gnome-mplayer.profile
312%config(noreplace) %{_sysconfdir}/%{name}/google-chrome-beta.profile
313%config(noreplace) %{_sysconfdir}/%{name}/google-chrome.profile
314%config(noreplace) %{_sysconfdir}/%{name}/google-chrome-stable.profile
315%config(noreplace) %{_sysconfdir}/%{name}/google-chrome-unstable.profile
316%config(noreplace) %{_sysconfdir}/%{name}/google-play-music-desktop-player.profile
317%config(noreplace) %{_sysconfdir}/%{name}/gpredict.profile
318%config(noreplace) %{_sysconfdir}/%{name}/gtar.profile
319%config(noreplace) %{_sysconfdir}/%{name}/gthumb.profile
320%config(noreplace) %{_sysconfdir}/%{name}/gwenview.profile
321%config(noreplace) %{_sysconfdir}/%{name}/gzip.profile
322%config(noreplace) %{_sysconfdir}/%{name}/hedgewars.profile
323%config(noreplace) %{_sysconfdir}/%{name}/hexchat.profile
324%config(noreplace) %{_sysconfdir}/%{name}/icecat.profile
325%config(noreplace) %{_sysconfdir}/%{name}/icedove.profile
326%config(noreplace) %{_sysconfdir}/%{name}/iceweasel.profile
327%config(noreplace) %{_sysconfdir}/%{name}/inox.profile
328%config(noreplace) %{_sysconfdir}/%{name}/jitsi.profile
329%config(noreplace) %{_sysconfdir}/%{name}/kmail.profile
330%config(noreplace) %{_sysconfdir}/%{name}/konversation.profile
331%config(noreplace) %{_sysconfdir}/%{name}/less.profile
332%config(noreplace) %{_sysconfdir}/%{name}/libreoffice.profile
333%config(noreplace) %{_sysconfdir}/%{name}/localc.profile
334%config(noreplace) %{_sysconfdir}/%{name}/lodraw.profile
335%config(noreplace) %{_sysconfdir}/%{name}/loffice.profile
336%config(noreplace) %{_sysconfdir}/%{name}/lofromtemplate.profile
337%config(noreplace) %{_sysconfdir}/%{name}/login.users
338%config(noreplace) %{_sysconfdir}/%{name}/loimpress.profile
339%config(noreplace) %{_sysconfdir}/%{name}/lomath.profile
340%config(noreplace) %{_sysconfdir}/%{name}/loweb.profile
341%config(noreplace) %{_sysconfdir}/%{name}/lowriter.profile
342%config(noreplace) %{_sysconfdir}/%{name}/lxterminal.profile
343%config(noreplace) %{_sysconfdir}/%{name}/mathematica.profile
344%config(noreplace) %{_sysconfdir}/%{name}/Mathematica.profile
345%config(noreplace) %{_sysconfdir}/%{name}/mcabber.profile
346%config(noreplace) %{_sysconfdir}/%{name}/midori.profile
347%config(noreplace) %{_sysconfdir}/%{name}/mpv.profile
348%config(noreplace) %{_sysconfdir}/%{name}/mupen64plus.profile
349%config(noreplace) %{_sysconfdir}/%{name}/netsurf.profile
350%config(noreplace) %{_sysconfdir}/%{name}/nolocal.net
351%config(noreplace) %{_sysconfdir}/%{name}/okular.profile
352%config(noreplace) %{_sysconfdir}/%{name}/openbox.profile
353%config(noreplace) %{_sysconfdir}/%{name}/opera-beta.profile
354%config(noreplace) %{_sysconfdir}/%{name}/opera.profile
355%config(noreplace) %{_sysconfdir}/%{name}/palemoon.profile
356%config(noreplace) %{_sysconfdir}/%{name}/parole.profile
357%config(noreplace) %{_sysconfdir}/%{name}/pidgin.profile
358%config(noreplace) %{_sysconfdir}/%{name}/pix.profile
359%config(noreplace) %{_sysconfdir}/%{name}/polari.profile
360%config(noreplace) %{_sysconfdir}/%{name}/psi-plus.profile
361%config(noreplace) %{_sysconfdir}/%{name}/qbittorrent.profile
362%config(noreplace) %{_sysconfdir}/%{name}/qtox.profile
363%config(noreplace) %{_sysconfdir}/%{name}/quassel.profile
364%config(noreplace) %{_sysconfdir}/%{name}/quiterss.profile
365%config(noreplace) %{_sysconfdir}/%{name}/qutebrowser.profile
366%config(noreplace) %{_sysconfdir}/%{name}/rhythmbox.profile
367%config(noreplace) %{_sysconfdir}/%{name}/rtorrent.profile
368%config(noreplace) %{_sysconfdir}/%{name}/seamonkey-bin.profile
369%config(noreplace) %{_sysconfdir}/%{name}/seamonkey.profile
370%config(noreplace) %{_sysconfdir}/%{name}/server.profile
371%config(noreplace) %{_sysconfdir}/%{name}/skypeforlinux.profile
372%config(noreplace) %{_sysconfdir}/%{name}/skype.profile
373%config(noreplace) %{_sysconfdir}/%{name}/slack.profile
374%config(noreplace) %{_sysconfdir}/%{name}/snap.profile
375%config(noreplace) %{_sysconfdir}/%{name}/soffice.profile
376%config(noreplace) %{_sysconfdir}/%{name}/spotify.profile
377%config(noreplace) %{_sysconfdir}/%{name}/ssh.profile
378%config(noreplace) %{_sysconfdir}/%{name}/steam.profile
379%config(noreplace) %{_sysconfdir}/%{name}/stellarium.profile
380%config(noreplace) %{_sysconfdir}/%{name}/strings.profile
381%config(noreplace) %{_sysconfdir}/%{name}/tar.profile
382%config(noreplace) %{_sysconfdir}/%{name}/telegram.profile
383%config(noreplace) %{_sysconfdir}/%{name}/Telegram.profile
384%config(noreplace) %{_sysconfdir}/%{name}/thunderbird.profile
385%config(noreplace) %{_sysconfdir}/%{name}/totem.profile
386%config(noreplace) %{_sysconfdir}/%{name}/transmission-gtk.profile
387%config(noreplace) %{_sysconfdir}/%{name}/transmission-qt.profile
388%config(noreplace) %{_sysconfdir}/%{name}/uget-gtk.profile
389%config(noreplace) %{_sysconfdir}/%{name}/unbound.profile
390%config(noreplace) %{_sysconfdir}/%{name}/unrar.profile
391%config(noreplace) %{_sysconfdir}/%{name}/unzip.profile
392%config(noreplace) %{_sysconfdir}/%{name}/uudeview.profile
393%config(noreplace) %{_sysconfdir}/%{name}/vivaldi-beta.profile
394%config(noreplace) %{_sysconfdir}/%{name}/vivaldi.profile
395%config(noreplace) %{_sysconfdir}/%{name}/vlc.profile
396%config(noreplace) %{_sysconfdir}/%{name}/warzone2100.profile
397%config(noreplace) %{_sysconfdir}/%{name}/webserver.net
398%config(noreplace) %{_sysconfdir}/%{name}/weechat-curses.profile
399%config(noreplace) %{_sysconfdir}/%{name}/weechat.profile
400%config(noreplace) %{_sysconfdir}/%{name}/wesnoth.profile
401%config(noreplace) %{_sysconfdir}/%{name}/whitelist-common.inc
402%config(noreplace) %{_sysconfdir}/%{name}/wine.profile
403%config(noreplace) %{_sysconfdir}/%{name}/xchat.profile
404%config(noreplace) %{_sysconfdir}/%{name}/xplayer.profile
405%config(noreplace) %{_sysconfdir}/%{name}/xreader.profile
406%config(noreplace) %{_sysconfdir}/%{name}/xviewer.profile
407%config(noreplace) %{_sysconfdir}/%{name}/xzdec.profile
408%config(noreplace) %{_sysconfdir}/%{name}/xz.profile
409%config(noreplace) %{_sysconfdir}/%{name}/zathura.profile
410%config(noreplace) %{_sysconfdir}/%{name}/7z.profile
411%config(noreplace) %{_sysconfdir}/%{name}/keepass.profile
412%config(noreplace) %{_sysconfdir}/%{name}/keepassx.profile
413%config(noreplace) %{_sysconfdir}/%{name}/claws-mail.profile
414%config(noreplace) %{_sysconfdir}/%{name}/mutt.profile
415%config(noreplace) %{_sysconfdir}/%{name}/git.profile
416%config(noreplace) %{_sysconfdir}/%{name}/emacs.profile
417%config(noreplace) %{_sysconfdir}/%{name}/vim.profile
418%config(noreplace) %{_sysconfdir}/%{name}/xpdf.profile
419%config(noreplace) %{_sysconfdir}/%{name}/virtualbox.profile
420%config(noreplace) %{_sysconfdir}/%{name}/openshot.profile
421%config(noreplace) %{_sysconfdir}/%{name}/flowblade.profile
422%config(noreplace) %{_sysconfdir}/%{name}/eog.profile
423%config(noreplace) %{_sysconfdir}/%{name}/evolution.profile
424%config(noreplace) %{_sysconfdir}/%{name}/feh.profile
425%config(noreplace) %{_sysconfdir}/%{name}/inkscape.profile
426%config(noreplace) %{_sysconfdir}/%{name}/gimp.profile
427%config(noreplace) %{_sysconfdir}/%{name}/luminance-hdr.profile
428%config(noreplace) %{_sysconfdir}/%{name}/mupdf.profile
429%config(noreplace) %{_sysconfdir}/%{name}/qpdfview.profile
430%config(noreplace) %{_sysconfdir}/%{name}/ranger.profile
431%config(noreplace) %{_sysconfdir}/%{name}/synfigstudio.profile
432
433/usr/bin/firejail
434/usr/bin/firemon
435/usr/bin/firecfg
436
437/usr/lib/firejail/libtrace.so
438/usr/lib/firejail/libtracelog.so
439/usr/lib/firejail/libconnect.so
440/usr/lib/firejail/faudit
441/usr/lib/firejail/ftee
442/usr/lib/firejail/firecfg.config
443/usr/lib/firejail/fshaper.sh
444
445/usr/share/doc/packages/firejail/COPYING
446/usr/share/doc/packages/firejail/README
447/usr/share/doc/packages/firejail/RELNOTES
448/usr/share/man/man1/firejail.1.gz
449/usr/share/man/man1/firemon.1.gz
450/usr/share/man/man1/firecfg.1.gz
451/usr/share/man/man5/firejail-profile.5.gz
452/usr/share/man/man5/firejail-login.5.gz
453/usr/share/bash-completion/completions/firejail
454/usr/share/bash-completion/completions/firemon
455/usr/share/bash-completion/completions/firecfg
456
457%post
458chmod u+s /usr/bin/firejail
459
460%changelog
461* Fri Oct 21 2016 netblue30 <netblue30@yahoo.com> 0.9.44-1
462 - CVE-2016-7545 submitted by Aleksey Manevich
463 - modifs: removed man firejail-config
464 - modifs: --private-tmp whitelists /tmp/.X11-unix directory
465 - modifs: Nvidia drivers added to --private-dev
466 - modifs: /srv supported by --whitelist
467 - feature: allow user access to /sys/fs (--noblacklist=/sys/fs)
468 - feature: support starting/joining sandbox is a single command
469 (--join-or-start)
470 - feature: X11 detection support for --audit
471 - feature: assign a name to the interface connected to the bridge
472 (--veth-name)
473 - feature: all user home directories are visible (--allusers)
474 - feature: add files to sandbox container (--put)
475 - feature: blocking x11 (--x11=block)
476 - feature: X11 security extension (--x11=xorg)
477 - feature: disable 3D hardware acceleration (--no3d)
478 - feature: x11 xpra, x11 xephyr, x11 block, allusers, no3d profile commands
479 - feature: move files in sandbox (--put)
480 - feature: accept wildcard patterns in user name field of restricted
481 shell login feature
482 - new profiles: qpdfview, mupdf, Luminance HDR, Synfig Studio, Gimp, Inkscape
483 - new profiles: feh, ranger, zathura, 7z, keepass, keepassx,
484 - new profiles: claws-mail, mutt, git, emacs, vim, xpdf, VirtualBox, OpenShot
485 - new profiles: Flowblade, Eye of GNOME (eog), Evolution
486 - bugfixes
487
488* Thu Sep 8 2016 netblue30 <netblue30@yahoo.com> 0.9.42-1
489 - security: --whitelist deleted files, submitted by Vasya Novikov
490 - security: disable x32 ABI in seccomp, submitted by Jann Horn
491 - security: tighten --chroot, submitted by Jann Horn
492 - security: terminal sandbox escape, submitted by Stephan Sokolow
493 - security: several TOCTOU fixes submitted by Aleksey Manevich
494 - modifs: bringing back --private-home option
495 - modifs: deprecated --user option, please use "sudo -u username firejail"
496 - modifs: allow symlinks in home directory for --whitelist option
497 - modifs: Firejail prompt is enabled by env variable FIREJAIL_PROMPT="yes"
498 - modifs: recursive mkdir
499 - modifs: include /dev/snd in --private-dev
500 - modifs: seccomp filter update
501 - modifs: release archives moved to .xz format
502 - feature: AppImage support (--appimage)
503 - feature: AppArmor support (--apparmor)
504 - feature: Ubuntu snap support (/etc/firejail/snap.profile)
505 - feature: Sandbox auditing support (--audit)
506 - feature: remove environment variable (--rmenv)
507 - feature: noexec support (--noexec)
508 - feature: clean local overlay storage directory (--overlay-clean)
509 - feature: store and reuse overlay (--overlay-named)
510 - feature: allow debugging inside the sandbox with gdb and strace
511 (--allow-debuggers)
512 - feature: mkfile profile command
513 - feature: quiet profile command
514 - feature: x11 profile command
515 - feature: option to fix desktop files (firecfg --fix)
516 - compile time: Busybox support (--enable-busybox-workaround)
517 - compile time: disable overlayfs (--disable-overlayfs)
518 - compile time: disable whitlisting (--disable-whitelist)
519 - compile time: disable global config (--disable-globalcfg)
520 - run time: enable/disable overlayfs (overlayfs yes/no)
521 - run time: enable/disable quiet as default (quiet-by-default yes/no)
522 - run time: user-defined network filter (netfilter-default)
523 - run time: enable/disable whitelisting (whitelist yes/no)
524 - run time: enable/disable remounting of /proc and /sys
525 (remount-proc-sys yes/no)
526 - run time: enable/disable chroot desktop features (chroot-desktop yes/no)
527 - profiles: Gitter, gThumb, mpv, Franz messenger, LibreOffice
528 - profiles: pix, audacity, xz, xzdec, gzip, cpio, less
529 - profiles: Atom Beta, Atom, jitsi, eom, uudeview
530 - profiles: tar (gtar), unzip, unrar, file, skypeforlinux,
531 - profiles: inox, Slack, gnome-chess. Gajim IM client, DOSBox
532 - bugfixes
533
534EOF
535
536echo "building rpm"
537rpmbuild -ba SPECS/firejail.spec
538rpm -qpl RPMS/x86_64/firejail-$VERSION-1.x86_64.rpm
539cd ..
540rm -f firejail-$VERSION-1.x86_64.rpm
541cp rpmbuild/RPMS/x86_64/firejail-$VERSION-1.x86_64.rpm .
542
diff --git a/src/faudit/syscall.c b/src/faudit/syscall.c
index 9924be00f..3c87305df 100644
--- a/src/faudit/syscall.c
+++ b/src/faudit/syscall.c
@@ -92,7 +92,8 @@ void syscall_run(const char *name) {
92 errExit("fork"); 92 errExit("fork");
93 if (child == 0) { 93 if (child == 0) {
94 execl(prog, prog, "syscall", name, NULL); 94 execl(prog, prog, "syscall", name, NULL);
95 exit(1); 95 perror("execl");
96 _exit(1);
96 } 97 }
97 98
98 // wait for the child to finish 99 // wait for the child to finish
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config
index 95d3d5caa..e3e333497 100644
--- a/src/firecfg/firecfg.config
+++ b/src/firecfg/firecfg.config
@@ -42,11 +42,13 @@ opera-beta
42opera 42opera
43palemoon 43palemoon
44qutebrowser 44qutebrowser
45start-tor-browser
45seamonkey 46seamonkey
46seamonkey-bin 47seamonkey-bin
47thunderbird 48thunderbird
48vivaldi-beta 49vivaldi-beta
49vivaldi 50vivaldi
51evolution
50 52
51# chat/messaging 53# chat/messaging
52bitlbee 54bitlbee
@@ -76,6 +78,7 @@ unbound
76mupen64plus 78mupen64plus
77wine 79wine
78dosbox 80dosbox
81virtualbox
79 82
80# games 83# games
810ad 840ad
@@ -134,8 +137,12 @@ Mathematica
134mathematica 137mathematica
135okular 138okular
136pix 139pix
140xpdf
137xreader 141xreader
138zathura 142zathura
143openshot
144flowblade
145eog
139 146
140# other 147# other
141ssh 148ssh
@@ -144,6 +151,7 @@ atom
144ranger 151ranger
145keepass 152keepass
146keepassx 153keepassx
154xiphos
147 155
148# weather/climate 156# weather/climate
149aweather 157aweather
diff --git a/src/firejail/Makefile.in b/src/firejail/Makefile.in
index fce460906..c99b6c30c 100644
--- a/src/firejail/Makefile.in
+++ b/src/firejail/Makefile.in
@@ -30,11 +30,11 @@ BINOBJS = $(foreach file, $(OBJS), $file)
30CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security 30CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
31LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread 31LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
32 32
33%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/euid_common.h ../include/libnetlink.h ../include/pid.h 33%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/euid_common.h ../include/pid.h ../include/seccomp.h ../include/syscall.h
34 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ 34 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
35 35
36firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o 36firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o
37 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/libnetlink.o ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS) 37 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS)
38 38
39clean:; rm -f *.o firejail firejail.1 firejail.1.gz 39clean:; rm -f *.o firejail firejail.1 firejail.1.gz
40 40
diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c
index 05bd8a1d8..322798ee5 100644
--- a/src/firejail/appimage.c
+++ b/src/firejail/appimage.c
@@ -39,7 +39,7 @@ void appimage_set(const char *appimage_path) {
39 assert(appimage_path); 39 assert(appimage_path);
40 assert(devloop == NULL); // don't call this twice! 40 assert(devloop == NULL); // don't call this twice!
41 EUID_ASSERT(); 41 EUID_ASSERT();
42 42
43#ifdef LOOP_CTL_GET_FREE // test for older kernels; this definition is found in /usr/include/linux/loop.h 43#ifdef LOOP_CTL_GET_FREE // test for older kernels; this definition is found in /usr/include/linux/loop.h
44 // check appimage_path 44 // check appimage_path
45 if (access(appimage_path, R_OK) == -1) { 45 if (access(appimage_path, R_OK) == -1) {
@@ -47,6 +47,12 @@ void appimage_set(const char *appimage_path) {
47 exit(1); 47 exit(1);
48 } 48 }
49 49
50 // get appimage type and ELF size
51 // a value of 0 means we are dealing with a type1 appimage
52 long unsigned int size = appimage2_size(appimage_path);
53 if (arg_debug)
54 printf("AppImage ELF size %lu\n", size);
55
50 // open as user to prevent race condition 56 // open as user to prevent race condition
51 int ffd = open(appimage_path, O_RDONLY|O_CLOEXEC); 57 int ffd = open(appimage_path, O_RDONLY|O_CLOEXEC);
52 if (ffd == -1) { 58 if (ffd == -1) {
@@ -54,9 +60,8 @@ void appimage_set(const char *appimage_path) {
54 exit(1); 60 exit(1);
55 } 61 }
56 62
57 EUID_ROOT();
58
59 // find or allocate a free loop device to use 63 // find or allocate a free loop device to use
64 EUID_ROOT();
60 int cfd = open("/dev/loop-control", O_RDWR); 65 int cfd = open("/dev/loop-control", O_RDWR);
61 int devnr = ioctl(cfd, LOOP_CTL_GET_FREE); 66 int devnr = ioctl(cfd, LOOP_CTL_GET_FREE);
62 if (devnr == -1) { 67 if (devnr == -1) {
@@ -72,38 +77,56 @@ void appimage_set(const char *appimage_path) {
72 fprintf(stderr, "Error: cannot configure the loopback device\n"); 77 fprintf(stderr, "Error: cannot configure the loopback device\n");
73 exit(1); 78 exit(1);
74 } 79 }
80
81 if (size) {
82 struct loop_info64 info;
83 memset(&info, 0, sizeof(struct loop_info64));
84 info.lo_offset = size;
85 if (ioctl(lfd, LOOP_SET_STATUS64, &info) == -1)
86 errExit("configure appimage offset");
87 }
88
75 close(lfd); 89 close(lfd);
76 close(ffd); 90 close(ffd);
77
78 EUID_USER(); 91 EUID_USER();
79 92
80 // creates directory with perms 0700 93 // creates appimage mount point perms 0700
81 char dirname[] = "/tmp/firejail-mnt-XXXXXX"; 94 if (asprintf(&mntdir, "%s/.appimage-%u", RUN_FIREJAIL_APPIMAGE_DIR, getpid()) == -1)
82 mntdir = strdup(mkdtemp(dirname)); 95 errExit("asprintf");
83 if (mntdir == NULL) { 96 EUID_ROOT();
84 fprintf(stderr, "Error: cannot create temporary directory\n"); 97 if (mkdir(mntdir, 0700) == -1) {
98 fprintf(stderr, "Error: cannot create appimage mount point\n");
85 exit(1); 99 exit(1);
86 } 100 }
87 if (chmod(mntdir, 0700) == -1) 101 if (chmod(mntdir, 0700) == -1)
88 errExit("chmod"); 102 errExit("chmod");
103 if (chown(mntdir, getuid(), getgid()) == -1)
104 errExit("chown");
105 EUID_USER();
89 ASSERT_PERMS(mntdir, getuid(), getgid(), 0700); 106 ASSERT_PERMS(mntdir, getuid(), getgid(), 0700);
90 107
108 // mount
91 char *mode; 109 char *mode;
92 if (asprintf(&mode, "mode=700,uid=%d,gid=%d", getuid(), getgid()) == -1) 110 if (asprintf(&mode, "mode=700,uid=%d,gid=%d", getuid(), getgid()) == -1)
93 errExit("asprintf"); 111 errExit("asprintf");
94
95 EUID_ROOT(); 112 EUID_ROOT();
96 if (mount(devloop, mntdir, "iso9660",MS_MGC_VAL|MS_RDONLY, mode) < 0) 113
97 errExit("mounting appimage"); 114 if (size == 0) {
98 115 if (mount(devloop, mntdir, "iso9660",MS_MGC_VAL|MS_RDONLY, mode) < 0)
116 errExit("mounting appimage");
117 }
118 else {
119 if (mount(devloop, mntdir, "squashfs",MS_MGC_VAL|MS_RDONLY, mode) < 0)
120 errExit("mounting appimage");
121 }
99 122
100 if (arg_debug) 123 if (arg_debug)
101 printf("appimage mounted on %s\n", mntdir); 124 printf("appimage mounted on %s\n", mntdir);
102 EUID_USER(); 125 EUID_USER();
103 126
127 // set environment
104 if (appimage_path && setenv("APPIMAGE", appimage_path, 1) < 0) 128 if (appimage_path && setenv("APPIMAGE", appimage_path, 1) < 0)
105 errExit("setenv"); 129 errExit("setenv");
106
107 if (mntdir && setenv("APPDIR", mntdir, 1) < 0) 130 if (mntdir && setenv("APPDIR", mntdir, 1) < 0)
108 errExit("setenv"); 131 errExit("setenv");
109 132
@@ -121,16 +144,32 @@ void appimage_set(const char *appimage_path) {
121void appimage_clear(void) { 144void appimage_clear(void) {
122 int rv; 145 int rv;
123 146
147 EUID_ROOT();
124 if (mntdir) { 148 if (mntdir) {
125 rv = umount2(mntdir, MNT_FORCE); 149 int i;
126 if (rv == -1 && errno == EBUSY) { 150 int rv = 0;
127 sleep(1); 151 for (i = 0; i < 5; i++) {
128 rv = umount2(mntdir, MNT_FORCE); 152 rv = umount2(mntdir, MNT_FORCE);
129 (void) rv; 153 if (rv == 0)
154 break;
155 if (rv == -1 && errno == EBUSY) {
156 if (!arg_quiet)
157 printf("Warning: EBUSY error trying to unmount %s\n", mntdir);
158 sleep(2);
159 continue;
160 }
130 161
162 // rv = -1
163 if (!arg_quiet) {
164 printf("Warning: error trying to unmount %s\n", mntdir);
165 perror("umount");
166 }
167 }
168
169 if (rv == 0) {
170 rmdir(mntdir);
171 free(mntdir);
131 } 172 }
132 rmdir(mntdir);
133 free(mntdir);
134 } 173 }
135 174
136 if (devloop) { 175 if (devloop) {
diff --git a/src/firejail/appimage_size.c b/src/firejail/appimage_size.c
new file mode 100644
index 000000000..3f5c3150c
--- /dev/null
+++ b/src/firejail/appimage_size.c
@@ -0,0 +1,160 @@
1/*
2 * Copyright (C) 2014-2016 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/*
21Compile with:
22gcc elfsize.c -o elfsize
23Example:
24ls -l 126584
25Calculation using the values also reported by readelf -h:
26Start of section headers e_shoff 124728
27Size of section headers e_shentsize 64
28Number of section headers e_shnum 29
29e_shoff + ( e_shentsize * e_shnum ) = 126584
30*/
31#include <elf.h>
32#include <byteswap.h>
33#include <stdio.h>
34#include <stdint.h>
35#include <errno.h>
36#include <stdlib.h>
37#include <unistd.h>
38#include <string.h>
39#include <fcntl.h>
40
41typedef Elf32_Nhdr Elf_Nhdr;
42
43static Elf64_Ehdr ehdr;
44
45#if __BYTE_ORDER == __LITTLE_ENDIAN
46#define ELFDATANATIVE ELFDATA2LSB
47#elif __BYTE_ORDER == __BIG_ENDIAN
48#define ELFDATANATIVE ELFDATA2MSB
49#else
50#error "Unknown machine endian"
51#endif
52
53static uint16_t file16_to_cpu(uint16_t val) {
54 if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
55 val = bswap_16(val);
56 return val;
57}
58
59
60static uint32_t file32_to_cpu(uint32_t val) {
61 if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
62 val = bswap_32(val);
63 return val;
64}
65
66
67static uint64_t file64_to_cpu(uint64_t val) {
68 if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
69 val = bswap_64(val);
70 return val;
71}
72
73
74// return 0 if error
75static long unsigned int read_elf32(int fd) {
76 Elf32_Ehdr ehdr32;
77 ssize_t ret;
78
79 ret = pread(fd, &ehdr32, sizeof(ehdr32), 0);
80 if (ret < 0 || (size_t)ret != sizeof(ehdr))
81 return 0;
82
83 ehdr.e_shoff = file32_to_cpu(ehdr32.e_shoff);
84 ehdr.e_shentsize = file16_to_cpu(ehdr32.e_shentsize);
85 ehdr.e_shnum = file16_to_cpu(ehdr32.e_shnum);
86
87 return(ehdr.e_shoff + (ehdr.e_shentsize * ehdr.e_shnum));
88}
89
90
91// return 0 if error
92static long unsigned int read_elf64(int fd) {
93 Elf64_Ehdr ehdr64;
94 ssize_t ret;
95
96 ret = pread(fd, &ehdr64, sizeof(ehdr64), 0);
97 if (ret < 0 || (size_t)ret != sizeof(ehdr))
98 return 0;
99
100 ehdr.e_shoff = file64_to_cpu(ehdr64.e_shoff);
101 ehdr.e_shentsize = file16_to_cpu(ehdr64.e_shentsize);
102 ehdr.e_shnum = file16_to_cpu(ehdr64.e_shnum);
103
104 return(ehdr.e_shoff + (ehdr.e_shentsize * ehdr.e_shnum));
105}
106
107
108// return 0 if error
109// return 0 if this is not an appimgage2 file
110long unsigned int appimage2_size(const char *fname) {
111/* TODO, FIXME: This assumes that the section header table (SHT) is
112the last part of the ELF. This is usually the case but
113it could also be that the last section is the last part
114of the ELF. This should be checked for.
115*/
116 ssize_t ret;
117 int fd;
118 long unsigned int size = 0;
119
120 fd = open(fname, O_RDONLY);
121 if (fd < 0)
122 return 0;
123
124 ret = pread(fd, ehdr.e_ident, EI_NIDENT, 0);
125 if (ret != EI_NIDENT)
126 goto getout;
127
128 if ((ehdr.e_ident[EI_DATA] != ELFDATA2LSB) &&
129 (ehdr.e_ident[EI_DATA] != ELFDATA2MSB))
130 goto getout;
131
132 if(ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
133 size = read_elf32(fd);
134 }
135 else if(ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
136 size = read_elf64(fd);
137 }
138 else {
139 goto getout;
140 }
141 if (size == 0)
142 goto getout;
143
144
145 // look for a LZMA header at this location
146 unsigned char buf[4];
147 ret = pread(fd, buf, 4, size);
148 if (ret != 4) {
149 size = 0;
150 goto getout;
151 }
152 if (memcmp(buf, "hsqs", 4) != 0)
153 size = 0;
154
155getout:
156 close(fd);
157 return size;
158}
159
160
diff --git a/src/firejail/arp.c b/src/firejail/arp.c
index fb5e426b0..ddb75905f 100644
--- a/src/firejail/arp.c
+++ b/src/firejail/arp.c
@@ -40,6 +40,7 @@ typedef struct arp_hdr_t {
40 uint8_t target_ip[4]; 40 uint8_t target_ip[4];
41} ArpHdr; 41} ArpHdr;
42 42
43
43// returns 0 if the address is not in use, -1 otherwise 44// returns 0 if the address is not in use, -1 otherwise
44int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr) { 45int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr) {
45 if (strlen(dev) > IFNAMSIZ) { 46 if (strlen(dev) > IFNAMSIZ) {
@@ -286,189 +287,4 @@ uint32_t arp_assign(const char *dev, Bridge *br) {
286 return ip; 287 return ip;
287} 288}
288 289
289// scan interface (--scan option)
290void arp_scan(const char *dev, uint32_t ifip, uint32_t ifmask) {
291 assert(dev);
292 assert(ifip);
293
294// printf("Scanning interface %s (%d.%d.%d.%d/%d)\n",
295// dev, PRINT_IP(ifip & ifmask), mask2bits(ifmask));
296
297 if (strlen(dev) > IFNAMSIZ) {
298 fprintf(stderr, "Error: invalid network device name %s\n", dev);
299 exit(1);
300 }
301
302 // find interface mac address
303 int sock;
304 if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
305 errExit("socket");
306 struct ifreq ifr;
307 memset(&ifr, 0, sizeof (ifr));
308 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
309 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
310 errExit("ioctl");
311 close(sock);
312 uint8_t mac[6];
313 memcpy (mac, ifr.ifr_hwaddr.sa_data, 6);
314
315 // open layer2 socket
316 if ((sock = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0)
317 errExit("socket");
318
319 // try all possible ip addresses in ascending order
320 uint32_t range = ~ifmask + 1; // the number of potential addresses
321 // this software is not supported for /31 networks
322 if (range < 4) {
323 fprintf(stderr, "Warning: this option is not supported for /31 networks\n");
324 close(sock);
325 return;
326 }
327
328 uint32_t dest = (ifip & ifmask) + 1;
329 uint32_t last = dest + range - 1;
330 uint32_t src = htonl(ifip);
331
332 // wait not more than one second for an answer
333 int header_printed = 0;
334 uint32_t last_ip = 0;
335 struct timeval ts;
336 ts.tv_sec = 2; // 2 seconds receive timeout
337 ts.tv_usec = 0;
338
339 while (1) {
340 fd_set rfds;
341 FD_ZERO(&rfds);
342 FD_SET(sock, &rfds);
343 fd_set wfds;
344 FD_ZERO(&wfds);
345 FD_SET(sock, &wfds);
346 int maxfd = sock;
347
348 uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
349 memset(frame, 0, ETH_FRAME_LEN);
350
351 int nready;
352 if (dest < last)
353 nready = select(maxfd + 1, &rfds, &wfds, (fd_set *) 0, NULL);
354 else
355 nready = select(maxfd + 1, &rfds, (fd_set *) 0, (fd_set *) 0, &ts);
356
357 if (nready < 0)
358 errExit("select");
359
360 if (nready == 0) { // timeout
361 break;
362 }
363
364 if (FD_ISSET(sock, &wfds) && dest < last) {
365 // configure layer2 socket address information
366 struct sockaddr_ll addr;
367 memset(&addr, 0, sizeof(addr));
368 if ((addr.sll_ifindex = if_nametoindex(dev)) == 0)
369 errExit("if_nametoindex");
370 addr.sll_family = AF_PACKET;
371 memcpy (addr.sll_addr, mac, 6);
372 addr.sll_halen = htons(6);
373
374 // build the arp packet header
375 ArpHdr hdr;
376 memset(&hdr, 0, sizeof(hdr));
377 hdr.htype = htons(1);
378 hdr.ptype = htons(ETH_P_IP);
379 hdr.hlen = 6;
380 hdr.plen = 4;
381 hdr.opcode = htons(1); //ARPOP_REQUEST
382 memcpy(hdr.sender_mac, mac, 6);
383 memcpy(hdr.sender_ip, (uint8_t *)&src, 4);
384 uint32_t dst = htonl(dest);
385 memcpy(hdr.target_ip, (uint8_t *)&dst, 4);
386
387 // build ethernet frame
388 uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
389 memset(frame, 0, sizeof(frame));
390 frame[0] = frame[1] = frame[2] = frame[3] = frame[4] = frame[5] = 0xff;
391 memcpy(frame + 6, mac, 6);
392 frame[12] = ETH_P_ARP / 256;
393 frame[13] = ETH_P_ARP % 256;
394 memcpy (frame + 14, &hdr, sizeof(hdr));
395
396 // send packet
397 int len;
398 if ((len = sendto (sock, frame, 14 + sizeof(ArpHdr), 0, (struct sockaddr *) &addr, sizeof (addr))) <= 0)
399 errExit("send");
400//printf("send %d bytes to %d.%d.%d.%d\n", len, PRINT_IP(dest));
401 fflush(0);
402 dest++;
403 }
404
405 if (FD_ISSET(sock, &rfds)) {
406 // read the incoming packet
407 int len = recvfrom(sock, frame, ETH_FRAME_LEN, 0, NULL, NULL);
408 if (len < 0) {
409 perror("recvfrom");
410 }
411
412 // parse the incoming packet
413 if ((unsigned int) len < 14 + sizeof(ArpHdr))
414 continue;
415
416 // look only at ARP packets
417 if (frame[12] != (ETH_P_ARP / 256) || frame[13] != (ETH_P_ARP % 256))
418 continue;
419
420 ArpHdr hdr;
421 memcpy(&hdr, frame + 14, sizeof(ArpHdr));
422
423 if (hdr.opcode == htons(2)) {
424 // check my mac and my address
425 if (memcmp(mac, hdr.target_mac, 6) != 0)
426 continue;
427 uint32_t ip;
428 memcpy(&ip, hdr.target_ip, 4);
429 if (ip != src)
430 continue;
431 memcpy(&ip, hdr.sender_ip, 4);
432 ip = ntohl(ip);
433
434 if (ip == last_ip) // filter duplicates
435 continue;
436 last_ip = ip;
437
438 // printing
439 if (header_printed == 0) {
440 printf(" Network scan:\n");
441
442 // print parent interface
443 if (cfg.bridge0.configured && cfg.bridge0.ip && cfg.bridge0.macvlan &&
444 (cfg.bridge0.ip & cfg.bridge0.mask) == (ifip & cfg.bridge0.mask))
445 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
446 PRINT_MAC(cfg.bridge0.mac), PRINT_IP(cfg.bridge0.ip));
447
448 if (cfg.bridge1.configured && cfg.bridge1.ip && cfg.bridge1.macvlan &&
449 (cfg.bridge1.ip & cfg.bridge1.mask) == (ifip & cfg.bridge1.mask))
450 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
451 PRINT_MAC(cfg.bridge1.mac), PRINT_IP(cfg.bridge1.ip));
452
453 if (cfg.bridge2.configured && cfg.bridge2.ip && cfg.bridge2.macvlan &&
454 (cfg.bridge2.ip & cfg.bridge2.mask) == (ifip & cfg.bridge2.mask))
455 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
456 PRINT_MAC(cfg.bridge2.mac), PRINT_IP(cfg.bridge2.ip));
457
458 if (cfg.bridge3.configured && cfg.bridge3.ip && cfg.bridge3.macvlan &&
459 (cfg.bridge3.ip & cfg.bridge3.mask) == (ifip & cfg.bridge3.mask))
460 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
461 PRINT_MAC(cfg.bridge3.mac), PRINT_IP(cfg.bridge3.ip));
462
463 header_printed = 1;
464 }
465 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
466 PRINT_MAC(hdr.sender_mac), PRINT_IP(ip));
467 }
468 }
469 }
470
471 close(sock);
472}
473
474 290
diff --git a/src/firejail/errno.c b/src/firejail/errno.c
index c493dfa09..8215c99a1 100644
--- a/src/firejail/errno.c
+++ b/src/firejail/errno.c
@@ -17,7 +17,6 @@
17 * with this program; if not, write to the Free Software Foundation, Inc., 17 * with this program; if not, write to the Free Software Foundation, Inc.,
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
21#ifdef HAVE_SECCOMP 20#ifdef HAVE_SECCOMP
22#include "firejail.h" 21#include "firejail.h"
23#include <errno.h> 22#include <errno.h>
@@ -205,16 +204,4 @@ char *errno_find_nr(int nr) {
205 204
206 return "unknown"; 205 return "unknown";
207} 206}
208
209void errno_print(void) {
210 EUID_ASSERT();
211
212 int i;
213 int elems = sizeof(errnolist) / sizeof(errnolist[0]);
214 for (i = 0; i < elems; i++) {
215 printf("%d\t- %s\n", errnolist[i].nr, errnolist[i].name);
216 }
217 printf("\n");
218}
219
220#endif // HAVE_SECCOMP 207#endif // HAVE_SECCOMP
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index f4d468394..cf540ff91 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -28,6 +28,7 @@
28// filesystem 28// filesystem
29#define RUN_FIREJAIL_BASEDIR "/run" 29#define RUN_FIREJAIL_BASEDIR "/run"
30#define RUN_FIREJAIL_DIR "/run/firejail" 30#define RUN_FIREJAIL_DIR "/run/firejail"
31#define RUN_FIREJAIL_APPIMAGE_DIR "/run/firejail/appimage"
31#define RUN_FIREJAIL_NAME_DIR "/run/firejail/name" 32#define RUN_FIREJAIL_NAME_DIR "/run/firejail/name"
32#define RUN_FIREJAIL_X11_DIR "/run/firejail/x11" 33#define RUN_FIREJAIL_X11_DIR "/run/firejail/x11"
33#define RUN_FIREJAIL_NETWORK_DIR "/run/firejail/network" 34#define RUN_FIREJAIL_NETWORK_DIR "/run/firejail/network"
@@ -36,7 +37,6 @@
36#define RUN_RO_DIR "/run/firejail/firejail.ro.dir" 37#define RUN_RO_DIR "/run/firejail/firejail.ro.dir"
37#define RUN_RO_FILE "/run/firejail/firejail.ro.file" 38#define RUN_RO_FILE "/run/firejail/firejail.ro.file"
38#define RUN_MNT_DIR "/run/firejail/mnt" // a tmpfs is mounted on this directory before any of the files below are created 39#define RUN_MNT_DIR "/run/firejail/mnt" // a tmpfs is mounted on this directory before any of the files below are created
39#define RUN_SECCOMP_CFG "/run/firejail/mnt/seccomp"
40#define RUN_CGROUP_CFG "/run/firejail/mnt/cgroup" 40#define RUN_CGROUP_CFG "/run/firejail/mnt/cgroup"
41#define RUN_CPU_CFG "/run/firejail/mnt/cpu" 41#define RUN_CPU_CFG "/run/firejail/mnt/cpu"
42#define RUN_GROUPS_CFG "/run/firejail/mnt/groups" 42#define RUN_GROUPS_CFG "/run/firejail/mnt/groups"
@@ -47,6 +47,12 @@
47#define RUN_BIN_DIR "/run/firejail/mnt/bin" 47#define RUN_BIN_DIR "/run/firejail/mnt/bin"
48#define RUN_PULSE_DIR "/run/firejail/mnt/pulse" 48#define RUN_PULSE_DIR "/run/firejail/mnt/pulse"
49 49
50#define RUN_SECCOMP_CFG "/run/firejail/mnt/seccomp" // configured filter
51#define RUN_SECCOMP_PROTOCOL "/run/firejail/mnt/seccomp.protocol" // protocol filter
52#define RUN_SECCOMP_AMD64 "/run/firejail/mnt/seccomp.amd64" // amd64 filter installed on i386 architectures
53#define RUN_SECCOMP_I386 "/run/firejail/mnt/seccomp.i386" // i386 filter installed on amd64 architectures
54
55
50#define RUN_DEV_DIR "/run/firejail/mnt/dev" 56#define RUN_DEV_DIR "/run/firejail/mnt/dev"
51#define RUN_DEVLOG_FILE "/run/firejail/mnt/devlog" 57#define RUN_DEVLOG_FILE "/run/firejail/mnt/devlog"
52 58
@@ -59,6 +65,7 @@
59#define RUN_WHITELIST_VAR_DIR "/run/firejail/mnt/orig-var" 65#define RUN_WHITELIST_VAR_DIR "/run/firejail/mnt/orig-var"
60#define RUN_WHITELIST_DEV_DIR "/run/firejail/mnt/orig-dev" 66#define RUN_WHITELIST_DEV_DIR "/run/firejail/mnt/orig-dev"
61#define RUN_WHITELIST_OPT_DIR "/run/firejail/mnt/orig-opt" 67#define RUN_WHITELIST_OPT_DIR "/run/firejail/mnt/orig-opt"
68#define RUN_WHITELIST_SRV_DIR "/run/firejail/mnt/orig-srv"
62 69
63#define RUN_XAUTHORITY_FILE "/run/firejail/mnt/.Xauthority" 70#define RUN_XAUTHORITY_FILE "/run/firejail/mnt/.Xauthority"
64#define RUN_XAUTHORITY_SEC_FILE "/run/firejail/mnt/sec.Xauthority" 71#define RUN_XAUTHORITY_SEC_FILE "/run/firejail/mnt/sec.Xauthority"
@@ -72,6 +79,8 @@
72#define RUN_GROUP_FILE "/run/firejail/mnt/group" 79#define RUN_GROUP_FILE "/run/firejail/mnt/group"
73#define RUN_FSLOGGER_FILE "/run/firejail/mnt/fslogger" 80#define RUN_FSLOGGER_FILE "/run/firejail/mnt/fslogger"
74 81
82
83
75// profiles 84// profiles
76#define DEFAULT_USER_PROFILE "default" 85#define DEFAULT_USER_PROFILE "default"
77#define DEFAULT_ROOT_PROFILE "server" 86#define DEFAULT_ROOT_PROFILE "server"
@@ -172,6 +181,7 @@ typedef struct profile_entry_t {
172 unsigned var_dir:1; // whitelist in /var directory 181 unsigned var_dir:1; // whitelist in /var directory
173 unsigned dev_dir:1; // whitelist in /dev directory 182 unsigned dev_dir:1; // whitelist in /dev directory
174 unsigned opt_dir:1; // whitelist in /opt directory 183 unsigned opt_dir:1; // whitelist in /opt directory
184 unsigned srv_dir:1; // whitelist in /srv directory
175}ProfileEntry; 185}ProfileEntry;
176 186
177typedef struct config_t { 187typedef struct config_t {
@@ -358,21 +368,19 @@ void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask, int mtu);
358void net_if_ip6(const char *ifname, const char *addr6); 368void net_if_ip6(const char *ifname, const char *addr6);
359int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6], int *mtu); 369int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6], int *mtu);
360int net_add_route(uint32_t dest, uint32_t mask, uint32_t gw); 370int net_add_route(uint32_t dest, uint32_t mask, uint32_t gw);
361void net_ifprint(void);
362void net_bridge_add_interface(const char *bridge, const char *dev);
363uint32_t network_get_defaultgw(void); 371uint32_t network_get_defaultgw(void);
364int net_config_mac(const char *ifname, const unsigned char mac[6]); 372int net_config_mac(const char *ifname, const unsigned char mac[6]);
365int net_get_mac(const char *ifname, unsigned char mac[6]); 373int net_get_mac(const char *ifname, unsigned char mac[6]);
374void net_config_interface(const char *dev, uint32_t ip, uint32_t mask, int mtu);
375
376// preproc.c
377void preproc_build_firejail_dir(void);
378void preproc_mount_mnt_dir(void);
379void preproc_build_cp_command(void);
380void preproc_delete_cp_command(void) ;
381void preproc_remount_mnt_dir(void);
366 382
367// fs.c 383// fs.c
368// build /run/firejail directory
369void fs_build_firejail_dir(void);
370// build /run/firejail/mnt directory
371void fs_build_mnt_dir(void);
372// grab a copy of cp command
373void fs_build_cp_command(void);
374// delete the temporary cp command
375void fs_delete_cp_command(void) ;
376// blacklist files or directoies by mounting empty files on top of them 384// blacklist files or directoies by mounting empty files on top of them
377void fs_blacklist(void); 385void fs_blacklist(void);
378// remount a directory read-only 386// remount a directory read-only
@@ -389,7 +397,6 @@ void fs_overlayfs(void);
389// chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf 397// chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf
390void fs_chroot(const char *rootdir); 398void fs_chroot(const char *rootdir);
391int fs_check_chroot_dir(const char *rootdir); 399int fs_check_chroot_dir(const char *rootdir);
392void fs_private_tmp(void);
393 400
394// profile.c 401// profile.c
395// find and read the profile specified by name from dir directory 402// find and read the profile specified by name from dir directory
@@ -426,13 +433,6 @@ int restricted_shell(const char *user);
426int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr); 433int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr);
427// assign an IP address using arp scanning 434// assign an IP address using arp scanning
428uint32_t arp_assign(const char *dev, Bridge *br); 435uint32_t arp_assign(const char *dev, Bridge *br);
429// scan interface (--scan option)
430void arp_scan(const char *dev, uint32_t srcaddr, uint32_t srcmask);
431
432// veth.c
433int net_create_veth(const char *dev, const char *nsdev, unsigned pid);
434int net_create_macvlan(const char *dev, const char *parent, unsigned pid);
435int net_move_interface(const char *dev, unsigned pid);
436 436
437// util.c 437// util.c
438void drop_privs(int nogroups); 438void drop_privs(int nogroups);
@@ -457,10 +457,11 @@ char *expand_home(const char *path, const char* homedir);
457const char *gnu_basename(const char *path); 457const char *gnu_basename(const char *path);
458uid_t pid_get_uid(pid_t pid); 458uid_t pid_get_uid(pid_t pid);
459void invalid_filename(const char *fname); 459void invalid_filename(const char *fname);
460uid_t get_tty_gid(void); 460uid_t get_group_id(const char *group);
461uid_t get_audio_gid(void);
462int remove_directory(const char *path); 461int remove_directory(const char *path);
463void flush_stdin(void); 462void flush_stdin(void);
463void create_empty_dir_as_root(const char *dir, mode_t mode);
464void create_empty_file_as_root(const char *dir, mode_t mode);
464 465
465// fs_var.c 466// fs_var.c
466void fs_var_log(void); // mounting /var/log 467void fs_var_log(void); // mounting /var/log
@@ -495,12 +496,14 @@ void fs_private_home_list(void);
495 496
496 497
497// seccomp.c 498// seccomp.c
499int seccomp_load(const char *fname);
500void seccomp_filter_32(void);
501void seccomp_filter_64(void);
498int seccomp_filter_drop(int enforce_seccomp); 502int seccomp_filter_drop(int enforce_seccomp);
499int seccomp_filter_keep(void); 503int seccomp_filter_keep(void);
500void seccomp_set(void); 504int seccomp_filter_errno(void);
501void seccomp_print_filter_name(const char *name); 505void seccomp_print_filter_name(const char *name);
502void seccomp_print_filter(pid_t pid); 506void seccomp_print_filter(pid_t pid);
503int seccomp_filter_errno(void);
504 507
505// caps.c 508// caps.c
506int caps_default_filter(void); 509int caps_default_filter(void);
@@ -517,8 +520,6 @@ void caps_print_filter_name(const char *name);
517const char *syscall_find_nr(int nr); 520const char *syscall_find_nr(int nr);
518// return -1 if error, 0 if no error 521// return -1 if error, 0 if no error
519int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg), int arg); 522int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg), int arg);
520// print all available syscallsseccomp
521void syscall_print(void);
522 523
523// fs_trace.c 524// fs_trace.c
524void fs_trace_preload(void); 525void fs_trace_preload(void);
@@ -597,13 +598,10 @@ void fs_check_bin_list(void);
597void fs_private_bin_list(void); 598void fs_private_bin_list(void);
598 599
599// protocol.c 600// protocol.c
600void protocol_list();
601void protocol_print_filter_name(const char *name);
602void protocol_print_filter(pid_t pid);
603void protocol_store(const char *prlist);
604void protocol_filter(void);
605void protocol_filter_save(void); 601void protocol_filter_save(void);
606void protocol_filter_load(const char *fname); 602void protocol_filter_load(const char *fname);
603void protocol_print_filter_name(const char *name);
604void protocol_print_filter(pid_t pid);
607 605
608// restrict_users.c 606// restrict_users.c
609void restrict_users(void); 607void restrict_users(void);
@@ -672,14 +670,33 @@ extern char *xephyr_extra_params;
672extern char *netfilter_default; 670extern char *netfilter_default;
673int checkcfg(int val); 671int checkcfg(int val);
674void print_compiletime_support(void); 672void print_compiletime_support(void);
673void x11_xorg(void);
675 674
676// appimage.c 675// appimage.c
677void appimage_set(const char *appimage_path); 676void appimage_set(const char *appimage_path);
678void appimage_clear(void); 677void appimage_clear(void);
679const char *appimage_getdir(void); 678const char *appimage_getdir(void);
680 679
680// appimage_size.c
681long unsigned int appimage2_size(const char *fname);
682
681// cmdline.c 683// cmdline.c
682void build_cmdline(char **command_line, char **window_title, int argc, char **argv, int index); 684void build_cmdline(char **command_line, char **window_title, int argc, char **argv, int index);
683 685
686// sbox.c
687// programs
688#define PATH_FNET (LIBDIR "/firejail/fnet")
689#define PATH_FIREMON (PREFIX "/bin/firemon")
690#define PATH_FSECCOMP (LIBDIR "/firejail/fseccomp")
691// bitmapped filters for sbox_run
692#define SBOX_ROOT (1 << 0)
693#define SBOX_USER (1 << 1)
694#define SBOX_SECCOMP (1 << 2)
695#define SBOX_CAPS_NONE (1 << 3) // drop all capabilities
696#define SBOX_CAPS_NETWORK (1 << 4) // caps filter for programs running network programs
697// run sbox
698int sbox_run(unsigned filter, int num, ...);
699
700
684#endif 701#endif
685 702
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index b40f8a3fa..dbd7eced7 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -29,149 +29,7 @@
29 29
30static void fs_rdwr(const char *dir); 30static void fs_rdwr(const char *dir);
31 31
32static void create_dir_as_root(const char *dir, mode_t mode) {
33 assert(dir);
34 if (arg_debug)
35 printf("Creating %s directory\n", dir);
36
37 if (mkdir(dir, mode) == -1)
38 errExit("mkdir");
39 if (chmod(dir, mode) == -1)
40 errExit("chmod");
41
42 ASSERT_PERMS(dir, 0, 0, mode);
43}
44
45static void create_empty_dir(void) {
46 struct stat s;
47
48 if (stat(RUN_RO_DIR, &s)) {
49 /* coverity[toctou] */
50 if (mkdir(RUN_RO_DIR, S_IRUSR | S_IXUSR) == -1)
51 errExit("mkdir");
52 if (chmod(RUN_RO_DIR, S_IRUSR | S_IXUSR) == -1)
53 errExit("chmod");
54 ASSERT_PERMS(RUN_RO_DIR, 0, 0, S_IRUSR | S_IXUSR);
55 }
56}
57 32
58static void create_empty_file(void) {
59 struct stat s;
60
61 if (stat(RUN_RO_FILE, &s)) {
62 /* coverity[toctou] */
63 FILE *fp = fopen(RUN_RO_FILE, "w");
64 if (!fp)
65 errExit("fopen");
66
67 SET_PERMS_STREAM(fp, 0, 0, S_IRUSR);
68 fclose(fp);
69 }
70}
71
72// build /run/firejail directory
73void fs_build_firejail_dir(void) {
74 struct stat s;
75
76 // CentOS 6 doesn't have /run directory
77 if (stat(RUN_FIREJAIL_BASEDIR, &s)) {
78 create_dir_as_root(RUN_FIREJAIL_BASEDIR, 0755);
79 }
80 else { // check /tmp/firejail directory belongs to root end exit if doesn't!
81 if (s.st_uid != 0 || s.st_gid != 0) {
82 fprintf(stderr, "Error: non-root %s directory, exiting...\n", RUN_FIREJAIL_DIR);
83 exit(1);
84 }
85 }
86
87 if (stat(RUN_FIREJAIL_DIR, &s)) {
88 create_dir_as_root(RUN_FIREJAIL_DIR, 0755);
89 }
90
91 if (stat(RUN_FIREJAIL_NETWORK_DIR, &s)) {
92 create_dir_as_root(RUN_FIREJAIL_NETWORK_DIR, 0755);
93 }
94
95 if (stat(RUN_FIREJAIL_BANDWIDTH_DIR, &s)) {
96 create_dir_as_root(RUN_FIREJAIL_BANDWIDTH_DIR, 0755);
97 }
98
99 if (stat(RUN_FIREJAIL_NAME_DIR, &s)) {
100 create_dir_as_root(RUN_FIREJAIL_NAME_DIR, 0755);
101 }
102
103 if (stat(RUN_FIREJAIL_X11_DIR, &s)) {
104 create_dir_as_root(RUN_FIREJAIL_X11_DIR, 0755);
105 }
106
107 create_empty_dir();
108 create_empty_file();
109}
110
111
112// build /tmp/firejail/mnt directory
113static int tmpfs_mounted = 0;
114#ifdef HAVE_CHROOT
115static void fs_build_remount_mnt_dir(void) {
116 tmpfs_mounted = 0;
117 fs_build_mnt_dir();
118}
119#endif
120
121void fs_build_mnt_dir(void) {
122 struct stat s;
123 fs_build_firejail_dir();
124
125 // create /run/firejail/mnt directory
126 if (stat(RUN_MNT_DIR, &s)) {
127 create_dir_as_root(RUN_MNT_DIR, 0755);
128 }
129
130 // ... and mount tmpfs on top of it
131 if (!tmpfs_mounted) {
132 // mount tmpfs on top of /run/firejail/mnt
133 if (arg_debug)
134 printf("Mounting tmpfs on %s directory\n", RUN_MNT_DIR);
135 if (mount("tmpfs", RUN_MNT_DIR, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
136 errExit("mounting /tmp/firejail/mnt");
137 tmpfs_mounted = 1;
138 fs_logger2("tmpfs", RUN_MNT_DIR);
139 }
140}
141
142// grab a copy of cp command
143void fs_build_cp_command(void) {
144 struct stat s;
145 fs_build_mnt_dir();
146 if (stat(RUN_CP_COMMAND, &s)) {
147 char* fname = realpath("/bin/cp", NULL);
148 if (fname == NULL) {
149 fprintf(stderr, "Error: /bin/cp not found\n");
150 exit(1);
151 }
152 if (stat(fname, &s)) {
153 fprintf(stderr, "Error: /bin/cp not found\n");
154 exit(1);
155 }
156 if (is_link(fname)) {
157 fprintf(stderr, "Error: invalid /bin/cp file\n");
158 exit(1);
159 }
160 int rv = copy_file(fname, RUN_CP_COMMAND, 0, 0, 0755);
161 if (rv) {
162 fprintf(stderr, "Error: cannot access /bin/cp\n");
163 exit(1);
164 }
165 ASSERT_PERMS(RUN_CP_COMMAND, 0, 0, 0755);
166
167 free(fname);
168 }
169}
170
171// delete the temporary cp command
172void fs_delete_cp_command(void) {
173 unlink(RUN_CP_COMMAND);
174}
175 33
176//*********************************************** 34//***********************************************
177// process profile file 35// process profile file
@@ -197,9 +55,6 @@ static void disable_file(OPERATION op, const char *filename) {
197 assert(op <OPERATION_MAX); 55 assert(op <OPERATION_MAX);
198 last_disable = UNSUCCESSFUL; 56 last_disable = UNSUCCESSFUL;
199 57
200 // rebuild /run/firejail directory in case tmpfs was mounted on top of /run
201 fs_build_firejail_dir();
202
203 // Resolve all symlinks 58 // Resolve all symlinks
204 char* fname = realpath(filename, NULL); 59 char* fname = realpath(filename, NULL);
205 if (fname == NULL && errno != EACCES) { 60 if (fname == NULL && errno != EACCES) {
@@ -251,9 +106,10 @@ static void disable_file(OPERATION op, const char *filename) {
251 // some distros put all executables under /usr/bin and make /bin a symbolic link 106 // some distros put all executables under /usr/bin and make /bin a symbolic link
252 if ((strcmp(fname, "/bin") == 0 || strcmp(fname, "/usr/bin") == 0) && 107 if ((strcmp(fname, "/bin") == 0 || strcmp(fname, "/usr/bin") == 0) &&
253 is_link(filename) && 108 is_link(filename) &&
254 S_ISDIR(s.st_mode)) 109 S_ISDIR(s.st_mode)) {
255 fprintf(stderr, "Warning: %s directory link was not blacklisted\n", filename); 110 if (!arg_quiet)
256 111 fprintf(stderr, "Warning: %s directory link was not blacklisted\n", filename);
112 }
257 else { 113 else {
258 if (arg_debug) 114 if (arg_debug)
259 printf("Disable %s\n", fname); 115 printf("Disable %s\n", fname);
@@ -644,7 +500,11 @@ void fs_proc_sys_dev_boot(void) {
644 500
645 disable_file(BLACKLIST_FILE, "/sys/firmware"); 501 disable_file(BLACKLIST_FILE, "/sys/firmware");
646 disable_file(BLACKLIST_FILE, "/sys/hypervisor"); 502 disable_file(BLACKLIST_FILE, "/sys/hypervisor");
647 disable_file(BLACKLIST_FILE, "/sys/fs"); 503 { // allow user access to /sys/fs if "--noblacklist=/sys/fs" is present on the command line
504 EUID_USER();
505 profile_add("blacklist /sys/fs");
506 EUID_ROOT();
507 }
648 disable_file(BLACKLIST_FILE, "/sys/module"); 508 disable_file(BLACKLIST_FILE, "/sys/module");
649 disable_file(BLACKLIST_FILE, "/sys/power"); 509 disable_file(BLACKLIST_FILE, "/sys/power");
650 disable_file(BLACKLIST_FILE, "/sys/kernel/debug"); 510 disable_file(BLACKLIST_FILE, "/sys/kernel/debug");
@@ -745,8 +605,8 @@ void fs_basic_fs(void) {
745 fs_rdonly("/usr"); 605 fs_rdonly("/usr");
746 606
747 // update /var directory in order to support multiple sandboxes running on the same root directory 607 // update /var directory in order to support multiple sandboxes running on the same root directory
748 if (!arg_private_dev) 608// if (!arg_private_dev)
749 fs_dev_shm(); 609// fs_dev_shm();
750 fs_var_lock(); 610 fs_var_lock();
751 fs_var_tmp(); 611 fs_var_tmp();
752 fs_var_log(); 612 fs_var_log();
@@ -859,9 +719,6 @@ void fs_overlayfs(void) {
859 if (major == 3 && minor < 18) 719 if (major == 3 && minor < 18)
860 oldkernel = 1; 720 oldkernel = 1;
861 721
862 // build overlay directories
863 fs_build_mnt_dir();
864
865 char *oroot; 722 char *oroot;
866 if(asprintf(&oroot, "%s/oroot", RUN_MNT_DIR) == -1) 723 if(asprintf(&oroot, "%s/oroot", RUN_MNT_DIR) == -1)
867 errExit("asprintf"); 724 errExit("asprintf");
@@ -1052,8 +909,8 @@ void fs_overlayfs(void) {
1052 errExit("chroot"); 909 errExit("chroot");
1053 910
1054 // update /var directory in order to support multiple sandboxes running on the same root directory 911 // update /var directory in order to support multiple sandboxes running on the same root directory
1055 if (!arg_private_dev) 912// if (!arg_private_dev)
1056 fs_dev_shm(); 913// fs_dev_shm();
1057 fs_var_lock(); 914 fs_var_lock();
1058 fs_var_tmp(); 915 fs_var_tmp();
1059 fs_var_log(); 916 fs_var_log();
@@ -1185,17 +1042,33 @@ void fs_chroot(const char *rootdir) {
1185 free(newx11); 1042 free(newx11);
1186 } 1043 }
1187 1044
1188 // some older distros don't have a /run directory 1045 // create /run/firejail directory in chroot
1189 // create one by default
1190 // no exit on error, let the user deal with any problems
1191 char *rundir; 1046 char *rundir;
1192 if (asprintf(&rundir, "%s/run", rootdir) == -1) 1047 if (asprintf(&rundir, "%s/run", rootdir) == -1)
1193 errExit("asprintf"); 1048 errExit("asprintf");
1194 if (!is_dir(rundir)) { 1049 create_empty_dir_as_root(rundir, 0755);
1195 int rv = mkdir(rundir, 0755); 1050 free(rundir);
1196 (void) rv; 1051 if (asprintf(&rundir, "%s/run/firejail", rootdir) == -1)
1197 rv = chown(rundir, 0, 0); 1052 errExit("asprintf");
1198 (void) rv; 1053 create_empty_dir_as_root(rundir, 0755);
1054 free(rundir);
1055
1056 // create /run/firejail/mnt directory in chroot and mount a tmpfs
1057 if (asprintf(&rundir, "%s/run/firejail/mnt", rootdir) == -1)
1058 errExit("asprintf");
1059 create_empty_dir_as_root(rundir, 0755);
1060 if (mount("tmpfs", rundir, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
1061 errExit("mounting /run/firejail/mnt");
1062 fs_logger2("tmpfs", RUN_MNT_DIR);
1063 free(rundir);
1064
1065 // retrieve seccomp.protocol
1066 struct stat s;
1067 if (stat(RUN_SECCOMP_PROTOCOL, &s) == 0) {
1068 if (asprintf(&rundir, "%s%s", rootdir, RUN_SECCOMP_PROTOCOL) == -1)
1069 errExit("asprintf");
1070 copy_file(RUN_SECCOMP_PROTOCOL, rundir, getuid(), getgid(), 0644);
1071 free(rundir);
1199 } 1072 }
1200 1073
1201 // copy /etc/resolv.conf in chroot directory 1074 // copy /etc/resolv.conf in chroot directory
@@ -1219,13 +1092,14 @@ void fs_chroot(const char *rootdir) {
1219 printf("Chrooting into %s\n", rootdir); 1092 printf("Chrooting into %s\n", rootdir);
1220 if (chroot(rootdir) < 0) 1093 if (chroot(rootdir) < 0)
1221 errExit("chroot"); 1094 errExit("chroot");
1222 // mount a new tmpfs in /run/firejail/mnt - the old one was lost in chroot 1095
1223 fs_build_remount_mnt_dir(); 1096 // create all other /run/firejail files and directories
1097 preproc_build_firejail_dir();
1224 1098
1225 if (checkcfg(CFG_CHROOT_DESKTOP)) { 1099 if (checkcfg(CFG_CHROOT_DESKTOP)) {
1226 // update /var directory in order to support multiple sandboxes running on the same root directory 1100 // update /var directory in order to support multiple sandboxes running on the same root directory
1227 if (!arg_private_dev) 1101// if (!arg_private_dev)
1228 fs_dev_shm(); 1102// fs_dev_shm();
1229 fs_var_lock(); 1103 fs_var_lock();
1230 fs_var_tmp(); 1104 fs_var_tmp();
1231 fs_var_log(); 1105 fs_var_log();
@@ -1245,12 +1119,4 @@ void fs_chroot(const char *rootdir) {
1245} 1119}
1246#endif 1120#endif
1247 1121
1248void fs_private_tmp(void) {
1249 // mount tmpfs on top of /run/firejail/mnt
1250 if (arg_debug)
1251 printf("Mounting tmpfs on /tmp directory\n");
1252 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=1777,gid=0") < 0)
1253 errExit("mounting /tmp/firejail/mnt");
1254 fs_logger2("tmpfs", "/tmp");
1255}
1256 1122
diff --git a/src/firejail/fs_bin.c b/src/firejail/fs_bin.c
index 40539305f..f59944735 100644
--- a/src/firejail/fs_bin.c
+++ b/src/firejail/fs_bin.c
@@ -192,6 +192,8 @@ static void duplicate(char *fname) {
192 if (asprintf(&f, "%s/%s", RUN_BIN_DIR, fname) == -1) 192 if (asprintf(&f, "%s/%s", RUN_BIN_DIR, fname) == -1)
193 errExit("asprintf"); 193 errExit("asprintf");
194 execlp(RUN_CP_COMMAND, RUN_CP_COMMAND, "-a", actual_path, f, NULL); 194 execlp(RUN_CP_COMMAND, RUN_CP_COMMAND, "-a", actual_path, f, NULL);
195 perror("execlp");
196 _exit(1);
195 } 197 }
196 // wait for the child to finish 198 // wait for the child to finish
197 waitpid(child, NULL, 0); 199 waitpid(child, NULL, 0);
@@ -208,8 +210,7 @@ void fs_private_bin_list(void) {
208 char *private_list = cfg.bin_private_keep; 210 char *private_list = cfg.bin_private_keep;
209 assert(private_list); 211 assert(private_list);
210 212
211 // create /tmp/firejail/mnt/bin directory 213 // create /run/firejail/mnt/bin directory
212 fs_build_mnt_dir();
213 if (mkdir(RUN_BIN_DIR, 0755) == -1) 214 if (mkdir(RUN_BIN_DIR, 0755) == -1)
214 errExit("mkdir"); 215 errExit("mkdir");
215 if (chmod(RUN_BIN_DIR, 0755) == -1) 216 if (chmod(RUN_BIN_DIR, 0755) == -1)
@@ -245,7 +246,7 @@ void fs_private_bin_list(void) {
245 duplicate(ptr); 246 duplicate(ptr);
246 free(dlist); 247 free(dlist);
247 fs_logger_print(); 248 fs_logger_print();
248 exit(0); 249 _exit(0);
249 } 250 }
250 // wait for the child to finish 251 // wait for the child to finish
251 waitpid(child, NULL, 0); 252 waitpid(child, NULL, 0);
diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c
index daf0afd9e..ef5d67b55 100644
--- a/src/firejail/fs_dev.c
+++ b/src/firejail/fs_dev.c
@@ -129,8 +129,6 @@ void fs_private_dev(void){
129 printf("Mounting tmpfs on /dev\n"); 129 printf("Mounting tmpfs on /dev\n");
130 130
131 // create DRI_DIR 131 // create DRI_DIR
132 fs_build_mnt_dir();
133
134 // keep a copy of dev directory 132 // keep a copy of dev directory
135 if (mkdir(RUN_DEV_DIR, 0755) == -1) 133 if (mkdir(RUN_DEV_DIR, 0755) == -1)
136 errExit("mkdir"); 134 errExit("mkdir");
@@ -225,7 +223,7 @@ void fs_private_dev(void){
225 223
226 224
227 // mount /dev/pts 225 // mount /dev/pts
228 gid_t ttygid = get_tty_gid(); 226 gid_t ttygid = get_group_id("tty");
229 char *data; 227 char *data;
230 if (asprintf(&data, "newinstance,gid=%d,mode=620,ptmxmode=0666", (int) ttygid) == -1) 228 if (asprintf(&data, "newinstance,gid=%d,mode=620,ptmxmode=0666", (int) ttygid) == -1)
231 errExit("asprintf"); 229 errExit("asprintf");
@@ -244,6 +242,7 @@ void fs_private_dev(void){
244} 242}
245 243
246 244
245#if 0
247void fs_dev_shm(void) { 246void fs_dev_shm(void) {
248 uid_t uid = getuid(); // set a new shm only if we started as root 247 uid_t uid = getuid(); // set a new shm only if we started as root
249 if (uid) 248 if (uid)
@@ -282,6 +281,7 @@ void fs_dev_shm(void) {
282 281
283 } 282 }
284} 283}
284#endif
285 285
286static void disable_file_or_dir(const char *fname) { 286static void disable_file_or_dir(const char *fname) {
287 if (arg_debug) 287 if (arg_debug)
diff --git a/src/firejail/fs_etc.c b/src/firejail/fs_etc.c
index e860bc173..b86d5eb74 100644
--- a/src/firejail/fs_etc.c
+++ b/src/firejail/fs_etc.c
@@ -106,6 +106,8 @@ static void duplicate(char *fname) {
106 if (asprintf(&f, "/etc/%s", fname) == -1) 106 if (asprintf(&f, "/etc/%s", fname) == -1)
107 errExit("asprintf"); 107 errExit("asprintf");
108 execlp(RUN_CP_COMMAND, RUN_CP_COMMAND, "-a", "--parents", f, RUN_MNT_DIR, NULL); 108 execlp(RUN_CP_COMMAND, RUN_CP_COMMAND, "-a", "--parents", f, RUN_MNT_DIR, NULL);
109 perror("execlp");
110 _exit(1);
109 } 111 }
110 // wait for the child to finish 112 // wait for the child to finish
111 waitpid(child, NULL, 0); 113 waitpid(child, NULL, 0);
@@ -128,8 +130,7 @@ void fs_private_etc_list(void) {
128 exit(1); 130 exit(1);
129 } 131 }
130 132
131 // create /tmp/firejail/mnt/etc directory 133 // create /run/firejail/mnt/etc directory
132 fs_build_mnt_dir();
133 if (mkdir(RUN_ETC_DIR, 0755) == -1) 134 if (mkdir(RUN_ETC_DIR, 0755) == -1)
134 errExit("mkdir"); 135 errExit("mkdir");
135 if (chmod(RUN_ETC_DIR, 0755) == -1) 136 if (chmod(RUN_ETC_DIR, 0755) == -1)
@@ -169,7 +170,7 @@ void fs_private_etc_list(void) {
169 duplicate(ptr); 170 duplicate(ptr);
170 free(dlist); 171 free(dlist);
171 fs_logger_print(); 172 fs_logger_print();
172 exit(0); 173 _exit(0);
173 } 174 }
174 // wait for the child to finish 175 // wait for the child to finish
175 waitpid(child, NULL, 0); 176 waitpid(child, NULL, 0);
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c
index 63d5a1c5e..a2532c367 100644
--- a/src/firejail/fs_home.c
+++ b/src/firejail/fs_home.c
@@ -104,8 +104,6 @@ static void skel(const char *homedir, uid_t u, gid_t g) {
104 104
105static int store_xauthority(void) { 105static int store_xauthority(void) {
106 // put a copy of .Xauthority in XAUTHORITY_FILE 106 // put a copy of .Xauthority in XAUTHORITY_FILE
107 fs_build_mnt_dir();
108
109 char *src; 107 char *src;
110 char *dest = RUN_XAUTHORITY_FILE; 108 char *dest = RUN_XAUTHORITY_FILE;
111 if (asprintf(&src, "%s/.Xauthority", cfg.homedir) == -1) 109 if (asprintf(&src, "%s/.Xauthority", cfg.homedir) == -1)
@@ -130,9 +128,6 @@ static int store_xauthority(void) {
130} 128}
131 129
132static int store_asoundrc(void) { 130static int store_asoundrc(void) {
133 // put a copy of .Xauthority in XAUTHORITY_FILE
134 fs_build_mnt_dir();
135
136 char *src; 131 char *src;
137 char *dest = RUN_ASOUNDRC_FILE; 132 char *dest = RUN_ASOUNDRC_FILE;
138 if (asprintf(&src, "%s/.asoundrc", cfg.homedir) == -1) 133 if (asprintf(&src, "%s/.asoundrc", cfg.homedir) == -1)
@@ -591,8 +586,7 @@ void fs_private_home_list(void) {
591 exit(1); 586 exit(1);
592 } 587 }
593 588
594 // create /tmp/firejail/mnt/home directory 589 // create /run/firejail/mnt/home directory
595 fs_build_mnt_dir();
596 int rv = mkdir(RUN_HOME_DIR, 0755); 590 int rv = mkdir(RUN_HOME_DIR, 0755);
597 if (rv == -1) 591 if (rv == -1)
598 errExit("mkdir"); 592 errExit("mkdir");
@@ -641,7 +635,7 @@ void fs_private_home_list(void) {
641 635
642 fs_logger_print(); // save the current log 636 fs_logger_print(); // save the current log
643 free(dlist); 637 free(dlist);
644 exit(0); 638 _exit(0);
645 } 639 }
646 // wait for the child to finish 640 // wait for the child to finish
647 waitpid(child, NULL, 0); 641 waitpid(child, NULL, 0);
diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c
index 87d3742e4..04197eb8f 100644
--- a/src/firejail/fs_hostname.c
+++ b/src/firejail/fs_hostname.c
@@ -27,7 +27,6 @@
27 27
28void fs_hostname(const char *hostname) { 28void fs_hostname(const char *hostname) {
29 struct stat s; 29 struct stat s;
30 fs_build_mnt_dir();
31 30
32 // create a new /etc/hostname 31 // create a new /etc/hostname
33 if (stat("/etc/hostname", &s) == 0) { 32 if (stat("/etc/hostname", &s) == 0) {
@@ -100,7 +99,6 @@ void fs_resolvconf(void) {
100 return; 99 return;
101 100
102 struct stat s; 101 struct stat s;
103 fs_build_mnt_dir();
104 102
105 // create a new /etc/hostname 103 // create a new /etc/hostname
106 if (stat("/etc/resolv.conf", &s) == 0) { 104 if (stat("/etc/resolv.conf", &s) == 0) {
diff --git a/src/firejail/fs_mkdir.c b/src/firejail/fs_mkdir.c
index b2a5927e6..cffe32a7a 100644
--- a/src/firejail/fs_mkdir.c
+++ b/src/firejail/fs_mkdir.c
@@ -81,7 +81,7 @@ void fs_mkdir(const char *name) {
81 81
82 // create directory 82 // create directory
83 mkdir_recursive(expanded); 83 mkdir_recursive(expanded);
84 exit(0); 84 _exit(0);
85 } 85 }
86 // wait for the child to finish 86 // wait for the child to finish
87 waitpid(child, NULL, 0); 87 waitpid(child, NULL, 0);
@@ -126,7 +126,7 @@ void fs_mkfile(const char *name) {
126 (void) rv; 126 (void) rv;
127 fclose(fp); 127 fclose(fp);
128 } 128 }
129 exit(0); 129 _exit(0);
130 } 130 }
131 // wait for the child to finish 131 // wait for the child to finish
132 waitpid(child, NULL, 0); 132 waitpid(child, NULL, 0);
diff --git a/src/firejail/fs_trace.c b/src/firejail/fs_trace.c
index 78fc8a647..719b55048 100644
--- a/src/firejail/fs_trace.c
+++ b/src/firejail/fs_trace.c
@@ -44,9 +44,6 @@ void fs_trace_preload(void) {
44} 44}
45 45
46void fs_trace(void) { 46void fs_trace(void) {
47 // create /tmp/firejail/mnt directory
48 fs_build_mnt_dir();
49
50 // create the new ld.so.preload file and mount-bind it 47 // create the new ld.so.preload file and mount-bind it
51 if (arg_debug) 48 if (arg_debug)
52 printf("Create the new ld.so.preload file\n"); 49 printf("Create the new ld.so.preload file\n");
diff --git a/src/firejail/fs_var.c b/src/firejail/fs_var.c
index a578d04e6..4ff00f3ba 100644
--- a/src/firejail/fs_var.c
+++ b/src/firejail/fs_var.c
@@ -317,9 +317,6 @@ void fs_var_utmp(void) {
317 return; 317 return;
318 } 318 }
319 319
320 // create /tmp/firejail/mnt directory
321 fs_build_mnt_dir();
322
323 // create a new utmp file 320 // create a new utmp file
324 if (arg_debug) 321 if (arg_debug)
325 printf("Create the new utmp file\n"); 322 printf("Create the new utmp file\n");
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c
index ad7fea227..9cd8f7681 100644
--- a/src/firejail/fs_whitelist.c
+++ b/src/firejail/fs_whitelist.c
@@ -254,7 +254,16 @@ static void whitelist_path(ProfileEntry *entry) {
254 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_OPT_DIR, fname) == -1) 254 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_OPT_DIR, fname) == -1)
255 errExit("asprintf"); 255 errExit("asprintf");
256 } 256 }
257 else if (entry->srv_dir) {
258 fname = path + 4; // strlen("/srv")
259 if (*fname == '\0') {
260 fprintf(stderr, "Error: file %s is not in /srv directory, exiting...\n", path);
261 exit(1);
262 }
257 263
264 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_SRV_DIR, fname) == -1)
265 errExit("asprintf");
266 }
258 // check if the file exists 267 // check if the file exists
259 struct stat s; 268 struct stat s;
260 if (wfile && stat(wfile, &s) == 0) { 269 if (wfile && stat(wfile, &s) == 0) {
@@ -317,7 +326,7 @@ void fs_whitelist(void) {
317 int var_dir = 0; // /var directory flag 326 int var_dir = 0; // /var directory flag
318 int dev_dir = 0; // /dev directory flag 327 int dev_dir = 0; // /dev directory flag
319 int opt_dir = 0; // /opt directory flag 328 int opt_dir = 0; // /opt directory flag
320 329 int srv_dir = 0; // /srv directory flag
321 // verify whitelist files, extract symbolic links, etc. 330 // verify whitelist files, extract symbolic links, etc.
322 while (entry) { 331 while (entry) {
323 // handle only whitelist commands 332 // handle only whitelist commands
@@ -387,7 +396,9 @@ void fs_whitelist(void) {
387 dev_dir = 1; 396 dev_dir = 1;
388 else if (strncmp(new_name, "/opt/", 5) == 0) 397 else if (strncmp(new_name, "/opt/", 5) == 0)
389 opt_dir = 1; 398 opt_dir = 1;
390 399 else if (strncmp(new_name, "/srv/", 5) == 0)
400 opt_dir = 1;
401
391 continue; 402 continue;
392 } 403 }
393 404
@@ -481,6 +492,16 @@ void fs_whitelist(void) {
481 goto errexit; 492 goto errexit;
482 } 493 }
483 } 494 }
495 else if (strncmp(new_name, "/srv/", 5) == 0) {
496 entry->srv_dir = 1;
497 srv_dir = 1;
498 // both path and absolute path are under /srv
499 if (strncmp(fname, "/srv/", 5) != 0) {
500 if (arg_debug)
501 fprintf(stderr, "Debug %d: fname #%s#\n", __LINE__, fname);
502 goto errexit;
503 }
504 }
484 else { 505 else {
485 if (arg_debug) 506 if (arg_debug)
486 fprintf(stderr, "Debug %d: \n", __LINE__); 507 fprintf(stderr, "Debug %d: \n", __LINE__);
@@ -508,10 +529,6 @@ void fs_whitelist(void) {
508 entry = entry->next; 529 entry = entry->next;
509 } 530 }
510 531
511 // create mount points
512 fs_build_mnt_dir();
513
514
515 // /home/user 532 // /home/user
516 if (home_dir) { 533 if (home_dir) {
517 // keep a copy of real home dir in RUN_WHITELIST_HOME_USER_DIR 534 // keep a copy of real home dir in RUN_WHITELIST_HOME_USER_DIR
@@ -550,29 +567,6 @@ void fs_whitelist(void) {
550 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=1777,gid=0") < 0) 567 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=1777,gid=0") < 0)
551 errExit("mounting tmpfs on /tmp"); 568 errExit("mounting tmpfs on /tmp");
552 fs_logger("tmpfs /tmp"); 569 fs_logger("tmpfs /tmp");
553
554 // mount appimage directory if necessary
555 if (arg_appimage) {
556 const char *dir = appimage_getdir();
557 assert(dir);
558 char *wdir;
559 if (asprintf(&wdir, "%s/%s", RUN_WHITELIST_TMP_DIR, dir + 4) == -1)
560 errExit("asprintf");
561
562 // create directory
563 if (mkdir(dir, 0755) < 0)
564 errExit("mkdir");
565 if (chown(dir, getuid(), getgid()) < 0)
566 errExit("chown");
567 if (chmod(dir, 0755) < 0)
568 errExit("chmod");
569
570 // mount
571 if (mount(wdir, dir, NULL, MS_BIND|MS_REC, NULL) < 0)
572 errExit("mount bind");
573 fs_logger2("whitelist", dir);
574 free(wdir);
575 }
576 } 570 }
577 571
578 // /media mountpoint 572 // /media mountpoint
@@ -698,6 +692,36 @@ void fs_whitelist(void) {
698 fs_logger("tmpfs /opt"); 692 fs_logger("tmpfs /opt");
699 } 693 }
700 694
695 // /srv mountpoint
696 if (srv_dir) {
697 // check if /srv directory exists
698 struct stat s;
699 if (stat("/srv", &s) == 0) {
700 // keep a copy of real /srv directory in RUN_WHITELIST_SRV_DIR
701 int rv = mkdir(RUN_WHITELIST_SRV_DIR, 0755);
702 if (rv == -1)
703 errExit("mkdir");
704 if (chown(RUN_WHITELIST_SRV_DIR, 0, 0) < 0)
705 errExit("chown");
706 if (chmod(RUN_WHITELIST_SRV_DIR, 0755) < 0)
707 errExit("chmod");
708
709 if (mount("/srv", RUN_WHITELIST_SRV_DIR, NULL, MS_BIND|MS_REC, NULL) < 0)
710 errExit("mount bind");
711
712 // mount tmpfs on /srv
713 if (arg_debug || arg_debug_whitelists)
714 printf("Mounting tmpfs on /srv directory\n");
715 if (mount("tmpfs", "/srv", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
716 errExit("mounting tmpfs on /srv");
717 fs_logger("tmpfs /srv");
718 }
719 else
720 srv_dir = 0;
721 }
722
723
724
701 // go through profile rules again, and interpret whitelist commands 725 // go through profile rules again, and interpret whitelist commands
702 entry = cfg.profile; 726 entry = cfg.profile;
703 while (entry) { 727 while (entry) {
@@ -789,6 +813,13 @@ void fs_whitelist(void) {
789 fs_logger2("tmpfs", RUN_WHITELIST_MNT_DIR); 813 fs_logger2("tmpfs", RUN_WHITELIST_MNT_DIR);
790 } 814 }
791 815
816 // mask the real /srv directory, currently mounted on RUN_WHITELIST_SRV_DIR
817 if (srv_dir) {
818 if (mount("tmpfs", RUN_WHITELIST_SRV_DIR, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
819 errExit("mount tmpfs");
820 fs_logger2("tmpfs", RUN_WHITELIST_SRV_DIR);
821 }
822
792 if (new_name) 823 if (new_name)
793 free(new_name); 824 free(new_name);
794 825
diff --git a/src/firejail/join.c b/src/firejail/join.c
index ea44019ca..6f1e9455c 100644
--- a/src/firejail/join.c
+++ b/src/firejail/join.c
@@ -292,16 +292,16 @@ void join(pid_t pid, int argc, char **argv, int index) {
292 if (apply_caps == 1) // not available for uid 0 292 if (apply_caps == 1) // not available for uid 0
293 caps_set(caps); 293 caps_set(caps);
294#ifdef HAVE_SECCOMP 294#ifdef HAVE_SECCOMP
295 // set protocol filter 295 // read cfg.protocol from file
296 if (getuid() != 0) 296 if (getuid() != 0)
297 protocol_filter_load(RUN_PROTOCOL_CFG); 297 protocol_filter_load(RUN_PROTOCOL_CFG);
298 if (cfg.protocol) { // not available for uid 0 298 if (cfg.protocol) { // not available for uid 0
299 protocol_filter(); 299 seccomp_load(RUN_SECCOMP_PROTOCOL); // install filter
300 } 300 }
301 301
302 // set seccomp filter 302 // set seccomp filter
303 if (apply_seccomp == 1) // not available for uid 0 303 if (apply_seccomp == 1) // not available for uid 0
304 seccomp_set(); 304 seccomp_load(RUN_SECCOMP_CFG);
305#endif 305#endif
306 306
307 // fix qt 4.8 307 // fix qt 4.8
diff --git a/src/firejail/list.c b/src/firejail/list.c
deleted file mode 100644
index d093a1f85..000000000
--- a/src/firejail/list.c
+++ /dev/null
@@ -1,101 +0,0 @@
1/*
2 * Copyright (C) 2014-2016 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#include "firejail.h"
21#include <sys/types.h>
22#include <sys/stat.h>
23
24static void set_privileges(void) {
25 struct stat s;
26 if (stat("/proc/sys/kernel/grsecurity", &s) == 0) {
27 EUID_ROOT();
28
29 // elevate privileges
30 if (setreuid(0, 0))
31 errExit("setreuid");
32 if (setregid(0, 0))
33 errExit("setregid");
34 }
35 else
36 drop_privs(1);
37}
38
39static char *get_firemon_path(const char *cmd) {
40 assert(cmd);
41
42 // start the argv[0] program in a new sandbox
43 char *firemon;
44 if (asprintf(&firemon, "%s/bin/firemon %s", PREFIX, cmd) == -1)
45 errExit("asprintf");
46
47 return firemon;
48}
49
50void top(void) {
51 EUID_ASSERT();
52 drop_privs(1);
53 char *cmd = get_firemon_path("--top");
54
55 char *arg[4];
56 arg[0] = "bash";
57 arg[1] = "-c";
58 arg[2] = cmd;
59 arg[3] = NULL;
60 execvp("/bin/bash", arg);
61}
62
63void netstats(void) {
64 EUID_ASSERT();
65 set_privileges();
66 char *cmd = get_firemon_path("--netstats");
67
68 char *arg[4];
69 arg[0] = "bash";
70 arg[1] = "-c";
71 arg[2] = cmd;
72 arg[3] = NULL;
73 execvp("/bin/bash", arg);
74}
75
76void list(void) {
77 EUID_ASSERT();
78 drop_privs(1);
79 char *cmd = get_firemon_path("--list");
80
81 char *arg[4];
82 arg[0] = "bash";
83 arg[1] = "-c";
84 arg[2] = cmd;
85 arg[3] = NULL;
86 execvp("/bin/bash", arg);
87}
88
89void tree(void) {
90 EUID_ASSERT();
91 drop_privs(1);
92 char *cmd = get_firemon_path("--tree");
93
94 char *arg[4];
95 arg[0] = "bash";
96 arg[1] = "-c";
97 arg[2] = cmd;
98 arg[3] = NULL;
99 execvp("/bin/bash", arg);
100}
101
diff --git a/src/firejail/ls.c b/src/firejail/ls.c
index 39efaa0a6..dba82be0b 100644
--- a/src/firejail/ls.c
+++ b/src/firejail/ls.c
@@ -358,7 +358,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
358 fprintf(stderr, "Error: Cannot read %s\n", fname1); 358 fprintf(stderr, "Error: Cannot read %s\n", fname1);
359 exit(1); 359 exit(1);
360 } 360 }
361 exit(0); 361 _exit(0);
362 } 362 }
363 363
364 // wait for the child to finish 364 // wait for the child to finish
@@ -391,7 +391,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
391 exit(1); 391 exit(1);
392 } 392 }
393 fclose(fp); 393 fclose(fp);
394 exit(0); 394 _exit(0);
395 } 395 }
396 396
397 // wait for the child to finish 397 // wait for the child to finish
@@ -445,7 +445,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
445 fprintf(stderr, "Error: Cannot read %s\n", src_fname); 445 fprintf(stderr, "Error: Cannot read %s\n", src_fname);
446 exit(1); 446 exit(1);
447 } 447 }
448 exit(0); 448 _exit(0);
449 } 449 }
450 450
451 // wait for the child to finish 451 // wait for the child to finish
@@ -494,7 +494,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
494 } 494 }
495 } 495 }
496 496
497 exit(0); 497 _exit(0);
498 } 498 }
499 499
500 // wait for the child to finish 500 // wait for the child to finish
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 6d4eb21df..fc86f9651 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -54,9 +54,9 @@ Config cfg; // configuration
54int arg_private = 0; // mount private /home and /tmp directoryu 54int arg_private = 0; // mount private /home and /tmp directoryu
55int arg_private_template = 0; // mount private /home using a template 55int arg_private_template = 0; // mount private /home using a template
56int arg_debug = 0; // print debug messages 56int arg_debug = 0; // print debug messages
57int arg_debug_check_filename; // print debug messages for filename checking 57int arg_debug_check_filename = 0; // print debug messages for filename checking
58int arg_debug_blacklists; // print debug messages for blacklists 58int arg_debug_blacklists = 0; // print debug messages for blacklists
59int arg_debug_whitelists; // print debug messages for whitelists 59int arg_debug_whitelists = 0; // print debug messages for whitelists
60int arg_nonetwork = 0; // --net=none 60int arg_nonetwork = 0; // --net=none
61int arg_command = 0; // -c 61int arg_command = 0; // -c
62int arg_overlay = 0; // overlay option 62int arg_overlay = 0; // overlay option
@@ -404,8 +404,8 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
404#ifdef HAVE_SECCOMP 404#ifdef HAVE_SECCOMP
405 else if (strcmp(argv[i], "--debug-syscalls") == 0) { 405 else if (strcmp(argv[i], "--debug-syscalls") == 0) {
406 if (checkcfg(CFG_SECCOMP)) { 406 if (checkcfg(CFG_SECCOMP)) {
407 syscall_print(); 407 int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FSECCOMP, "debug-syscalls");
408 exit(0); 408 exit(rv);
409 } 409 }
410 else { 410 else {
411 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n"); 411 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n");
@@ -414,7 +414,8 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
414 } 414 }
415 else if (strcmp(argv[i], "--debug-errnos") == 0) { 415 else if (strcmp(argv[i], "--debug-errnos") == 0) {
416 if (checkcfg(CFG_SECCOMP)) { 416 if (checkcfg(CFG_SECCOMP)) {
417 errno_print(); 417 int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FSECCOMP, "debug-errnos");
418 exit(rv);
418 } 419 }
419 else { 420 else {
420 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n"); 421 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n");
@@ -438,8 +439,8 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
438 exit(0); 439 exit(0);
439 } 440 }
440 else if (strcmp(argv[i], "--debug-protocols") == 0) { 441 else if (strcmp(argv[i], "--debug-protocols") == 0) {
441 protocol_list(); 442 int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FSECCOMP, "debug-protocols");
442 exit(0); 443 exit(rv);
443 } 444 }
444 else if (strncmp(argv[i], "--protocol.print=", 17) == 0) { 445 else if (strncmp(argv[i], "--protocol.print=", 17) == 0) {
445 if (checkcfg(CFG_SECCOMP)) { 446 if (checkcfg(CFG_SECCOMP)) {
@@ -498,27 +499,32 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
498 exit(0); 499 exit(0);
499 } 500 }
500 else if (strcmp(argv[i], "--list") == 0) { 501 else if (strcmp(argv[i], "--list") == 0) {
501 list(); 502 int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FIREMON, "--list");
502 exit(0); 503 exit(rv);
503 } 504 }
504 else if (strcmp(argv[i], "--tree") == 0) { 505 else if (strcmp(argv[i], "--tree") == 0) {
505 tree(); 506 int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FIREMON, "--tree");
506 exit(0); 507 exit(rv);
507 } 508 }
508 else if (strcmp(argv[i], "--top") == 0) { 509 else if (strcmp(argv[i], "--top") == 0) {
509 top(); 510 int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FIREMON, "--top");
510 exit(0); 511 exit(rv);
511 } 512 }
512#ifdef HAVE_NETWORK 513#ifdef HAVE_NETWORK
513 else if (strcmp(argv[i], "--netstats") == 0) { 514 else if (strcmp(argv[i], "--netstats") == 0) {
514 if (checkcfg(CFG_NETWORK)) { 515 if (checkcfg(CFG_NETWORK)) {
515 netstats(); 516 struct stat s;
517 int rv;
518 if (stat("/proc/sys/kernel/grsecurity", &s) == 0)
519 rv = sbox_run(SBOX_ROOT | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FIREMON, "--netstats");
520 else
521 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FIREMON, "--netstats");
522 exit(rv);
516 } 523 }
517 else { 524 else {
518 fprintf(stderr, "Error: networking features are disabled in Firejail configuration file\n"); 525 fprintf(stderr, "Error: networking features are disabled in Firejail configuration file\n");
519 exit(1); 526 exit(1);
520 } 527 }
521 exit(0);
522 } 528 }
523#endif 529#endif
524#ifdef HAVE_FILE_TRANSFER 530#ifdef HAVE_FILE_TRANSFER
@@ -849,6 +855,9 @@ int main(int argc, char **argv) {
849 int highest_errno = errno_highest_nr(); 855 int highest_errno = errno_highest_nr();
850#endif 856#endif
851 857
858 // build /run/firejail directory structure
859 preproc_build_firejail_dir();
860
852 detect_quiet(argc, argv); 861 detect_quiet(argc, argv);
853 detect_allow_debuggers(argc, argv); 862 detect_allow_debuggers(argc, argv);
854 863
@@ -951,10 +960,8 @@ int main(int argc, char **argv) {
951 // initialize globals 960 // initialize globals
952 init_cfg(argc, argv); 961 init_cfg(argc, argv);
953 962
954
955 // check firejail directories 963 // check firejail directories
956 EUID_ROOT(); 964 EUID_ROOT();
957 fs_build_firejail_dir();
958 bandwidth_del_run_file(sandbox_pid); 965 bandwidth_del_run_file(sandbox_pid);
959 network_del_run_file(sandbox_pid); 966 network_del_run_file(sandbox_pid);
960 delete_name_file(sandbox_pid); 967 delete_name_file(sandbox_pid);
@@ -1112,7 +1119,16 @@ int main(int argc, char **argv) {
1112#ifdef HAVE_SECCOMP 1119#ifdef HAVE_SECCOMP
1113 else if (strncmp(argv[i], "--protocol=", 11) == 0) { 1120 else if (strncmp(argv[i], "--protocol=", 11) == 0) {
1114 if (checkcfg(CFG_SECCOMP)) { 1121 if (checkcfg(CFG_SECCOMP)) {
1115 protocol_store(argv[i] + 11); 1122 if (cfg.protocol) {
1123 if (!arg_quiet)
1124 fprintf(stderr, "Warning: a protocol list is present, the new list \"%s\" will not be installed\n", argv[i] + 11);
1125 }
1126 else {
1127 // store list
1128 cfg.protocol = strdup(argv[i] + 11);
1129 if (!cfg.protocol)
1130 errExit("strdup");
1131 }
1116 } 1132 }
1117 else { 1133 else {
1118 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n"); 1134 fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n");
@@ -1447,35 +1463,6 @@ int main(int argc, char **argv) {
1447 } 1463 }
1448 1464
1449 } 1465 }
1450#if 0 // disabled for now, it could be used to overwrite system directories
1451 else if (strncmp(argv[i], "--overlay-path=", 15) == 0) {
1452 if (checkcfg(CFG_OVERLAYFS)) {
1453 if (cfg.chrootdir) {
1454 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
1455 exit(1);
1456 }
1457 struct stat s;
1458 if (stat("/proc/sys/kernel/grsecurity", &s) == 0) {
1459 fprintf(stderr, "Error: --overlay option is not available on Grsecurity systems\n");
1460 exit(1);
1461 }
1462 arg_overlay = 1;
1463 arg_overlay_keep = 1;
1464 arg_overlay_reuse = 1;
1465
1466 char *dirname = argv[i] + 15;
1467 if (dirname == '\0') {
1468 fprintf(stderr, "Error: invalid overlay option\n");
1469 exit(1);
1470 }
1471 cfg.overlay_dir = expand_home(dirname, cfg.homedir);
1472 }
1473 else {
1474 fprintf(stderr, "Error: overlayfs feature is disabled in Firejail configuration file\n");
1475 exit(1);
1476 }
1477 }
1478#endif
1479 else if (strcmp(argv[i], "--overlay-tmpfs") == 0) { 1466 else if (strcmp(argv[i], "--overlay-tmpfs") == 0) {
1480 if (checkcfg(CFG_OVERLAYFS)) { 1467 if (checkcfg(CFG_OVERLAYFS)) {
1481 if (cfg.chrootdir) { 1468 if (cfg.chrootdir) {
@@ -1605,6 +1592,14 @@ int main(int argc, char **argv) {
1605 return 1; 1592 return 1;
1606 } 1593 }
1607 1594
1595 // don't allow "--chroot=/"
1596 char *rpath = realpath(cfg.chrootdir, NULL);
1597 if (rpath == NULL || strcmp(rpath, "/") == 0) {
1598 fprintf(stderr, "Error: invalid chroot directory\n");
1599 exit(1);
1600 }
1601 free(rpath);
1602
1608 // check chroot directory structure 1603 // check chroot directory structure
1609 if (fs_check_chroot_dir(cfg.chrootdir)) { 1604 if (fs_check_chroot_dir(cfg.chrootdir)) {
1610 fprintf(stderr, "Error: invalid chroot\n"); 1605 fprintf(stderr, "Error: invalid chroot\n");
@@ -2506,7 +2501,7 @@ int main(int argc, char **argv) {
2506 network_main(child); 2501 network_main(child);
2507 if (arg_debug) 2502 if (arg_debug)
2508 printf("Host network configured\n"); 2503 printf("Host network configured\n");
2509 exit(0); 2504 _exit(0);
2510 } 2505 }
2511 2506
2512 // wait for the child to finish 2507 // wait for the child to finish
@@ -2555,16 +2550,30 @@ int main(int argc, char **argv) {
2555 ptr += strlen(ptr); 2550 ptr += strlen(ptr);
2556 2551
2557 // add tty group 2552 // add tty group
2558 gid_t ttygid = get_tty_gid(); 2553 gid_t g = get_group_id("tty");
2559 if (ttygid) { 2554 if (g) {
2560 sprintf(ptr, "%d %d 1\n", ttygid, ttygid); 2555 sprintf(ptr, "%d %d 1\n", g, g);
2561 ptr += strlen(ptr); 2556 ptr += strlen(ptr);
2562 } 2557 }
2563 2558
2564 // add audio group 2559 // add audio group
2565 gid_t audiogid = get_audio_gid(); 2560 g = get_group_id("audio");
2566 if (ttygid) { 2561 if (g) {
2567 sprintf(ptr, "%d %d 1\n", audiogid, audiogid); 2562 sprintf(ptr, "%d %d 1\n", g, g);
2563 ptr += strlen(ptr);
2564 }
2565
2566 // add video group
2567 g = get_group_id("video");
2568 if (g) {
2569 sprintf(ptr, "%d %d 1\n", g, g);
2570 ptr += strlen(ptr);
2571 }
2572
2573 // add games group
2574 g = get_group_id("games");
2575 if (g) {
2576 sprintf(ptr, "%d %d 1\n", g, g);
2568 } 2577 }
2569 2578
2570 EUID_ROOT(); 2579 EUID_ROOT();
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c
index b50d61039..c1f9a2c37 100644
--- a/src/firejail/netfilter.c
+++ b/src/firejail/netfilter.c
@@ -145,7 +145,8 @@ void netfilter(const char *fname) {
145 // wipe out environment variables 145 // wipe out environment variables
146 environ = NULL; 146 environ = NULL;
147 execl(iptables_restore, iptables_restore, NULL); 147 execl(iptables_restore, iptables_restore, NULL);
148 // it will never get here!!! 148 perror("execl");
149 _exit(1);
149 } 150 }
150 // wait for the child to finish 151 // wait for the child to finish
151 waitpid(child, NULL, 0); 152 waitpid(child, NULL, 0);
@@ -163,7 +164,8 @@ void netfilter(const char *fname) {
163 errExit("setregid"); 164 errExit("setregid");
164 environ = NULL; 165 environ = NULL;
165 execl(iptables, iptables, "-vL", NULL); 166 execl(iptables, iptables, "-vL", NULL);
166 // it will never get here!!! 167 perror("execl");
168 _exit(1);
167 } 169 }
168 // wait for the child to finish 170 // wait for the child to finish
169 waitpid(child, NULL, 0); 171 waitpid(child, NULL, 0);
@@ -256,7 +258,8 @@ void netfilter6(const char *fname) {
256 // wipe out environment variables 258 // wipe out environment variables
257 environ = NULL; 259 environ = NULL;
258 execl(ip6tables_restore, ip6tables_restore, NULL); 260 execl(ip6tables_restore, ip6tables_restore, NULL);
259 // it will never get here!!! 261 perror("execl");
262 _exit(1);
260 } 263 }
261 // wait for the child to finish 264 // wait for the child to finish
262 waitpid(child, NULL, 0); 265 waitpid(child, NULL, 0);
@@ -269,7 +272,8 @@ void netfilter6(const char *fname) {
269 if (child == 0) { 272 if (child == 0) {
270 environ = NULL; 273 environ = NULL;
271 execl(ip6tables, ip6tables, "-vL", NULL); 274 execl(ip6tables, ip6tables, "-vL", NULL);
272 // it will never get here!!! 275 perror("execl");
276 _exit(1);
273 } 277 }
274 // wait for the child to finish 278 // wait for the child to finish
275 waitpid(child, NULL, 0); 279 waitpid(child, NULL, 0);
diff --git a/src/firejail/network.c b/src/firejail/network.c
index 4473ef099..6d09d770f 100644
--- a/src/firejail/network.c
+++ b/src/firejail/network.c
@@ -28,70 +28,6 @@
28#include <net/route.h> 28#include <net/route.h>
29#include <linux/if_bridge.h> 29#include <linux/if_bridge.h>
30 30
31// scan interfaces in current namespace and print IP address/mask for each interface
32void net_ifprint(void) {
33 uint32_t ip;
34 uint32_t mask;
35 struct ifaddrs *ifaddr, *ifa;
36
37 if (getifaddrs(&ifaddr) == -1)
38 errExit("getifaddrs");
39
40 printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n",
41 "Interface", "MAC", "IP", "Mask", "Status");
42 // walk through the linked list
43 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
44 if (ifa->ifa_addr == NULL)
45 continue;
46
47 if (ifa->ifa_addr->sa_family == AF_INET) {
48 struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask;
49 mask = ntohl(si->sin_addr.s_addr);
50 si = (struct sockaddr_in *) ifa->ifa_addr;
51 ip = ntohl(si->sin_addr.s_addr);
52
53 // interface status
54 char *status;
55 if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
56 status = "UP";
57 else
58 status = "DOWN";
59
60 // ip address and mask
61 char ipstr[30];
62 sprintf(ipstr, "%d.%d.%d.%d", PRINT_IP(ip));
63 char maskstr[30];
64 sprintf(maskstr, "%d.%d.%d.%d", PRINT_IP(mask));
65
66 // mac address
67 unsigned char mac[6];
68 net_get_mac(ifa->ifa_name, mac);
69 char macstr[30];
70 if (strcmp(ifa->ifa_name, "lo") == 0)
71 macstr[0] = '\0';
72 else
73 sprintf(macstr, "%02x:%02x:%02x:%02x:%02x:%02x", PRINT_MAC(mac));
74
75 // print
76 printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n",
77 ifa->ifa_name, macstr, ipstr, maskstr, status);
78
79 // network scanning
80 if (!arg_scan) // scanning disabled
81 continue;
82 if (strcmp(ifa->ifa_name, "lo") == 0) // no loopbabck scanning
83 continue;
84 if (mask2bits(mask) < 16) // not scanning large networks
85 continue;
86 if (!ip) // if not configured
87 continue;
88 // only if the interface is up and running
89 if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
90 arp_scan(ifa->ifa_name, ip, mask);
91 }
92 }
93 freeifaddrs(ifaddr);
94}
95 31
96int net_get_mtu(const char *ifname) { 32int net_get_mtu(const char *ifname) {
97 int mtu = 0; 33 int mtu = 0;
@@ -190,101 +126,11 @@ void net_if_up(const char *ifname) {
190 fprintf(stderr, "Error: invalid network device name %s\n", ifname); 126 fprintf(stderr, "Error: invalid network device name %s\n", ifname);
191 exit(1); 127 exit(1);
192 } 128 }
193 129 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 3,
194 int sock = socket(AF_INET,SOCK_DGRAM,0); 130 PATH_FNET, "ifup", ifname);
195 if (sock < 0) 131}
196 errExit("socket");
197
198 // get the existing interface flags
199 struct ifreq ifr;
200 memset(&ifr, 0, sizeof(ifr));
201 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
202 ifr.ifr_addr.sa_family = AF_INET;
203
204 // read the existing flags
205 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
206 close(sock);
207 printf("Error: cannot bring up interface %s\n", ifname);
208 errExit("ioctl");
209 }
210 132
211 ifr.ifr_flags |= IFF_UP;
212 133
213 // set the new flags
214 if (ioctl( sock, SIOCSIFFLAGS, &ifr ) < 0) {
215 close(sock);
216 printf("Error: cannot bring up interface %s\n", ifname);
217 errExit("ioctl");
218 }
219
220 // checking
221 // read the existing flags
222 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
223 close(sock);
224 printf("Error: cannot bring up interface %s\n", ifname);
225 errExit("ioctl");
226 }
227
228 // wait not more than 500ms for the interface to come up
229 int cnt = 0;
230 while (cnt < 50) {
231 usleep(10000); // sleep 10ms
232
233 // read the existing flags
234 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
235 close(sock);
236 printf("Error: cannot bring up interface %s\n", ifname);
237 errExit("ioctl");
238 }
239 if (ifr.ifr_flags & IFF_RUNNING)
240 break;
241 cnt++;
242 }
243
244 close(sock);
245}
246
247// bring interface up
248void net_if_down(const char *ifname) {
249 if (strlen(ifname) > IFNAMSIZ) {
250 fprintf(stderr, "Error: invalid network device name %s\n", ifname);
251 exit(1);
252 }
253
254 int sock = socket(AF_INET,SOCK_DGRAM,0);
255 if (sock < 0)
256 errExit("socket");
257
258 // get the existing interface flags
259 struct ifreq ifr;
260 memset(&ifr, 0, sizeof(ifr));
261 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
262 ifr.ifr_addr.sa_family = AF_INET;
263
264 // read the existing flags
265 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
266 close(sock);
267 printf("Error: cannot shut down interface %s\n", ifname);
268 errExit("ioctl");
269 }
270
271 ifr.ifr_flags &= ~IFF_UP;
272
273 // set the new flags
274 if (ioctl( sock, SIOCSIFFLAGS, &ifr ) < 0) {
275 close(sock);
276 printf("Error: cannot shut down interface %s\n", ifname);
277 errExit("ioctl");
278 }
279
280 close(sock);
281}
282
283struct ifreq6 {
284 struct in6_addr ifr6_addr;
285 uint32_t ifr6_prefixlen;
286 unsigned int ifr6_ifindex;
287};
288// configure interface ipv6 address 134// configure interface ipv6 address
289// ex: firejail --net=eth0 --ip6=2001:0db8:0:f101::1/64 135// ex: firejail --net=eth0 --ip6=2001:0db8:0:f101::1/64
290void net_if_ip6(const char *ifname, const char *addr6) { 136void net_if_ip6(const char *ifname, const char *addr6) {
@@ -293,107 +139,11 @@ void net_if_ip6(const char *ifname, const char *addr6) {
293 exit(1); 139 exit(1);
294 } 140 }
295 141
296 // extract prefix 142 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 5,
297 unsigned long prefix; 143 PATH_FNET, "config", "ipv6", ifname, addr6);
298 char *ptr;
299 if ((ptr = strchr(addr6, '/'))) {
300 prefix = atol(ptr + 1);
301 if (prefix > 128) {
302 fprintf(stderr, "Error: invalid prefix for IPv6 address %s\n", addr6);
303 exit(1);
304 }
305 *ptr = '\0'; // mark the end of the address
306 }
307 else
308 prefix = 128;
309
310 // extract address
311 struct sockaddr_in6 sin6;
312 memset(&sin6, 0, sizeof(sin6));
313 sin6.sin6_family = AF_INET6;
314 int rv = inet_pton(AF_INET6, addr6, sin6.sin6_addr.s6_addr);
315 if (rv <= 0) {
316 fprintf(stderr, "Error: invalid IPv6 address %s\n", addr6);
317 exit(1);
318 }
319
320 // open socket
321 int sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
322 if (sock < 0) {
323 fprintf(stderr, "Error: IPv6 is not supported on this system\n");
324 exit(1);
325 }
326
327 // find interface index
328 struct ifreq ifr;
329 memset(&ifr, 0, sizeof(ifr));
330 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
331 ifr.ifr_addr.sa_family = AF_INET;
332 if (ioctl(sock, SIOGIFINDEX, &ifr) < 0) {
333 perror("ioctl SIOGIFINDEX");
334 exit(1);
335 }
336
337 // configure address
338 struct ifreq6 ifr6;
339 memset(&ifr6, 0, sizeof(ifr6));
340 ifr6.ifr6_prefixlen = prefix;
341 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
342 memcpy((char *) &ifr6.ifr6_addr, (char *) &sin6.sin6_addr, sizeof(struct in6_addr));
343 if (ioctl(sock, SIOCSIFADDR, &ifr6) < 0) {
344 perror("ioctl SIOCSIFADDR");
345 exit(1);
346 }
347
348 close(sock);
349}
350
351// configure interface ipv4 address
352void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask, int mtu) {
353 if (strlen(ifname) > IFNAMSIZ) {
354 fprintf(stderr, "Error: invalid network device name %s\n", ifname);
355 exit(1);
356 }
357 if (arg_debug)
358 printf("configure interface %s\n", ifname);
359
360 int sock = socket(AF_INET,SOCK_DGRAM,0);
361 if (sock < 0)
362 errExit("socket");
363
364 struct ifreq ifr;
365 memset(&ifr, 0, sizeof(ifr));
366 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
367 ifr.ifr_addr.sa_family = AF_INET;
368
369 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(ip);
370 if (ioctl( sock, SIOCSIFADDR, &ifr ) < 0) {
371 close(sock);
372 errExit("ioctl");
373 }
374
375 if (ip != 0) {
376 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(mask);
377 if (ioctl( sock, SIOCSIFNETMASK, &ifr ) < 0) {
378 close(sock);
379 errExit("ioctl");
380 }
381 }
382
383 // configure mtu
384 if (mtu > 0) {
385 ifr.ifr_mtu = mtu;
386 if (ioctl( sock, SIOCSIFMTU, &ifr ) < 0) {
387 close(sock);
388 errExit("ioctl");
389 }
390 }
391 144
392 close(sock);
393 usleep(10000); // sleep 10ms
394} 145}
395 146
396
397// add an IP route, return -1 if error, 0 if the route was added 147// add an IP route, return -1 if error, 0 if the route was added
398int net_add_route(uint32_t ip, uint32_t mask, uint32_t gw) { 148int net_add_route(uint32_t ip, uint32_t mask, uint32_t gw) {
399 int sock; 149 int sock;
@@ -431,52 +181,6 @@ int net_add_route(uint32_t ip, uint32_t mask, uint32_t gw) {
431} 181}
432 182
433 183
434// add a veth device to a bridge
435void net_bridge_add_interface(const char *bridge, const char *dev) {
436 if (strlen(bridge) > IFNAMSIZ) {
437 fprintf(stderr, "Error: invalid network device name %s\n", bridge);
438 exit(1);
439 }
440
441 // somehow adding the interface to the bridge resets MTU on bridge device!!!
442 // workaround: restore MTU on the bridge device
443 // todo: put a real fix in
444 int mtu1 = net_get_mtu(bridge);
445
446 struct ifreq ifr;
447 int err;
448 int ifindex = if_nametoindex(dev);
449
450 if (ifindex <= 0)
451 errExit("if_nametoindex");
452
453 int sock;
454 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
455 errExit("socket");
456
457 memset(&ifr, 0, sizeof(ifr));
458 strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
459#ifdef SIOCBRADDIF
460 ifr.ifr_ifindex = ifindex;
461 err = ioctl(sock, SIOCBRADDIF, &ifr);
462 if (err < 0)
463#endif
464 {
465 unsigned long args[4] = { BRCTL_ADD_IF, ifindex, 0, 0 };
466
467 ifr.ifr_data = (char *) args;
468 err = ioctl(sock, SIOCDEVPRIVATE, &ifr);
469 }
470 (void) err;
471 close(sock);
472
473 int mtu2 = net_get_mtu(bridge);
474 if (mtu1 != mtu2) {
475 if (arg_debug)
476 printf("Restoring MTU for %s\n", bridge);
477 net_set_mtu(bridge, mtu1);
478 }
479}
480 184
481#define BUFSIZE 1024 185#define BUFSIZE 1024
482uint32_t network_get_defaultgw(void) { 186uint32_t network_get_defaultgw(void) {
@@ -510,20 +214,15 @@ uint32_t network_get_defaultgw(void) {
510} 214}
511 215
512int net_config_mac(const char *ifname, const unsigned char mac[6]) { 216int net_config_mac(const char *ifname, const unsigned char mac[6]) {
513 struct ifreq ifr; 217 char *macstr;
514 int sock; 218 if (asprintf(&macstr, "%02x:%02x:%02x:%02x:%02x:%02x",
515 219 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) == -1)
516 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 220 errExit("asprintf");
517 errExit("socket");
518 221
519 memset(&ifr, 0, sizeof(ifr)); 222 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 5,
520 strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 223 PATH_FNET, "config", "mac", ifname, macstr);
521 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
522 memcpy(ifr.ifr_hwaddr.sa_data, mac, 6);
523 224
524 if (ioctl(sock, SIOCSIFHWADDR, &ifr) == -1) 225 free(macstr);
525 errExit("ioctl");
526 close(sock);
527 return 0; 226 return 0;
528} 227}
529 228
@@ -546,3 +245,27 @@ int net_get_mac(const char *ifname, unsigned char mac[6]) {
546 close(sock); 245 close(sock);
547 return 0; 246 return 0;
548} 247}
248
249void net_config_interface(const char *dev, uint32_t ip, uint32_t mask, int mtu) {
250 assert(dev);
251
252 char *ipstr;
253 if (asprintf(&ipstr, "%llu", (long long unsigned) ip) == -1)
254 errExit("asprintf");
255
256 char *maskstr;
257 if (asprintf(&maskstr, "%llu", (long long unsigned) mask) == -1)
258 errExit("asprintf");
259
260 char *mtustr;
261 if (asprintf(&mtustr, "%d", mtu) == -1)
262 errExit("asprintf");
263
264 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 7,
265 PATH_FNET, "config", "interface", dev, ipstr, maskstr, mtustr);
266
267 free(ipstr);
268 free(maskstr);
269 free(mtustr);
270}
271
diff --git a/src/firejail/network_main.c b/src/firejail/network_main.c
index 907b84642..8a9c47f0e 100644
--- a/src/firejail/network_main.c
+++ b/src/firejail/network_main.c
@@ -23,6 +23,7 @@
23#include <sys/stat.h> 23#include <sys/stat.h>
24#include <unistd.h> 24#include <unistd.h>
25#include <net/if.h> 25#include <net/if.h>
26#include <stdarg.h>
26 27
27// configure bridge structure 28// configure bridge structure
28// - extract ip address and mask from the bridge interface 29// - extract ip address and mask from the bridge interface
@@ -127,13 +128,11 @@ void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child) {
127 else 128 else
128 dev = br->veth_name; 129 dev = br->veth_name;
129 130
130 net_create_veth(dev, ifname, child); 131 char *cstr;
131 132 if (asprintf(&cstr, "%d", child) == -1)
132 // add interface to the bridge 133 errExit("asprintf");
133 net_bridge_add_interface(br->dev, dev); 134 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 7, PATH_FNET, "create", "veth", dev, ifname, br->dev, cstr);
134 135 free(cstr);
135 // bring up the interface
136 net_if_up(dev);
137 136
138 char *msg; 137 char *msg;
139 if (asprintf(&msg, "%d.%d.%d.%d address assigned to sandbox", PRINT_IP(br->ipsandbox)) == -1) 138 if (asprintf(&msg, "%d.%d.%d.%d address assigned to sandbox", PRINT_IP(br->ipsandbox)) == -1)
@@ -290,47 +289,53 @@ void net_dns_print(pid_t pid) {
290} 289}
291 290
292void network_main(pid_t child) { 291void network_main(pid_t child) {
292 char *cstr;
293 if (asprintf(&cstr, "%d", child) == -1)
294 errExit("asprintf");
295
293 // create veth pair or macvlan device 296 // create veth pair or macvlan device
294 if (cfg.bridge0.configured) { 297 if (cfg.bridge0.configured) {
295 if (cfg.bridge0.macvlan == 0) { 298 if (cfg.bridge0.macvlan == 0) {
296 net_configure_veth_pair(&cfg.bridge0, "eth0", child); 299 net_configure_veth_pair(&cfg.bridge0, "eth0", child);
297 } 300 }
298 else 301 else
299 net_create_macvlan(cfg.bridge0.devsandbox, cfg.bridge0.dev, child); 302 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 6, PATH_FNET, "create", "macvlan", cfg.bridge0.devsandbox, cfg.bridge0.dev, cstr);
300 } 303 }
301 304
302 if (cfg.bridge1.configured) { 305 if (cfg.bridge1.configured) {
303 if (cfg.bridge1.macvlan == 0) 306 if (cfg.bridge1.macvlan == 0)
304 net_configure_veth_pair(&cfg.bridge1, "eth1", child); 307 net_configure_veth_pair(&cfg.bridge1, "eth1", child);
305 else 308 else
306 net_create_macvlan(cfg.bridge1.devsandbox, cfg.bridge1.dev, child); 309 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 6, PATH_FNET, "create", "macvlan", cfg.bridge1.devsandbox, cfg.bridge1.dev, cstr);
307 } 310 }
308 311
309 if (cfg.bridge2.configured) { 312 if (cfg.bridge2.configured) {
310 if (cfg.bridge2.macvlan == 0) 313 if (cfg.bridge2.macvlan == 0)
311 net_configure_veth_pair(&cfg.bridge2, "eth2", child); 314 net_configure_veth_pair(&cfg.bridge2, "eth2", child);
312 else 315 else
313 net_create_macvlan(cfg.bridge2.devsandbox, cfg.bridge2.dev, child); 316 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 6, PATH_FNET, "create", "macvlan", cfg.bridge2.devsandbox, cfg.bridge2.dev, cstr);
314 } 317 }
315 318
316 if (cfg.bridge3.configured) { 319 if (cfg.bridge3.configured) {
317 if (cfg.bridge3.macvlan == 0) 320 if (cfg.bridge3.macvlan == 0)
318 net_configure_veth_pair(&cfg.bridge3, "eth3", child); 321 net_configure_veth_pair(&cfg.bridge3, "eth3", child);
319 else 322 else
320 net_create_macvlan(cfg.bridge3.devsandbox, cfg.bridge3.dev, child); 323 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 6, PATH_FNET, "create", "macvlan", cfg.bridge3.devsandbox, cfg.bridge3.dev, cstr);
321 } 324 }
322 325
323 // move interfaces in sandbox 326 // move interfaces in sandbox
324 if (cfg.interface0.configured) { 327 if (cfg.interface0.configured) {
325 net_move_interface(cfg.interface0.dev, child); 328 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 4, PATH_FNET, "moveif", cfg.interface0.dev, cstr);
326 } 329 }
327 if (cfg.interface1.configured) { 330 if (cfg.interface1.configured) {
328 net_move_interface(cfg.interface1.dev, child); 331 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 4, PATH_FNET, "moveif", cfg.interface1.dev, cstr);
329 } 332 }
330 if (cfg.interface2.configured) { 333 if (cfg.interface2.configured) {
331 net_move_interface(cfg.interface2.dev, child); 334 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 4, PATH_FNET, "moveif", cfg.interface3.dev, cstr);
332 } 335 }
333 if (cfg.interface3.configured) { 336 if (cfg.interface3.configured) {
334 net_move_interface(cfg.interface3.dev, child); 337 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 4, PATH_FNET, "moveif", cfg.interface3.dev, cstr);
335 } 338 }
339
340 free(cstr);
336} 341}
diff --git a/src/firejail/preproc.c b/src/firejail/preproc.c
new file mode 100644
index 000000000..2873571a9
--- /dev/null
+++ b/src/firejail/preproc.c
@@ -0,0 +1,141 @@
1/*
2 * Copyright (C) 2014-2016 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#include "firejail.h"
21#include <sys/mount.h>
22#include <sys/stat.h>
23
24static int tmpfs_mounted = 0;
25
26// build /run/firejail directory
27void preproc_build_firejail_dir(void) {
28 struct stat s;
29
30 // CentOS 6 doesn't have /run directory
31 if (stat(RUN_FIREJAIL_BASEDIR, &s)) {
32 create_empty_dir_as_root(RUN_FIREJAIL_BASEDIR, 0755);
33 }
34
35 if (stat(RUN_FIREJAIL_DIR, &s)) {
36 create_empty_dir_as_root(RUN_FIREJAIL_DIR, 0755);
37 }
38
39 if (stat(RUN_FIREJAIL_NETWORK_DIR, &s)) {
40 create_empty_dir_as_root(RUN_FIREJAIL_NETWORK_DIR, 0755);
41 }
42
43 if (stat(RUN_FIREJAIL_BANDWIDTH_DIR, &s)) {
44 create_empty_dir_as_root(RUN_FIREJAIL_BANDWIDTH_DIR, 0755);
45 }
46
47 if (stat(RUN_FIREJAIL_NAME_DIR, &s)) {
48 create_empty_dir_as_root(RUN_FIREJAIL_NAME_DIR, 0755);
49 }
50
51 if (stat(RUN_FIREJAIL_X11_DIR, &s)) {
52 create_empty_dir_as_root(RUN_FIREJAIL_X11_DIR, 0755);
53 }
54
55 if (stat(RUN_FIREJAIL_APPIMAGE_DIR, &s)) {
56 create_empty_dir_as_root(RUN_FIREJAIL_APPIMAGE_DIR, 0755);
57 }
58
59 if (stat(RUN_MNT_DIR, &s)) {
60 create_empty_dir_as_root(RUN_MNT_DIR, 0755);
61 }
62
63 create_empty_file_as_root(RUN_RO_FILE, S_IRUSR);
64 create_empty_dir_as_root(RUN_RO_DIR, S_IRUSR);
65}
66
67// build /run/firejail/mnt directory
68void preproc_mount_mnt_dir(void) {
69 // mount tmpfs on top of /run/firejail/mnt
70 if (!tmpfs_mounted) {
71 if (arg_debug)
72 printf("Mounting tmpfs on %s directory\n", RUN_MNT_DIR);
73 if (mount("tmpfs", RUN_MNT_DIR, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
74 errExit("mounting /run/firejail/mnt");
75 tmpfs_mounted = 1;
76 fs_logger2("tmpfs", RUN_MNT_DIR);
77
78 // create all seccomp files
79 // as root, create RUN_SECCOMP_I386 file
80 create_empty_file_as_root(RUN_SECCOMP_I386, 0644);
81 if (chown(RUN_SECCOMP_I386, getuid(), getgid()) == -1)
82 errExit("chown");
83 if (chmod(RUN_SECCOMP_I386, 0644) == -1)
84 errExit("chmod");
85
86 // as root, create RUN_SECCOMP_AMD64 file
87 create_empty_file_as_root(RUN_SECCOMP_AMD64, 0644);
88 if (chown(RUN_SECCOMP_AMD64, getuid(), getgid()) == -1)
89 errExit("chown");
90 if (chmod(RUN_SECCOMP_AMD64, 0644) == -1)
91 errExit("chmod");
92
93 // as root, create RUN_SECCOMP file
94 create_empty_file_as_root(RUN_SECCOMP_CFG, 0644);
95 if (chown(RUN_SECCOMP_CFG, getuid(), getgid()) == -1)
96 errExit("chown");
97 if (chmod(RUN_SECCOMP_CFG, 0644) == -1)
98 errExit("chmod");
99
100 // as root, create RUN_SECCOMP_PROTOCOL file
101 create_empty_file_as_root(RUN_SECCOMP_PROTOCOL, 0644);
102 if (chown(RUN_SECCOMP_PROTOCOL, getuid(), getgid()) == -1)
103 errExit("chown");
104 if (chmod(RUN_SECCOMP_PROTOCOL, 0644) == -1)
105 errExit("chmod");
106 }
107}
108
109// grab a copy of cp command
110void preproc_build_cp_command(void) {
111 struct stat s;
112 preproc_mount_mnt_dir();
113 if (stat(RUN_CP_COMMAND, &s)) {
114 char* fname = realpath("/bin/cp", NULL);
115 if (fname == NULL) {
116 fprintf(stderr, "Error: /bin/cp not found\n");
117 exit(1);
118 }
119 if (stat(fname, &s)) {
120 fprintf(stderr, "Error: /bin/cp not found\n");
121 exit(1);
122 }
123 if (is_link(fname)) {
124 fprintf(stderr, "Error: invalid /bin/cp file\n");
125 exit(1);
126 }
127 int rv = copy_file(fname, RUN_CP_COMMAND, 0, 0, 0755);
128 if (rv) {
129 fprintf(stderr, "Error: cannot access /bin/cp\n");
130 exit(1);
131 }
132 ASSERT_PERMS(RUN_CP_COMMAND, 0, 0, 0755);
133
134 free(fname);
135 }
136}
137
138// delete the temporary cp command
139void preproc_delete_cp_command(void) {
140 unlink(RUN_CP_COMMAND);
141}
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index e5c35a89d..f7d5e87e6 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -497,8 +497,18 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
497 497
498 if (strncmp(ptr, "protocol ", 9) == 0) { 498 if (strncmp(ptr, "protocol ", 9) == 0) {
499#ifdef HAVE_SECCOMP 499#ifdef HAVE_SECCOMP
500 if (checkcfg(CFG_SECCOMP)) 500 if (checkcfg(CFG_SECCOMP)) {
501 protocol_store(ptr + 9); 501 if (cfg.protocol) {
502 if (!arg_quiet)
503 fprintf(stderr, "Warning: a protocol list is present, the new list \"%s\" will not be installed\n", ptr + 9);
504 return 0;
505 }
506
507 // store list
508 cfg.protocol = strdup(ptr + 9);
509 if (!cfg.protocol)
510 errExit("strdup");
511 }
502 else 512 else
503 fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); 513 fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n");
504#endif 514#endif
diff --git a/src/firejail/protocol.c b/src/firejail/protocol.c
index 1ef5bf13d..e8e88aee9 100644
--- a/src/firejail/protocol.c
+++ b/src/firejail/protocol.c
@@ -18,257 +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 20
21/*
22 struct sock_filter filter[] = {
23 VALIDATE_ARCHITECTURE,
24 EXAMINE_SYSCALL,
25 ONLY(SYS_socket),
26 EXAMINE_ARGUMENT(0), // allow only AF_INET and AF_INET6, drop everything else
27 WHITELIST(AF_INET),
28 WHITELIST(AF_INET6),
29 WHITELIST(AF_PACKET),
30 RETURN_ERRNO(ENOTSUP)
31 };
32 struct sock_fprog prog = {
33 .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
34 .filter = filter,
35 };
36
37
38 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
39 perror("prctl(NO_NEW_PRIVS)");
40 return 1;
41 }
42 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
43 perror("prctl");
44 return 1;
45 }
46*/
47
48#ifdef HAVE_SECCOMP 21#ifdef HAVE_SECCOMP
49#include "firejail.h" 22#include "firejail.h"
50#include "seccomp.h" 23#include "../include/seccomp.h"
51#include <sys/types.h>
52#include <sys/socket.h>
53
54static char *protocol[] = {
55 "unix",
56 "inet",
57 "inet6",
58 "netlink",
59 "packet",
60 NULL
61};
62
63static struct sock_filter protocol_filter_command[] = {
64 WHITELIST(AF_UNIX),
65 WHITELIST(AF_INET),
66 WHITELIST(AF_INET6),
67 WHITELIST(AF_NETLINK),
68 WHITELIST(AF_PACKET)
69};
70// Note: protocol[] and protocol_filter_command are synchronized
71
72// command length
73struct sock_filter whitelist[] = {
74 WHITELIST(AF_UNIX)
75};
76unsigned whitelist_len = sizeof(whitelist) / sizeof(struct sock_filter);
77
78
79
80static int is_protocol(const char *p) {
81 int i = 0;
82 while (protocol[i] != NULL) {
83 if (strcmp(protocol[i], p) == 0)
84 return 1;
85 i++;
86 }
87
88 return 0;
89}
90
91static struct sock_filter *find_protocol_domain(const char *p) {
92 int i = 0;
93 while (protocol[i] != NULL) {
94 if (strcmp(protocol[i], p) == 0)
95 return &protocol_filter_command[i * whitelist_len];
96 i++;
97 }
98
99 return NULL;
100}
101
102// --debug-protocols
103void protocol_list(void) {
104 EUID_ASSERT();
105
106#ifndef SYS_socket
107 fprintf(stderr, "Warning: --protocol not supported on this platform\n");
108 return;
109#endif
110
111 int i = 0;
112 while (protocol[i] != NULL) {
113 printf("%s, ", protocol[i]);
114 i++;
115 }
116 printf("\n");
117}
118
119
120// check protocol list and store it in cfg structure
121void protocol_store(const char *prlist) {
122 EUID_ASSERT();
123 assert(prlist);
124
125 if (cfg.protocol && !arg_quiet) {
126 fprintf(stderr, "Warning: a protocol list is present, the new list \"%s\" will not be installed\n", prlist);
127 return;
128 }
129
130 // temporary list
131 char *tmplist = strdup(prlist);
132 if (!tmplist)
133 errExit("strdup");
134
135 // check list
136 char *token = strtok(tmplist, ",");
137 if (!token)
138 goto errout;
139
140 while (token) {
141 if (!is_protocol(token))
142 goto errout;
143 token = strtok(NULL, ",");
144 }
145 free(tmplist);
146
147 // store list
148 cfg.protocol = strdup(prlist);
149 if (!cfg.protocol)
150 errExit("strdup");
151 return;
152
153errout:
154 fprintf(stderr, "Error: invalid protocol list\n");
155 exit(1);
156}
157
158// install protocol filter
159void protocol_filter(void) {
160 assert(cfg.protocol);
161 if (arg_debug)
162 printf("Set protocol filter: %s\n", cfg.protocol);
163
164#ifndef SYS_socket
165 (void) find_protocol_domain;
166 fprintf(stderr, "Warning: --protocol not supported on this platform\n");
167 return;
168#else
169 // build the filter
170 struct sock_filter filter[32]; // big enough
171 memset(&filter[0], 0, sizeof(filter));
172 uint8_t *ptr = (uint8_t *) &filter[0];
173
174 // header
175 struct sock_filter filter_start[] = {
176 VALIDATE_ARCHITECTURE,
177 EXAMINE_SYSCALL,
178 ONLY(SYS_socket),
179 EXAMINE_ARGUMENT(0)
180 };
181 memcpy(ptr, &filter_start[0], sizeof(filter_start));
182 ptr += sizeof(filter_start);
183
184#if 0
185printf("entries %u\n", (unsigned) (sizeof(filter_start) / sizeof(struct sock_filter)));
186{
187 unsigned j;
188 unsigned char *ptr2 = (unsigned char *) &filter[0];
189 for (j = 0; j < sizeof(filter); j++, ptr2++) {
190 if ((j % (sizeof(struct sock_filter))) == 0)
191 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
192 printf("%02x, ", (*ptr2) & 0xff);
193 }
194 printf("\n");
195}
196printf("whitelist_len %u, struct sock_filter len %u\n", whitelist_len, (unsigned) sizeof(struct sock_filter));
197#endif
198
199
200 // parse list and add commands
201 char *tmplist = strdup(cfg.protocol);
202 if (!tmplist)
203 errExit("strdup");
204 char *token = strtok(tmplist, ",");
205 if (!token)
206 errExit("strtok");
207
208 while (token) {
209 struct sock_filter *domain = find_protocol_domain(token);
210 assert(domain);
211 memcpy(ptr, domain, whitelist_len * sizeof(struct sock_filter));
212 ptr += whitelist_len * sizeof(struct sock_filter);
213 token = strtok(NULL, ",");
214
215#if 0
216printf("entries %u\n", (unsigned) ((uint64_t) ptr - (uint64_t) (filter)) / (unsigned) sizeof(struct sock_filter));
217{
218 unsigned j;
219 unsigned char *ptr2 = (unsigned char *) &filter[0];
220 for (j = 0; j < sizeof(filter); j++, ptr2++) {
221 if ((j % (sizeof(struct sock_filter))) == 0)
222 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
223 printf("%02x, ", (*ptr2) & 0xff);
224 }
225 printf("\n");
226}
227#endif
228
229
230 }
231 free(tmplist);
232
233 // add end of filter
234 struct sock_filter filter_end[] = {
235 RETURN_ERRNO(ENOTSUP)
236 };
237 memcpy(ptr, &filter_end[0], sizeof(filter_end));
238 ptr += sizeof(filter_end);
239
240#if 0
241printf("entries %u\n", (unsigned) ((uint64_t) ptr - (uint64_t) (filter)) / (unsigned) sizeof(struct sock_filter));
242{
243 unsigned j;
244 unsigned char *ptr2 = (unsigned char *) &filter[0];
245 for (j = 0; j < sizeof(filter); j++, ptr2++) {
246 if ((j % (sizeof(struct sock_filter))) == 0)
247 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
248 printf("%02x, ", (*ptr2) & 0xff);
249 }
250 printf("\n");
251}
252#endif
253
254 // install filter
255 unsigned short entries = (unsigned short) ((uintptr_t) ptr - (uintptr_t) (filter)) / (unsigned) sizeof(struct sock_filter);
256 struct sock_fprog prog = {
257 .len = entries,
258 .filter = filter,
259 };
260
261 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
262 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
263 return;
264 }
265#endif // SYS_socket
266}
267 24
268void protocol_filter_save(void) { 25void protocol_filter_save(void) {
269 // save protocol filter configuration in PROTOCOL_CFG 26 // save protocol filter configuration in PROTOCOL_CFG
270 fs_build_mnt_dir();
271
272 FILE *fp = fopen(RUN_PROTOCOL_CFG, "w"); 27 FILE *fp = fopen(RUN_PROTOCOL_CFG, "w");
273 if (!fp) 28 if (!fp)
274 errExit("fopen"); 29 errExit("fopen");
diff --git a/src/firejail/pulseaudio.c b/src/firejail/pulseaudio.c
index 90997f934..e1a58c1c8 100644
--- a/src/firejail/pulseaudio.c
+++ b/src/firejail/pulseaudio.c
@@ -104,7 +104,6 @@ void pulseaudio_init(void) {
104 return; 104 return;
105 105
106 // create the new user pulseaudio directory 106 // create the new user pulseaudio directory
107 fs_build_mnt_dir();
108 int rv = mkdir(RUN_PULSE_DIR, 0700); 107 int rv = mkdir(RUN_PULSE_DIR, 0700);
109 (void) rv; // in --chroot mode the directory can already be there 108 (void) rv; // in --chroot mode the directory can already be there
110 if (chown(RUN_PULSE_DIR, getuid(), getgid()) < 0) 109 if (chown(RUN_PULSE_DIR, getuid(), getgid()) < 0)
diff --git a/src/firejail/restrict_users.c b/src/firejail/restrict_users.c
index 5ef9524d7..57e84e5cc 100644
--- a/src/firejail/restrict_users.c
+++ b/src/firejail/restrict_users.c
@@ -73,7 +73,6 @@ static void sanitize_home(void) {
73 return; 73 return;
74 } 74 }
75 75
76 fs_build_mnt_dir();
77 if (mkdir(RUN_WHITELIST_HOME_DIR, 0755) == -1) 76 if (mkdir(RUN_WHITELIST_HOME_DIR, 0755) == -1)
78 errExit("mkdir"); 77 errExit("mkdir");
79 78
@@ -127,7 +126,6 @@ static void sanitize_passwd(void) {
127 126
128 FILE *fpin = NULL; 127 FILE *fpin = NULL;
129 FILE *fpout = NULL; 128 FILE *fpout = NULL;
130 fs_build_mnt_dir();
131 129
132 // open files 130 // open files
133 /* coverity[toctou] */ 131 /* coverity[toctou] */
@@ -261,7 +259,6 @@ static void sanitize_group(void) {
261 259
262 FILE *fpin = NULL; 260 FILE *fpin = NULL;
263 FILE *fpout = NULL; 261 FILE *fpout = NULL;
264 fs_build_mnt_dir();
265 262
266 // open files 263 // open files
267 /* coverity[toctou] */ 264 /* coverity[toctou] */
diff --git a/src/firejail/restricted_shell.c b/src/firejail/restricted_shell.c
index 24ce27c2e..979bb1eed 100644
--- a/src/firejail/restricted_shell.c
+++ b/src/firejail/restricted_shell.c
@@ -18,6 +18,7 @@
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 <fnmatch.h>
21 22
22#define MAX_READ 4096 // maximum line length 23#define MAX_READ 4096 // maximum line length
23char *restricted_user = NULL; 24char *restricted_user = NULL;
@@ -49,7 +50,11 @@ int restricted_shell(const char *user) {
49 if (*ptr == '\n' || *ptr == '#') 50 if (*ptr == '\n' || *ptr == '#')
50 continue; 51 continue;
51 52
52 // parse line 53 //
54 // parse line
55 //
56
57 // extract users
53 char *usr = ptr; 58 char *usr = ptr;
54 char *args = strchr(usr, ':'); 59 char *args = strchr(usr, ':');
55 if (args == NULL) { 60 if (args == NULL) {
@@ -63,7 +68,7 @@ int restricted_shell(const char *user) {
63 if (ptr) 68 if (ptr)
64 *ptr = '\0'; 69 *ptr = '\0';
65 70
66 // if nothing follows, continue 71 // extract firejail command line arguments
67 char *ptr2 = args; 72 char *ptr2 = args;
68 int found = 0; 73 int found = 0;
69 while (*ptr2 != '\0') { 74 while (*ptr2 != '\0') {
@@ -73,12 +78,13 @@ int restricted_shell(const char *user) {
73 } 78 }
74 ptr2++; 79 ptr2++;
75 } 80 }
81 // if nothing follows, continue
76 if (!found) 82 if (!found)
77 continue; 83 continue;
78 84
79 // process user 85 // user name globbing
80 if (strcmp(user, usr) == 0) { 86 if (fnmatch(usr, user, 0) == 0) {
81 // extract program arguments 87 // process program arguments
82 88
83 fullargv[0] = "firejail"; 89 fullargv[0] = "firejail";
84 int i; 90 int i;
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 8021ce9a3..3942e4da6 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -122,7 +122,7 @@ static void sandbox_if_up(Bridge *br) {
122 assert(br); 122 assert(br);
123 if (!br->configured) 123 if (!br->configured)
124 return; 124 return;
125 125
126 char *dev = br->devsandbox; 126 char *dev = br->devsandbox;
127 net_if_up(dev); 127 net_if_up(dev);
128 128
@@ -137,8 +137,7 @@ static void sandbox_if_up(Bridge *br) {
137 assert(br->ipsandbox); 137 assert(br->ipsandbox);
138 if (arg_debug) 138 if (arg_debug)
139 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev); 139 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev);
140 net_if_ip(dev, br->ipsandbox, br->mask, br->mtu); 140 net_config_interface(dev, br->ipsandbox, br->mask, br->mtu);
141 net_if_up(dev);
142 } 141 }
143 else if (br->arg_ip_none == 0 && br->macvlan == 1) { 142 else if (br->arg_ip_none == 0 && br->macvlan == 1) {
144 // reassign the macvlan address 143 // reassign the macvlan address
@@ -160,8 +159,7 @@ static void sandbox_if_up(Bridge *br) {
160 159
161 if (arg_debug) 160 if (arg_debug)
162 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev); 161 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev);
163 net_if_ip(dev, br->ipsandbox, br->mask, br->mtu); 162 net_config_interface(dev, br->ipsandbox, br->mask, br->mtu);
164 net_if_up(dev);
165 } 163 }
166 164
167 if (br->ip6sandbox) 165 if (br->ip6sandbox)
@@ -256,32 +254,6 @@ static int monitor_application(pid_t app_pid) {
256 254
257 // return the latest exit status. 255 // return the latest exit status.
258 return status; 256 return status;
259
260#if 0
261// todo: find a way to shut down interfaces before closing the namespace
262// the problem is we don't have enough privileges to shutdown interfaces in this moment
263 // shut down bridge/macvlan interfaces
264 if (any_bridge_configured()) {
265
266 if (cfg.bridge0.configured) {
267 printf("Shutting down %s\n", cfg.bridge0.devsandbox);
268 net_if_down( cfg.bridge0.devsandbox);
269 }
270 if (cfg.bridge1.configured) {
271 printf("Shutting down %s\n", cfg.bridge1.devsandbox);
272 net_if_down( cfg.bridge1.devsandbox);
273 }
274 if (cfg.bridge2.configured) {
275 printf("Shutting down %s\n", cfg.bridge2.devsandbox);
276 net_if_down( cfg.bridge2.devsandbox);
277 }
278 if (cfg.bridge3.configured) {
279 printf("Shutting down %s\n", cfg.bridge3.devsandbox);
280 net_if_down( cfg.bridge3.devsandbox);
281 }
282 usleep(20000); // 20 ms sleep
283 }
284#endif
285} 257}
286 258
287void start_audit(void) { 259void start_audit(void) {
@@ -442,7 +414,8 @@ int sandbox(void* sandbox_arg) {
442 if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) { 414 if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
443 chk_chroot(); 415 chk_chroot();
444 } 416 }
445 417 // ... and mount a tmpfs on top of /run/firejail/mnt directory
418 preproc_mount_mnt_dir();
446 419
447 //**************************** 420 //****************************
448 // log sandbox data 421 // log sandbox data
@@ -459,7 +432,7 @@ int sandbox(void* sandbox_arg) {
459 fs_logger("install mount namespace"); 432 fs_logger("install mount namespace");
460 433
461 //**************************** 434 //****************************
462 // netfilter etc. 435 // netfilter
463 //**************************** 436 //****************************
464 if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter 437 if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter
465 netfilter(arg_netfilter_file); 438 netfilter(arg_netfilter_file);
@@ -468,6 +441,105 @@ int sandbox(void* sandbox_arg) {
468 netfilter6(arg_netfilter6_file); 441 netfilter6(arg_netfilter6_file);
469 } 442 }
470 443
444 //****************************
445 // networking
446 //****************************
447 int gw_cfg_failed = 0; // default gw configuration flag
448 if (arg_nonetwork) {
449 net_if_up("lo");
450 if (arg_debug)
451 printf("Network namespace enabled, only loopback interface available\n");
452 }
453 else if (any_bridge_configured() || any_interface_configured()) {
454 // configure lo and eth0...eth3
455 net_if_up("lo");
456
457 if (mac_not_zero(cfg.bridge0.macsandbox))
458 net_config_mac(cfg.bridge0.devsandbox, cfg.bridge0.macsandbox);
459 sandbox_if_up(&cfg.bridge0);
460
461 if (mac_not_zero(cfg.bridge1.macsandbox))
462 net_config_mac(cfg.bridge1.devsandbox, cfg.bridge1.macsandbox);
463 sandbox_if_up(&cfg.bridge1);
464
465 if (mac_not_zero(cfg.bridge2.macsandbox))
466 net_config_mac(cfg.bridge2.devsandbox, cfg.bridge2.macsandbox);
467 sandbox_if_up(&cfg.bridge2);
468
469 if (mac_not_zero(cfg.bridge3.macsandbox))
470 net_config_mac(cfg.bridge3.devsandbox, cfg.bridge3.macsandbox);
471 sandbox_if_up(&cfg.bridge3);
472
473
474// todo: this code seems to be dead!!!
475 // enable interfaces
476 if (cfg.interface0.configured && cfg.interface0.ip) {
477assert(0);
478 if (arg_debug)
479 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface0.ip), cfg.interface0.dev);
480 net_config_interface(cfg.interface0.dev, cfg.interface0.ip, cfg.interface0.mask, cfg.interface0.mtu);
481 }
482 if (cfg.interface1.configured && cfg.interface1.ip) {
483assert(0);
484 if (arg_debug)
485 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface1.ip), cfg.interface1.dev);
486 net_config_interface(cfg.interface1.dev, cfg.interface1.ip, cfg.interface1.mask, cfg.interface1.mtu);
487 }
488 if (cfg.interface2.configured && cfg.interface2.ip) {
489assert(0);
490 if (arg_debug)
491 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface2.ip), cfg.interface2.dev);
492 net_config_interface(cfg.interface2.dev, cfg.interface2.ip, cfg.interface2.mask, cfg.interface2.mtu);
493 }
494 if (cfg.interface3.configured && cfg.interface3.ip) {
495assert(0);
496 if (arg_debug)
497 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface3.ip), cfg.interface3.dev);
498 net_config_interface(cfg.interface3.dev, cfg.interface3.ip, cfg.interface3.mask, cfg.interface3.mtu);
499 }
500
501 // add a default route
502 if (cfg.defaultgw) {
503 // set the default route
504 if (net_add_route(0, 0, cfg.defaultgw)) {
505 fprintf(stderr, "Warning: cannot configure default route\n");
506 gw_cfg_failed = 1;
507 }
508 }
509
510 if (arg_debug)
511 printf("Network namespace enabled\n");
512 }
513
514
515 // print network configuration
516 if (!arg_quiet) {
517 if (any_bridge_configured() || any_interface_configured() || cfg.defaultgw || cfg.dns1) {
518 printf("\n");
519 if (any_bridge_configured() || any_interface_configured()) {
520// net_ifprint();
521 if (arg_scan)
522 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 3, PATH_FNET, "printif", "scan");
523 else
524 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, PATH_FNET, "printif", "scan");
525
526 }
527 if (cfg.defaultgw != 0) {
528 if (gw_cfg_failed)
529 printf("Default gateway configuration failed\n");
530 else
531 printf("Default gateway %d.%d.%d.%d\n", PRINT_IP(cfg.defaultgw));
532 }
533 if (cfg.dns1 != 0)
534 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns1));
535 if (cfg.dns2 != 0)
536 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns2));
537 if (cfg.dns3 != 0)
538 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns3));
539 printf("\n");
540 }
541 }
542
471 // load IBUS env variables 543 // load IBUS env variables
472 if (arg_nonetwork || any_bridge_configured() || any_interface_configured()) { 544 if (arg_nonetwork || any_bridge_configured() || any_interface_configured()) {
473 // do nothing - there are problems with ibus version 1.5.11 545 // do nothing - there are problems with ibus version 1.5.11
@@ -475,9 +547,27 @@ int sandbox(void* sandbox_arg) {
475 else 547 else
476 env_ibus_load(); 548 env_ibus_load();
477 549
478 // grab a copy of cp command 550 //****************************
479 fs_build_cp_command(); 551 // fs pre-processing:
480 552 // - copy some commands under /run
553 // - build seccomp filters
554 // - create an empty /etc/ld.so.preload
555 //****************************
556 preproc_build_cp_command();
557
558#ifdef HAVE_SECCOMP
559 if (cfg.protocol) {
560 if (arg_debug)
561 printf("Build protocol filter: %s\n", cfg.protocol);
562
563 // build the seccomp filter as a regular user
564 int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 5,
565 PATH_FSECCOMP, "protocol", "build", cfg.protocol, RUN_SECCOMP_PROTOCOL);
566 if (rv)
567 exit(rv);
568 }
569#endif
570
481 // trace pre-install 571 // trace pre-install
482 if (arg_trace || arg_tracelog || mask_x11_abstract_socket) 572 if (arg_trace || arg_tracelog || mask_x11_abstract_socket)
483 fs_trace_preload(); 573 fs_trace_preload();
@@ -488,6 +578,13 @@ int sandbox(void* sandbox_arg) {
488#ifdef HAVE_SECCOMP 578#ifdef HAVE_SECCOMP
489 int enforce_seccomp = 0; 579 int enforce_seccomp = 0;
490#endif 580#endif
581 if (arg_appimage) {
582 enforce_filters();
583#ifdef HAVE_SECCOMP
584 enforce_seccomp = 1;
585#endif
586 }
587
491#ifdef HAVE_CHROOT 588#ifdef HAVE_CHROOT
492 if (cfg.chrootdir) { 589 if (cfg.chrootdir) {
493 fs_chroot(cfg.chrootdir); 590 fs_chroot(cfg.chrootdir);
@@ -610,7 +707,6 @@ int sandbox(void* sandbox_arg) {
610 EUID_USER(); 707 EUID_USER();
611 profile_add("whitelist /tmp/.X11-unix"); 708 profile_add("whitelist /tmp/.X11-unix");
612 EUID_ROOT(); 709 EUID_ROOT();
613// fs_private_tmp();
614 } 710 }
615 } 711 }
616 712
@@ -657,102 +753,17 @@ int sandbox(void* sandbox_arg) {
657 fs_dev_disable_3d(); 753 fs_dev_disable_3d();
658 754
659 //**************************** 755 //****************************
660 // networking 756 // set dns
661 //**************************** 757 //****************************
662 int gw_cfg_failed = 0; // default gw configuration flag
663 if (arg_nonetwork) {
664 net_if_up("lo");
665 if (arg_debug)
666 printf("Network namespace enabled, only loopback interface available\n");
667 }
668 else if (any_bridge_configured() || any_interface_configured()) {
669 // configure lo and eth0...eth3
670 net_if_up("lo");
671
672 if (mac_not_zero(cfg.bridge0.macsandbox))
673 net_config_mac(cfg.bridge0.devsandbox, cfg.bridge0.macsandbox);
674 sandbox_if_up(&cfg.bridge0);
675
676 if (mac_not_zero(cfg.bridge1.macsandbox))
677 net_config_mac(cfg.bridge1.devsandbox, cfg.bridge1.macsandbox);
678 sandbox_if_up(&cfg.bridge1);
679
680 if (mac_not_zero(cfg.bridge2.macsandbox))
681 net_config_mac(cfg.bridge2.devsandbox, cfg.bridge2.macsandbox);
682 sandbox_if_up(&cfg.bridge2);
683
684 if (mac_not_zero(cfg.bridge3.macsandbox))
685 net_config_mac(cfg.bridge3.devsandbox, cfg.bridge3.macsandbox);
686 sandbox_if_up(&cfg.bridge3);
687
688 // enable interfaces
689 if (cfg.interface0.configured && cfg.interface0.ip) {
690 if (arg_debug)
691 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface0.ip), cfg.interface0.dev);
692 net_if_ip(cfg.interface0.dev, cfg.interface0.ip, cfg.interface0.mask, cfg.interface0.mtu);
693 net_if_up(cfg.interface0.dev);
694 }
695 if (cfg.interface1.configured && cfg.interface1.ip) {
696 if (arg_debug)
697 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface1.ip), cfg.interface1.dev);
698 net_if_ip(cfg.interface1.dev, cfg.interface1.ip, cfg.interface1.mask, cfg.interface1.mtu);
699 net_if_up(cfg.interface1.dev);
700 }
701 if (cfg.interface2.configured && cfg.interface2.ip) {
702 if (arg_debug)
703 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface2.ip), cfg.interface2.dev);
704 net_if_ip(cfg.interface2.dev, cfg.interface2.ip, cfg.interface2.mask, cfg.interface2.mtu);
705 net_if_up(cfg.interface2.dev);
706 }
707 if (cfg.interface3.configured && cfg.interface3.ip) {
708 if (arg_debug)
709 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface3.ip), cfg.interface3.dev);
710 net_if_ip(cfg.interface3.dev, cfg.interface3.ip, cfg.interface3.mask, cfg.interface3.mtu);
711 net_if_up(cfg.interface3.dev);
712 }
713
714 // add a default route
715 if (cfg.defaultgw) {
716 // set the default route
717 if (net_add_route(0, 0, cfg.defaultgw)) {
718 fprintf(stderr, "Warning: cannot configure default route\n");
719 gw_cfg_failed = 1;
720 }
721 }
722
723 if (arg_debug)
724 printf("Network namespace enabled\n");
725 }
726
727 // if any dns server is configured, it is time to set it now
728 fs_resolvconf(); 758 fs_resolvconf();
759
760 //****************************
761 // fs post-processing
762 //****************************
763 preproc_delete_cp_command();
729 fs_logger_print(); 764 fs_logger_print();
730 fs_logger_change_owner(); 765 fs_logger_change_owner();
731 766
732 // print network configuration
733 if (!arg_quiet) {
734 if (any_bridge_configured() || any_interface_configured() || cfg.defaultgw || cfg.dns1) {
735 printf("\n");
736 if (any_bridge_configured() || any_interface_configured())
737 net_ifprint();
738 if (cfg.defaultgw != 0) {
739 if (gw_cfg_failed)
740 printf("Default gateway configuration failed\n");
741 else
742 printf("Default gateway %d.%d.%d.%d\n", PRINT_IP(cfg.defaultgw));
743 }
744 if (cfg.dns1 != 0)
745 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns1));
746 if (cfg.dns2 != 0)
747 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns2));
748 if (cfg.dns3 != 0)
749 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns3));
750 printf("\n");
751 }
752 }
753
754 fs_delete_cp_command();
755
756 //**************************** 767 //****************************
757 // set application environment 768 // set application environment
758 //**************************** 769 //****************************
@@ -808,12 +819,24 @@ int sandbox(void* sandbox_arg) {
808 // set rlimits 819 // set rlimits
809 set_rlimits(); 820 set_rlimits();
810 821
811 // set seccomp 822 // set cpu affinity
823 if (cfg.cpus) {
824 save_cpu(); // save cpu affinity mask to CPU_CFG file
825 set_cpu_affinity();
826 }
827
828 // save cgroup in CGROUP_CFG file
829 if (cfg.cgroup)
830 save_cgroup();
831
832 // set seccomp //todo: push it down after drop_privs and/or configuring noroot
812#ifdef HAVE_SECCOMP 833#ifdef HAVE_SECCOMP
813 // install protocol filter 834 // install protocol filter
814 if (cfg.protocol) { 835 if (cfg.protocol) {
815 protocol_filter(); // install filter 836 if (arg_debug)
816 protocol_filter_save(); // save filter in PROTOCOL_CFG 837 printf("Install protocol filter: %s\n", cfg.protocol);
838 seccomp_load(RUN_SECCOMP_PROTOCOL); // install filter
839 protocol_filter_save(); // save filter in RUN_PROTOCOL_CFG
817 } 840 }
818 841
819 // if a keep list is available, disregard the drop list 842 // if a keep list is available, disregard the drop list
@@ -827,16 +850,6 @@ int sandbox(void* sandbox_arg) {
827 } 850 }
828#endif 851#endif
829 852
830 // set cpu affinity
831 if (cfg.cpus) {
832 save_cpu(); // save cpu affinity mask to CPU_CFG file
833 set_cpu_affinity();
834 }
835
836 // save cgroup in CGROUP_CFG file
837 if (cfg.cgroup)
838 save_cgroup();
839
840 //**************************************** 853 //****************************************
841 // drop privileges or create a new user namespace 854 // drop privileges or create a new user namespace
842 //**************************************** 855 //****************************************
@@ -909,8 +922,6 @@ int sandbox(void* sandbox_arg) {
909 int status = monitor_application(app_pid); // monitor application 922 int status = monitor_application(app_pid); // monitor application
910 flush_stdin(); 923 flush_stdin();
911 924
912
913
914 if (WIFEXITED(status)) { 925 if (WIFEXITED(status)) {
915 // if we had a proper exit, return that exit status 926 // if we had a proper exit, return that exit status
916 return WEXITSTATUS(status); 927 return WEXITSTATUS(status);
diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c
new file mode 100644
index 000000000..6499b7005
--- /dev/null
+++ b/src/firejail/sbox.c
@@ -0,0 +1,186 @@
1/*
2 * Copyright (C) 2014-2016 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#include "firejail.h"
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <unistd.h>
24#include <net/if.h>
25#include <stdarg.h>
26 #include <sys/wait.h>
27#include "../include/seccomp.h"
28
29static struct sock_filter filter[] = {
30 VALIDATE_ARCHITECTURE,
31 EXAMINE_SYSCALL,
32
33#if defined(__x86_64__)
34#define X32_SYSCALL_BIT 0x40000000
35 // handle X32 ABI
36 BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, X32_SYSCALL_BIT, 1, 0),
37 BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, 0, 1, 0),
38 RETURN_ERRNO(EPERM),
39#endif
40
41 // syscall list
42#ifdef SYS_mount
43 BLACKLIST(SYS_mount), // mount/unmount filesystems
44#endif
45#ifdef SYS_umount2
46 BLACKLIST(SYS_umount2),
47#endif
48#ifdef SYS_ptrace
49 BLACKLIST(SYS_ptrace), // trace processes
50#endif
51#ifdef SYS_kexec_file_load
52 BLACKLIST(SYS_kexec_file_load),
53#endif
54#ifdef SYS_kexec_load
55 BLACKLIST(SYS_kexec_load), // loading a different kernel
56#endif
57#ifdef SYS_name_to_handle_at
58 BLACKLIST(SYS_name_to_handle_at),
59#endif
60#ifdef SYS_open_by_handle_at
61 BLACKLIST(SYS_open_by_handle_at), // open by handle
62#endif
63#ifdef SYS_init_module
64 BLACKLIST(SYS_init_module), // kernel module handling
65#endif
66#ifdef SYS_finit_module // introduced in 2013
67 BLACKLIST(SYS_finit_module),
68#endif
69#ifdef SYS_create_module
70 BLACKLIST(SYS_create_module),
71#endif
72#ifdef SYS_delete_module
73 BLACKLIST(SYS_delete_module),
74#endif
75#ifdef SYS_iopl
76 BLACKLIST(SYS_iopl), // io permissions
77#endif
78#ifdef SYS_ioperm
79 BLACKLIST(SYS_ioperm),
80#endif
81#ifdef SYS_iopl
82 BLACKLIST(SYS_iopl), // io permissions
83#endif
84#ifdef SYS_ioprio_set
85 BLACKLIST(SYS_ioprio_set),
86#endif
87#ifdef SYS_ni_syscall // new io permissions call on arm devices
88 BLACKLIST(SYS_ni_syscall),
89#endif
90#ifdef SYS_swapon
91 BLACKLIST(SYS_swapon), // swap on/off
92#endif
93#ifdef SYS_swapoff
94 BLACKLIST(SYS_swapoff),
95#endif
96#ifdef SYS_syslog
97 BLACKLIST(SYS_syslog), // kernel printk control
98#endif
99 RETURN_ALLOW
100};
101
102static struct sock_fprog prog = {
103 .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
104 .filter = filter,
105};
106
107typedef struct sbox_config {
108 char *name;
109 char *path;
110 unsigned filters;
111} SboxConfig;
112
113
114int sbox_run(unsigned filter, int num, ...) {
115 EUID_ROOT();
116
117 int i;
118 va_list valist;
119 va_start(valist, num);
120
121 // build argument list
122 char *arg[num + 1];
123 for (i = 0; i < num; i++)
124 arg[i] = va_arg(valist, char*);
125 arg[i] = NULL;
126 va_end(valist);
127
128 if (arg_debug) {
129 printf("sbox run: ");
130 for (i = 0; i <= num; i++)
131 printf("%s ", arg[i]);
132 printf("\n");
133 }
134
135 pid_t child = fork();
136 if (child < 0)
137 errExit("fork");
138 if (child == 0) {
139 // apply filters
140 if (filter & SBOX_CAPS_NONE) {
141 caps_drop_all();
142 }
143 else if (filter & SBOX_CAPS_NETWORK) {
144 uint64_t set = ((uint64_t) 1) << CAP_NET_ADMIN;
145 set |= ((uint64_t) 1) << CAP_NET_RAW;
146 caps_set(set);
147 }
148
149 if (filter & SBOX_SECCOMP) {
150 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
151 perror("prctl(NO_NEW_PRIVS)");
152 }
153 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
154 perror("prctl(PR_SET_SECCOMP)");
155 }
156 }
157
158 if (filter & SBOX_ROOT) {
159 // elevate privileges in order to get grsecurity working
160 if (setreuid(0, 0))
161 errExit("setreuid");
162 if (setregid(0, 0))
163 errExit("setregid");
164 }
165 else if (filter & SBOX_USER)
166 drop_privs(1);
167
168 if (arg[0]) // get rid of scan-build warning
169 execvp(arg[0], arg);
170 else
171 assert(0);
172 perror("execl");
173 _exit(1);
174 }
175
176 int status;
177 if (waitpid(child, &status, 0) == -1 ) {
178 errExit("waitpid");
179 }
180 if (WIFEXITED(status) && status != 0) {
181 fprintf(stderr, "Error: failed to run %s\n", arg[0]);
182 exit(1);
183 }
184
185 return status;
186}
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c
index c2da1168a..74d29fc9d 100644
--- a/src/firejail/seccomp.c
+++ b/src/firejail/seccomp.c
@@ -20,763 +20,205 @@
20 20
21#ifdef HAVE_SECCOMP 21#ifdef HAVE_SECCOMP
22#include "firejail.h" 22#include "firejail.h"
23#include "seccomp.h" 23#include "../include/seccomp.h"
24
25#define SECSIZE 128 // initial filter size
26static struct sock_filter *sfilter = NULL;
27static int sfilter_alloc_size = 0;
28static int sfilter_index = 0;
29
30// debug filter
31void filter_debug(void) {
32 // start filter
33 struct sock_filter filter[] = {
34 VALIDATE_ARCHITECTURE,
35 EXAMINE_SYSCALL
36 };
37
38 // print sizes
39 printf("SECCOMP Filter:\n");
40 if (sfilter == NULL) {
41 printf("SECCOMP filter not allocated\n");
42 return;
43 }
44 if (sfilter_index < 4)
45 return;
46
47 // test the start of the filter
48 if (memcmp(sfilter, filter, sizeof(filter)) == 0) {
49 printf(" VALIDATE_ARCHITECTURE\n");
50 printf(" EXAMINE_SYSCAL\n");
51 }
52
53 // loop trough blacklists
54 int i = 4;
55 while (i < sfilter_index) {
56 // minimal parsing!
57 unsigned char *ptr = (unsigned char *) &sfilter[i];
58 int *nr = (int *) (ptr + 4);
59 if (*ptr == 0x15 && *(ptr +14) == 0xff && *(ptr + 15) == 0x7f ) {
60 printf(" WHITELIST %d %s\n", *nr, syscall_find_nr(*nr));
61 i += 2;
62 }
63 else if (*ptr == 0x15 && *(ptr +14) == 0 && *(ptr + 15) == 0) {
64 printf(" BLACKLIST %d %s\n", *nr, syscall_find_nr(*nr));
65 i += 2;
66 }
67 else if (*ptr == 0x15 && *(ptr +14) == 0x5 && *(ptr + 15) == 0) {
68 int err = *(ptr + 13) << 8 | *(ptr + 12);
69 printf(" ERRNO %d %s %d %s\n", *nr, syscall_find_nr(*nr), err, errno_find_nr(err));
70 i += 2;
71 }
72 else if (*ptr == 0x06 && *(ptr +6) == 0 && *(ptr + 7) == 0 ) {
73 printf(" KILL_PROCESS\n");
74 i++;
75 }
76 else if (*ptr == 0x06 && *(ptr +6) == 0xff && *(ptr + 7) == 0x7f ) {
77 printf(" RETURN_ALLOW\n");
78 i++;
79 }
80 else {
81 printf(" UNKNOWN ENTRY!!!\n");
82 i++;
83 }
84 }
85}
86
87// initialize filter
88static void filter_init(void) {
89 if (sfilter) {
90 assert(0);
91 return;
92 }
93
94// if (arg_debug)
95// printf("Initialize seccomp filter\n");
96 // allocate a filter of SECSIZE
97 sfilter = malloc(sizeof(struct sock_filter) * SECSIZE);
98 if (!sfilter)
99 errExit("malloc");
100 memset(sfilter, 0, sizeof(struct sock_filter) * SECSIZE);
101 sfilter_alloc_size = SECSIZE;
102
103 // copy the start entries
104#if defined(__x86_64__)
105#define X32_SYSCALL_BIT 0x40000000
106 struct sock_filter filter[] = {
107 VALIDATE_ARCHITECTURE,
108 EXAMINE_SYSCALL,
109 // handle X32 ABI
110 BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, X32_SYSCALL_BIT, 1, 0),
111 BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, 0, 1, 0),
112 RETURN_ERRNO(EPERM)
113 };
114#else
115 struct sock_filter filter[] = {
116 VALIDATE_ARCHITECTURE,
117 EXAMINE_SYSCALL
118 };
119#endif
120 sfilter_index = sizeof(filter) / sizeof(struct sock_filter);
121 memcpy(sfilter, filter, sizeof(filter));
122}
123
124static void filter_realloc(void) {
125 assert(sfilter);
126 assert(sfilter_alloc_size);
127 assert(sfilter_index);
128 if (arg_debug)
129 printf("Allocating more seccomp filter entries\n");
130
131 // allocate the new memory
132 struct sock_filter *old = sfilter;
133 sfilter = malloc(sizeof(struct sock_filter) * (sfilter_alloc_size + SECSIZE));
134 if (!sfilter)
135 errExit("malloc");
136 memset(sfilter, 0, sizeof(struct sock_filter) * (sfilter_alloc_size + SECSIZE));
137
138 // copy old filter
139 memcpy(sfilter, old, sizeof(struct sock_filter) * sfilter_alloc_size);
140 sfilter_alloc_size += SECSIZE;
141}
142
143static void filter_add_whitelist(int syscall, int arg) {
144 (void) arg;
145 assert(sfilter);
146 assert(sfilter_alloc_size);
147 assert(sfilter_index);
148// if (arg_debug)
149// printf("Whitelisting syscall %d %s\n", syscall, syscall_find_nr(syscall));
150
151 if ((sfilter_index + 2) > sfilter_alloc_size)
152 filter_realloc();
153
154 struct sock_filter filter[] = {
155 WHITELIST(syscall)
156 };
157#if 0
158{
159 int i;
160 unsigned char *ptr = (unsigned char *) &filter[0];
161 for (i = 0; i < sizeof(filter); i++, ptr++)
162 printf("%x, ", (*ptr) & 0xff);
163 printf("\n");
164}
165#endif
166 memcpy(&sfilter[sfilter_index], filter, sizeof(filter));
167 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
168}
169
170static void filter_add_blacklist(int syscall, int arg) {
171 (void) arg;
172 assert(sfilter);
173 assert(sfilter_alloc_size);
174 assert(sfilter_index);
175// if (arg_debug)
176// printf("Blacklisting syscall %d %s\n", syscall, syscall_find_nr(syscall));
177
178 if ((sfilter_index + 2) > sfilter_alloc_size)
179 filter_realloc();
180
181 struct sock_filter filter[] = {
182 BLACKLIST(syscall)
183 };
184#if 0
185{
186 int i;
187 unsigned char *ptr = (unsigned char *) &filter[0];
188 for (i = 0; i < sizeof(filter); i++, ptr++)
189 printf("%x, ", (*ptr) & 0xff);
190 printf("\n");
191}
192#endif
193 memcpy(&sfilter[sfilter_index], filter, sizeof(filter));
194 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
195}
196
197static void filter_add_errno(int syscall, int arg) {
198 assert(sfilter);
199 assert(sfilter_alloc_size);
200 assert(sfilter_index);
201// if (arg_debug)
202// printf("Errno syscall %d %d %s\n", syscall, arg, syscall_find_nr(syscall));
203
204 if ((sfilter_index + 2) > sfilter_alloc_size)
205 filter_realloc();
206
207 struct sock_filter filter[] = {
208 BLACKLIST_ERRNO(syscall, arg)
209 };
210#if 0
211{
212 int i;
213 unsigned char *ptr = (unsigned char *) &filter[0];
214 for (i = 0; i < sizeof(filter); i++, ptr++)
215 printf("%x, ", (*ptr) & 0xff);
216 printf("\n");
217}
218#endif
219 memcpy(&sfilter[sfilter_index], filter, sizeof(filter));
220 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
221}
222
223static void filter_end_blacklist(void) {
224 assert(sfilter);
225 assert(sfilter_alloc_size);
226 assert(sfilter_index);
227// if (arg_debug)
228// printf("Ending syscall filter\n");
229
230 if ((sfilter_index + 2) > sfilter_alloc_size)
231 filter_realloc();
232
233 struct sock_filter filter[] = {
234 RETURN_ALLOW
235 };
236#if 0
237{
238 int i;
239 unsigned char *ptr = (unsigned char *) &filter[0];
240 for (i = 0; i < sizeof(filter); i++, ptr++)
241 printf("%x, ", (*ptr) & 0xff);
242 printf("\n");
243}
244#endif
245 memcpy(&sfilter[sfilter_index], filter, sizeof(filter));
246 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
247}
248
249static void filter_end_whitelist(void) {
250 assert(sfilter);
251 assert(sfilter_alloc_size);
252 assert(sfilter_index);
253 if (arg_debug)
254 printf("Ending syscall filter\n");
255
256 if ((sfilter_index + 2) > sfilter_alloc_size)
257 filter_realloc();
258
259 struct sock_filter filter[] = {
260 KILL_PROCESS
261 };
262#if 0
263{
264 int i;
265 unsigned char *ptr = (unsigned char *) &filter[0];
266 for (i = 0; i < sizeof(filter); i++, ptr++)
267 printf("%x, ", (*ptr) & 0xff);
268 printf("\n");
269}
270#endif
271 memcpy(&sfilter[sfilter_index], filter, sizeof(filter));
272 sfilter_index += sizeof(filter) / sizeof(struct sock_filter);
273}
274
275 24
276// save seccomp filter in /run/firejail/mnt/seccomp 25int seccomp_load(const char *fname) {
277static void write_seccomp_file(void) { 26 assert(fname);
278 fs_build_mnt_dir();
279 assert(sfilter);
280
281 int fd = open(RUN_SECCOMP_CFG, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
282 if (fd == -1)
283 errExit("open");
284
285 if (arg_debug)
286 printf("Save seccomp filter, size %u bytes\n", (unsigned) (sfilter_index * sizeof(struct sock_filter)));
287 errno = 0;
288 ssize_t sz = write(fd, sfilter, sfilter_index * sizeof(struct sock_filter));
289 if (sz != (ssize_t)(sfilter_index * sizeof(struct sock_filter))) {
290 fprintf(stderr, "Error: cannot save seccomp filter\n");
291 exit(1);
292 }
293 SET_PERMS_FD(fd, 0, 0, S_IRUSR | S_IWUSR);
294 close(fd);
295}
296
297// read seccomp filter from /run/firejail/mnt/seccomp
298static void read_seccomp_file(const char *fname) {
299 assert(sfilter == NULL && sfilter_index == 0);
300 27
301 // check file 28 // check file
302 struct stat s; 29 struct stat s;
303 if (stat(fname, &s) == -1) { 30 if (stat(fname, &s) == -1) {
304 fprintf(stderr, "Warning: seccomp file not found\n"); 31 fprintf(stderr, "Error: cannot read protocol filter file\n");
305 return;
306 }
307 ssize_t sz = s.st_size;
308 if (sz == 0 || (sz % sizeof(struct sock_filter)) != 0) {
309 fprintf(stderr, "Error: invalid seccomp file\n");
310 exit(1); 32 exit(1);
311 } 33 }
312 sfilter = malloc(sz); 34 int size = s.st_size;
313 if (!sfilter) 35 unsigned short entries = (unsigned short) size / (unsigned short) sizeof(struct sock_filter);
314 errExit("malloc"); 36//printf("size %d, entries %d\n", s.st_size, entries);
315 37
316 // read file 38 // read filter
317 /* coverity[toctou] */ 39 struct sock_filter filter[entries];
318 int fd = open(fname,O_RDONLY); 40 memset(&filter[0], 0, sizeof(filter));
319 if (fd == -1) 41 int src = open(fname, O_RDONLY);
320 errExit("open"); 42 int rd = 0;
321 errno = 0; 43 while (rd < size) {
322 ssize_t size = read(fd, sfilter, sz); 44 int rv = read(src, (unsigned char *) filter + rd, size - rd);
323 if (size != sz) { 45 if (rv == -1) {
324 fprintf(stderr, "Error: invalid seccomp file\n"); 46 fprintf(stderr, "Error: cannot read %s file\n", fname);
325 exit(1); 47 exit(1);
48 }
49 rd += rv;
326 } 50 }
327 sfilter_index = sz / sizeof(struct sock_filter); 51 close(src);
328 52
329 if (arg_debug) 53 // install filter
330 printf("Read seccomp filter, size %u bytes\n", (unsigned) (sfilter_index * sizeof(struct sock_filter))); 54 struct sock_fprog prog = {
55 .len = entries,
56 .filter = filter,
57 };
331 58
332 close(fd); 59 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
60 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
61 return 1;
62 }
333 63
334 if (arg_debug) 64 return 0;
335 filter_debug();
336} 65}
337 66
67
68
69
338// i386 filter installed on amd64 architectures 70// i386 filter installed on amd64 architectures
339void seccomp_filter_32(void) { 71void seccomp_filter_32(void) {
340 // hardcoded syscall values 72 if (arg_debug)
341 struct sock_filter filter[] = { 73 printf("Build secondary 32-bit filter\n");
342 VALIDATE_ARCHITECTURE_32,
343 EXAMINE_SYSCALL,
344 BLACKLIST(21), // mount
345 BLACKLIST(52), // umount2
346// todo: implement --allow-debuggers
347 BLACKLIST(26), // ptrace
348 BLACKLIST(283), // kexec_load
349 BLACKLIST(341), // name_to_handle_at
350 BLACKLIST(342), // open_by_handle_at
351 BLACKLIST(127), // create_module
352 BLACKLIST(128), // init_module
353 BLACKLIST(350), // finit_module
354 BLACKLIST(129), // delete_module
355 BLACKLIST(110), // iopl
356 BLACKLIST(101), // ioperm
357 BLACKLIST(289), // ioprio_set
358 BLACKLIST(87), // swapon
359 BLACKLIST(115), // swapoff
360 BLACKLIST(103), // syslog
361 BLACKLIST(347), // process_vm_readv
362 BLACKLIST(348), // process_vm_writev
363 BLACKLIST(135), // sysfs
364 BLACKLIST(149), // _sysctl
365 BLACKLIST(124), // adjtimex
366 BLACKLIST(343), // clock_adjtime
367 BLACKLIST(253), // lookup_dcookie
368 BLACKLIST(336), // perf_event_open
369 BLACKLIST(338), // fanotify_init
370 BLACKLIST(349), // kcmp
371 BLACKLIST(286), // add_key
372 BLACKLIST(287), // request_key
373 BLACKLIST(288), // keyctl
374 BLACKLIST(86), // uselib
375 BLACKLIST(51), // acct
376 BLACKLIST(123), // modify_ldt
377 BLACKLIST(217), // pivot_root
378 BLACKLIST(245), // io_setup
379 BLACKLIST(246), // io_destroy
380 BLACKLIST(247), // io_getevents
381 BLACKLIST(248), // io_submit
382 BLACKLIST(249), // io_cancel
383 BLACKLIST(257), // remap_file_pages
384 BLACKLIST(274), // mbind
385 BLACKLIST(275), // get_mempolicy
386 BLACKLIST(276), // set_mempolicy
387 BLACKLIST(294), // migrate_pages
388 BLACKLIST(317), // move_pages
389 BLACKLIST(316), // vmsplice
390 BLACKLIST(61), // chroot
391 BLACKLIST(88), // reboot
392 BLACKLIST(169), // nfsservctl
393 BLACKLIST(130), // get_kernel_syms
394
395 RETURN_ALLOW
396 };
397 74
398 struct sock_fprog prog = { 75 // build the seccomp filter as a regular user
399 .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])), 76 int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4,
400 .filter = filter, 77 PATH_FSECCOMP, "secondary", "32", RUN_SECCOMP_I386);
401 }; 78 if (rv)
79 exit(rv);
402 80
403 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { 81 if (seccomp_load(RUN_SECCOMP_I386) == 0) {
404 ; 82 if (arg_debug)
405 } 83 printf("Dual i386/amd64 seccomp filter configured\n");
406 else if (arg_debug) {
407 printf("Dual i386/amd64 seccomp filter configured\n");
408 } 84 }
409} 85}
410 86
411// amd64 filter installed on i386 architectures 87// amd64 filter installed on i386 architectures
412void seccomp_filter_64(void) { 88void seccomp_filter_64(void) {
413 // hardcoded syscall values 89 if (arg_debug)
414 struct sock_filter filter[] = { 90 printf("Build secondary 64-bit filter\n");
415 VALIDATE_ARCHITECTURE_64,
416 EXAMINE_SYSCALL,
417 BLACKLIST(165), // mount
418 BLACKLIST(166), // umount2
419// todo: implement --allow-debuggers
420 BLACKLIST(101), // ptrace
421 BLACKLIST(246), // kexec_load
422 BLACKLIST(304), // open_by_handle_at
423 BLACKLIST(303), // name_to_handle_at
424 BLACKLIST(174), // create_module
425 BLACKLIST(175), // init_module
426 BLACKLIST(313), // finit_module
427 BLACKLIST(176), // delete_module
428 BLACKLIST(172), // iopl
429 BLACKLIST(173), // ioperm
430 BLACKLIST(251), // ioprio_set
431 BLACKLIST(167), // swapon
432 BLACKLIST(168), // swapoff
433 BLACKLIST(103), // syslog
434 BLACKLIST(310), // process_vm_readv
435 BLACKLIST(311), // process_vm_writev
436 BLACKLIST(139), // sysfs
437 BLACKLIST(156), // _sysctl
438 BLACKLIST(159), // adjtimex
439 BLACKLIST(305), // clock_adjtime
440 BLACKLIST(212), // lookup_dcookie
441 BLACKLIST(298), // perf_event_open
442 BLACKLIST(300), // fanotify_init
443 BLACKLIST(312), // kcmp
444 BLACKLIST(248), // add_key
445 BLACKLIST(249), // request_key
446 BLACKLIST(250), // keyctl
447 BLACKLIST(134), // uselib
448 BLACKLIST(163), // acct
449 BLACKLIST(154), // modify_ldt
450 BLACKLIST(155), // pivot_root
451 BLACKLIST(206), // io_setup
452 BLACKLIST(207), // io_destroy
453 BLACKLIST(208), // io_getevents
454 BLACKLIST(209), // io_submit
455 BLACKLIST(210), // io_cancel
456 BLACKLIST(216), // remap_file_pages
457 BLACKLIST(237), // mbind
458 BLACKLIST(239), // get_mempolicy
459 BLACKLIST(238), // set_mempolicy
460 BLACKLIST(256), // migrate_pages
461 BLACKLIST(279), // move_pages
462 BLACKLIST(278), // vmsplice
463 BLACKLIST(161), // chroot
464 BLACKLIST(184), // tuxcall
465 BLACKLIST(169), // reboot
466 BLACKLIST(180), // nfsservctl
467 BLACKLIST(177), // get_kernel_syms
468
469 RETURN_ALLOW
470 };
471 91
472 struct sock_fprog prog = { 92 // build the seccomp filter as a regular user
473 .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])), 93 int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4,
474 .filter = filter, 94 PATH_FSECCOMP, "secondary", "64", RUN_SECCOMP_AMD64);
475 }; 95 if (rv)
96 exit(rv);
476 97
477 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { 98 if (seccomp_load(RUN_SECCOMP_AMD64) == 0) {
478 ; 99 if (arg_debug)
479 } 100 printf("Dual i386/amd64 seccomp filter configured\n");
480 else if (arg_debug) {
481 printf("Dual i386/amd64 seccomp filter configured\n");
482 } 101 }
483} 102}
484 103
485 104
486// drop filter for seccomp option 105// drop filter for seccomp option
487int seccomp_filter_drop(int enforce_seccomp) { 106int seccomp_filter_drop(int enforce_seccomp) {
488 filter_init();
489
490 // default seccomp 107 // default seccomp
491 if (cfg.seccomp_list_drop == NULL) { 108 if (cfg.seccomp_list_drop == NULL && cfg.seccomp_list == NULL) {
492#if defined(__x86_64__) 109#if defined(__x86_64__)
493 seccomp_filter_32(); 110 seccomp_filter_32();
494#endif 111#endif
495#if defined(__i386__) 112#if defined(__i386__)
496 seccomp_filter_64(); 113 seccomp_filter_64();
497#endif 114#endif
498 115 if (arg_debug)
499#ifdef SYS_mount 116 printf("Build default seccomp filter\n");
500 filter_add_blacklist(SYS_mount, 0); 117 // build the seccomp filter as a regular user
501#endif 118 int rv;
502#ifdef SYS_umount2 119 if (arg_allow_debuggers)
503 filter_add_blacklist(SYS_umount2, 0); 120 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4,
504#endif 121 PATH_FSECCOMP, "default", RUN_SECCOMP_CFG, "allow-debuggers");
505 122 else
506 if (!arg_allow_debuggers) { 123 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3,
507#ifdef SYS_ptrace 124 PATH_FSECCOMP, "default", RUN_SECCOMP_CFG);
508 filter_add_blacklist(SYS_ptrace, 0); 125 if (rv)
509#endif 126 exit(rv);
510 }
511
512#ifdef SYS_kexec_load
513 filter_add_blacklist(SYS_kexec_load, 0);
514#endif
515#ifdef SYS_kexec_file_load
516 filter_add_blacklist(SYS_kexec_file_load, 0);
517#endif
518#ifdef SYS_open_by_handle_at
519 filter_add_blacklist(SYS_open_by_handle_at, 0);
520#endif
521#ifdef SYS_name_to_handle_at
522 filter_add_blacklist(SYS_name_to_handle_at, 0);
523#endif
524#ifdef SYS_init_module
525 filter_add_blacklist(SYS_init_module, 0);
526#endif
527#ifdef SYS_finit_module // introduced in 2013
528 filter_add_blacklist(SYS_finit_module, 0);
529#endif
530#ifdef SYS_create_module
531 filter_add_blacklist(SYS_create_module, 0);
532#endif
533#ifdef SYS_delete_module
534 filter_add_blacklist(SYS_delete_module, 0);
535#endif
536#ifdef SYS_iopl
537 filter_add_blacklist(SYS_iopl, 0);
538#endif
539#ifdef SYS_ioperm
540 filter_add_blacklist(SYS_ioperm, 0);
541#endif
542#ifdef SYS_ioprio_set
543 filter_add_blacklist(SYS_ioprio_set, 0);
544#endif
545#ifdef SYS_ni_syscall // new io permissions call on arm devices
546 filter_add_blacklist(SYS_ni_syscall, 0);
547#endif
548#ifdef SYS_swapon
549 filter_add_blacklist(SYS_swapon, 0);
550#endif
551#ifdef SYS_swapoff
552 filter_add_blacklist(SYS_swapoff, 0);
553#endif
554#ifdef SYS_syslog
555 filter_add_blacklist(SYS_syslog, 0);
556#endif
557 if (!arg_allow_debuggers) {
558#ifdef SYS_process_vm_readv
559 filter_add_blacklist(SYS_process_vm_readv, 0);
560#endif
561 }
562
563#ifdef SYS_process_vm_writev
564 filter_add_blacklist(SYS_process_vm_writev, 0);
565#endif
566
567// mknod removed in 0.9.29 - it brakes Zotero extension
568//#ifdef SYS_mknod
569// filter_add_blacklist(SYS_mknod, 0);
570//#endif
571
572 // new syscalls in 0.9,23
573#ifdef SYS_sysfs
574 filter_add_blacklist(SYS_sysfs, 0);
575#endif
576#ifdef SYS__sysctl
577 filter_add_blacklist(SYS__sysctl, 0);
578#endif
579#ifdef SYS_adjtimex
580 filter_add_blacklist(SYS_adjtimex, 0);
581#endif
582#ifdef SYS_clock_adjtime
583 filter_add_blacklist(SYS_clock_adjtime, 0);
584#endif
585#ifdef SYS_lookup_dcookie
586 filter_add_blacklist(SYS_lookup_dcookie, 0);
587#endif
588#ifdef SYS_perf_event_open
589 filter_add_blacklist(SYS_perf_event_open, 0);
590#endif
591#ifdef SYS_fanotify_init
592 filter_add_blacklist(SYS_fanotify_init, 0);
593#endif
594#ifdef SYS_kcmp
595 filter_add_blacklist(SYS_kcmp, 0);
596#endif
597
598// 0.9.32
599#ifdef SYS_add_key
600 filter_add_blacklist(SYS_add_key, 0);
601#endif
602#ifdef SYS_request_key
603 filter_add_blacklist(SYS_request_key, 0);
604#endif
605#ifdef SYS_keyctl
606 filter_add_blacklist(SYS_keyctl, 0);
607#endif
608#ifdef SYS_uselib
609 filter_add_blacklist(SYS_uselib, 0);
610#endif
611#ifdef SYS_acct
612 filter_add_blacklist(SYS_acct, 0);
613#endif
614#ifdef SYS_modify_ldt
615 filter_add_blacklist(SYS_modify_ldt, 0);
616#endif
617 //#ifdef SYS_unshare
618 // filter_add_blacklist(SYS_unshare, 0);
619 //#endif
620#ifdef SYS_pivot_root
621 filter_add_blacklist(SYS_pivot_root, 0);
622#endif
623 //#ifdef SYS_quotactl
624 // filter_add_blacklist(SYS_quotactl, 0);
625 //#endif
626#ifdef SYS_io_setup
627 filter_add_blacklist(SYS_io_setup, 0);
628#endif
629#ifdef SYS_io_destroy
630 filter_add_blacklist(SYS_io_destroy, 0);
631#endif
632#ifdef SYS_io_getevents
633 filter_add_blacklist(SYS_io_getevents, 0);
634#endif
635#ifdef SYS_io_submit
636 filter_add_blacklist(SYS_io_submit, 0);
637#endif
638#ifdef SYS_io_cancel
639 filter_add_blacklist(SYS_io_cancel, 0);
640#endif
641#ifdef SYS_remap_file_pages
642 filter_add_blacklist(SYS_remap_file_pages, 0);
643#endif
644#ifdef SYS_mbind
645 filter_add_blacklist(SYS_mbind, 0);
646#endif
647#ifdef SYS_get_mempolicy
648 filter_add_blacklist(SYS_get_mempolicy, 0);
649#endif
650#ifdef SYS_set_mempolicy
651 filter_add_blacklist(SYS_set_mempolicy, 0);
652#endif
653#ifdef SYS_migrate_pages
654 filter_add_blacklist(SYS_migrate_pages, 0);
655#endif
656#ifdef SYS_move_pages
657 filter_add_blacklist(SYS_move_pages, 0);
658#endif
659#ifdef SYS_vmsplice
660 filter_add_blacklist(SYS_vmsplice, 0);
661#endif
662#ifdef SYS_chroot
663 filter_add_blacklist(SYS_chroot, 0);
664#endif
665 //#ifdef SYS_set_robust_list
666 // filter_add_blacklist(SYS_set_robust_list, 0);
667 //#endif
668 //#ifdef SYS_get_robust_list
669 // filter_add_blacklist(SYS_get_robust_list, 0);
670 //#endif
671
672 // CHECK_SECCOMP(seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(clone), 1,
673 // SCMP_A0(SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER)));
674
675// 0.9.39
676#ifdef SYS_tuxcall
677 filter_add_blacklist(SYS_tuxcall, 0);
678#endif
679#ifdef SYS_reboot
680 filter_add_blacklist(SYS_reboot, 0);
681#endif
682#ifdef SYS_nfsservctl
683 filter_add_blacklist(SYS_nfsservctl, 0);
684#endif
685#ifdef SYS_get_kernel_syms
686 filter_add_blacklist(SYS_get_kernel_syms, 0);
687#endif
688
689 } 127 }
690 128
691 // default seccomp filter with additional drop list 129 // default seccomp filter with additional drop list
692 if (cfg.seccomp_list && cfg.seccomp_list_drop == NULL) { 130 else if (cfg.seccomp_list && cfg.seccomp_list_drop == NULL) {
693 if (syscall_check_list(cfg.seccomp_list, filter_add_blacklist, 0)) { 131#if defined(__x86_64__)
694 fprintf(stderr, "Error: cannot load seccomp filter\n"); 132 seccomp_filter_32();
133#endif
134#if defined(__i386__)
135 seccomp_filter_64();
136#endif
137 if (arg_debug)
138 printf("Build default+drop seccomp filter\n");
139 if (strlen(cfg.seccomp_list) == 0) {
140 fprintf(stderr, "Error: empty syscall lists are not allowed\n");
695 exit(1); 141 exit(1);
696 } 142 }
143
144 // build the seccomp filter as a regular user
145 int rv;
146 if (arg_allow_debuggers)
147 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 6,
148 PATH_FSECCOMP, "default", "drop", RUN_SECCOMP_CFG, cfg.seccomp_list, "allow-debuggers");
149 else
150 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 5,
151 PATH_FSECCOMP, "default", "drop", RUN_SECCOMP_CFG, cfg.seccomp_list);
152 if (rv)
153 exit(rv);
697 } 154 }
698 // drop list 155
156 // drop list without defaults - secondary filters are not installed
699 else if (cfg.seccomp_list == NULL && cfg.seccomp_list_drop) { 157 else if (cfg.seccomp_list == NULL && cfg.seccomp_list_drop) {
700 if (syscall_check_list(cfg.seccomp_list_drop, filter_add_blacklist, 0)) { 158 if (arg_debug)
701 fprintf(stderr, "Error: cannot load seccomp filter\n"); 159 printf("Build drop seccomp filter\n");
160 if (strlen(cfg.seccomp_list_drop) == 0) {
161 fprintf(stderr, "Error: empty syscall lists are not allowed\n");
702 exit(1); 162 exit(1);
703 } 163 }
704 }
705
706
707 filter_end_blacklist();
708 if (arg_debug)
709 filter_debug();
710
711 // save seccomp filter in /tmp/firejail/mnt/seccomp
712 // in order to use it in --join operations
713 write_seccomp_file();
714
715 164
716 struct sock_fprog prog = { 165 // build the seccomp filter as a regular user
717 .len = sfilter_index, 166 int rv;
718 .filter = sfilter, 167 if (arg_allow_debuggers)
719 }; 168 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 5,
720 169 PATH_FSECCOMP, "drop", RUN_SECCOMP_CFG, cfg.seccomp_list_drop, "allow-debuggers");
721 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
722 if (enforce_seccomp) {
723 fprintf(stderr, "Error: a seccomp-enabled Linux kernel is required, exiting...\n");
724 exit(1);
725 }
726 else 170 else
727 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n"); 171 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4,
172 PATH_FSECCOMP, "drop", RUN_SECCOMP_CFG, cfg.seccomp_list_drop);
728 173
729 return 1; 174 if (rv)
175 exit(rv);
176 }
177 else {
178 assert(0);
730 } 179 }
731 180
732 return 0; 181 // load the filter
182 if (seccomp_load(RUN_SECCOMP_CFG) == 0) {
183 if (arg_debug)
184 printf("seccomp filter configured\n");
185 }
186 else if (enforce_seccomp) {
187 fprintf(stderr, "Error: a seccomp-enabled Linux kernel is required, exiting...\n");
188 exit(1);
189 }
190
191 if (arg_debug)
192 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3,
193 PATH_FSECCOMP, "print", RUN_SECCOMP_CFG);
194
195 return seccomp_load(RUN_SECCOMP_CFG);
733} 196}
734 197
735// keep filter for seccomp option 198// keep filter for seccomp option
736int seccomp_filter_keep(void) { 199int seccomp_filter_keep(void) {
737 filter_init(); 200 if (arg_debug)
738 201 printf("Build drop seccomp filter\n");
739 // these 4 syscalls are used by firejail after the seccomp filter is initialized 202 if (strlen(cfg.seccomp_list_keep) == 0) {
740 filter_add_whitelist(SYS_setuid, 0); 203 fprintf(stderr, "Error: empty syscall lists are not allowed\n");
741 filter_add_whitelist(SYS_setgid, 0); 204 exit(1);
742 filter_add_whitelist(SYS_setgroups, 0);
743 filter_add_whitelist(SYS_dup, 0);
744
745 // apply keep list
746 if (cfg.seccomp_list_keep) {
747 if (syscall_check_list(cfg.seccomp_list_keep, filter_add_whitelist, 0)) {
748 fprintf(stderr, "Error: cannot load seccomp filter\n");
749 exit(1);
750 }
751 } 205 }
752 206
753 filter_end_whitelist(); 207 // build the seccomp filter as a regular user
208 int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4,
209 PATH_FSECCOMP, "keep", RUN_SECCOMP_CFG, cfg.seccomp_list_keep);
210 if (rv)
211 exit(rv);
754 if (arg_debug) 212 if (arg_debug)
755 filter_debug(); 213 printf("seccomp filter configured\n");
756
757 // save seccomp filter in /tmp/firejail/mnt/seccomp
758 // in order to use it in --join operations
759 write_seccomp_file();
760
761 214
762 struct sock_fprog prog = { 215
763 .len = sfilter_index, 216 return seccomp_load(RUN_SECCOMP_CFG);
764 .filter = sfilter,
765 };
766
767 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
768 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
769 return 1;
770 }
771 else if (arg_debug) {
772 printf("seccomp enabled\n");
773 }
774
775 return 0;
776} 217}
777 218
778// errno filter for seccomp option 219// errno filter for seccomp option
779int seccomp_filter_errno(void) { 220int seccomp_filter_errno(void) {
221#if 0 //todo: disabled temporarely, bring it back
780 int i; 222 int i;
781 int higest_errno = errno_highest_nr(); 223 int higest_errno = errno_highest_nr();
782 filter_init(); 224 filter_init();
@@ -796,45 +238,14 @@ int seccomp_filter_errno(void) {
796 if (arg_debug) 238 if (arg_debug)
797 filter_debug(); 239 filter_debug();
798 240
799 // save seccomp filter in /tmp/firejail/mnt/seccomp 241 // save seccomp filter in /run/firejail/mnt/seccomp
800 // in order to use it in --join operations 242 // in order to use it in --join operations
801 write_seccomp_file(); 243 write_seccomp_file();
802 244 return seccomp_load(RUN_SECCOMP_CFG);
803 struct sock_fprog prog = { 245#else
804 .len = sfilter_index, 246printf("*** --seccomp.<errno> is temporarily disabled, it will be brought back soon ***\n");
805 .filter = sfilter,
806 };
807
808 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
809 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
810 return 1;
811 }
812 else if (arg_debug) {
813 printf("seccomp enabled\n");
814 }
815
816 return 0; 247 return 0;
817} 248#endif
818
819
820
821void seccomp_set(void) {
822 // read seccomp filter from /tmp/firejail/mnt/seccomp
823 read_seccomp_file(RUN_SECCOMP_CFG);
824
825 // apply filter
826 struct sock_fprog prog = {
827 .len = sfilter_index,
828 .filter = sfilter,
829 };
830
831 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
832 fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n");
833 return;
834 }
835 else if (arg_debug) {
836 printf("seccomp enabled\n");
837 }
838} 249}
839 250
840void seccomp_print_filter_name(const char *name) { 251void seccomp_print_filter_name(const char *name) {
@@ -891,10 +302,11 @@ void seccomp_print_filter(pid_t pid) {
891 exit(1); 302 exit(1);
892 } 303 }
893 304
894 // read and print the filter 305 // read and print the filter - run this as root, the user doesn't have access
895 read_seccomp_file(fname); 306 int rv = sbox_run(SBOX_ROOT | SBOX_SECCOMP, 3,
896 drop_privs(1); 307 PATH_FSECCOMP, "print", fname);
897 filter_debug(); 308 if (rv)
309 exit(rv);
898 free(fname); 310 free(fname);
899 311
900 exit(0); 312 exit(0);
diff --git a/src/firejail/util.c b/src/firejail/util.c
index 7aa0ae0e8..9752504e5 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -171,11 +171,17 @@ void logerr(const char *msg) {
171} 171}
172 172
173 173
174// return -1 if error, 0 if no error 174// return -1 if error, 0 if no error; if destname already exists, return error
175int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) { 175int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) {
176 assert(srcname); 176 assert(srcname);
177 assert(destname); 177 assert(destname);
178 178
179 struct stat s;
180 if (stat(destname, &s) == 0) {
181 fprintf(stderr, "Error: file %s already exists\n", destname);
182 return -1;
183 }
184
179 // open source 185 // open source
180 int src = open(srcname, O_RDONLY); 186 int src = open(srcname, O_RDONLY);
181 if (src < 0) { 187 if (src < 0) {
@@ -649,25 +655,14 @@ void invalid_filename(const char *fname) {
649} 655}
650 656
651 657
652uid_t get_tty_gid(void) { 658uid_t get_group_id(const char *group) {
653 // find tty group id 659 // find tty group id
654 gid_t ttygid = 0; 660 gid_t gid = 0;
655 struct group *g = getgrnam("tty"); 661 struct group *g = getgrnam(group);
656 if (g) 662 if (g)
657 ttygid = g->gr_gid; 663 gid = g->gr_gid;
658 664
659 return ttygid; 665 return gid;
660}
661
662
663uid_t get_audio_gid(void) {
664 // find tty group id
665 gid_t audiogid = 0;
666 struct group *g = getgrnam("audio");
667 if (g)
668 audiogid = g->gr_gid;
669
670 return audiogid;
671} 666}
672 667
673 668
@@ -701,3 +696,38 @@ void flush_stdin(void) {
701 } 696 }
702} 697}
703 698
699void create_empty_dir_as_root(const char *dir, mode_t mode) {
700 assert(dir);
701 struct stat s;
702
703 if (stat(dir, &s)) {
704 if (arg_debug)
705 printf("Creating empty %s directory\n", dir);
706 if (mkdir(dir, mode) == -1)
707 errExit("mkdir");
708 if (chmod(dir, mode) == -1)
709 errExit("chmod");
710 if (chown(dir, 0, 0) == -1)
711 errExit("chown");
712 ASSERT_PERMS(dir, 0, 0, mode);
713 }
714}
715
716void create_empty_file_as_root(const char *fname, mode_t mode) {
717 assert(fname);
718 struct stat s;
719
720 if (stat(fname, &s)) {
721 if (arg_debug)
722 printf("Creating empty %s file\n", fname);
723
724 FILE *fp = fopen(fname, "w");
725 if (!fp)
726 errExit("fopen");
727 SET_PERMS_STREAM(fp, 0, 0, S_IRUSR);
728 fclose(fp);
729 if (chmod(fname, mode) == -1)
730 errExit("chmod");
731 }
732}
733
diff --git a/src/firejail/x11.c b/src/firejail/x11.c
index d40d349e1..c79f1a74e 100644
--- a/src/firejail/x11.c
+++ b/src/firejail/x11.c
@@ -314,7 +314,7 @@ void x11_start_xephyr(int argc, char **argv) {
314 314
315 execvp(server_argv[0], server_argv); 315 execvp(server_argv[0], server_argv);
316 perror("execvp"); 316 perror("execvp");
317 exit(1); 317 _exit(1);
318 } 318 }
319 319
320 if (arg_debug) 320 if (arg_debug)
@@ -355,7 +355,7 @@ void x11_start_xephyr(int argc, char **argv) {
355 355
356 execvp(jail_argv[0], jail_argv); 356 execvp(jail_argv[0], jail_argv);
357 perror("execvp"); 357 perror("execvp");
358 exit(1); 358 _exit(1);
359 } 359 }
360 360
361 // cleanup 361 // cleanup
@@ -434,7 +434,7 @@ void x11_start_xpra(int argc, char **argv) {
434 434
435 execvp(server_argv[0], server_argv); 435 execvp(server_argv[0], server_argv);
436 perror("execvp"); 436 perror("execvp");
437 exit(1); 437 _exit(1);
438 } 438 }
439 439
440 // check X11 socket 440 // check X11 socket
@@ -480,7 +480,7 @@ void x11_start_xpra(int argc, char **argv) {
480 480
481 execvp(attach_argv[0], attach_argv); 481 execvp(attach_argv[0], attach_argv);
482 perror("execvp"); 482 perror("execvp");
483 exit(1); 483 _exit(1);
484 } 484 }
485 485
486 setenv("DISPLAY", display_str, 1); 486 setenv("DISPLAY", display_str, 1);
@@ -536,7 +536,7 @@ void x11_start_xpra(int argc, char **argv) {
536 } 536 }
537 execvp(stop_argv[0], stop_argv); 537 execvp(stop_argv[0], stop_argv);
538 perror("execvp"); 538 perror("execvp");
539 exit(1); 539 _exit(1);
540 } 540 }
541 541
542 // wait for xpra server to stop, 10 seconds limit 542 // wait for xpra server to stop, 10 seconds limit
@@ -672,7 +672,7 @@ void x11_xorg(void) {
672 execlp("/usr/bin/xauth", "/usr/bin/xauth", "-f", RUN_XAUTHORITY_SEC_FILE, 672 execlp("/usr/bin/xauth", "/usr/bin/xauth", "-f", RUN_XAUTHORITY_SEC_FILE,
673 "generate", display, "MIT-MAGIC-COOKIE-1", "untrusted", NULL); 673 "generate", display, "MIT-MAGIC-COOKIE-1", "untrusted", NULL);
674 674
675 exit(0); 675 _exit(0);
676 } 676 }
677 // wait for the child to finish 677 // wait for the child to finish
678 waitpid(child, NULL, 0); 678 waitpid(child, NULL, 0);
diff --git a/src/firemon/interface.c b/src/firemon/interface.c
index 5a89e1491..bceed93d3 100644
--- a/src/firemon/interface.c
+++ b/src/firemon/interface.c
@@ -146,7 +146,7 @@ static void print_sandbox(pid_t pid) {
146 return; 146 return;
147 net_ifprint(); 147 net_ifprint();
148 printf("\n"); 148 printf("\n");
149 exit(0); 149 _exit(0);
150 } 150 }
151 151
152 // wait for the child to finish 152 // wait for the child to finish
diff --git a/src/firemon/procevent.c b/src/firemon/procevent.c
index 188c10183..78a3a4fb2 100644
--- a/src/firemon/procevent.c
+++ b/src/firemon/procevent.c
@@ -28,6 +28,8 @@
28#include <arpa/inet.h> 28#include <arpa/inet.h>
29#include <time.h> 29#include <time.h>
30#include <fcntl.h> 30#include <fcntl.h>
31#include <sys/uio.h>
32
31#define PIDS_BUFLEN 4096 33#define PIDS_BUFLEN 4096
32#define SERVER_PORT 889 // 889-899 is left unassigned by IANA 34#define SERVER_PORT 889 // 889-899 is left unassigned by IANA
33 35
diff --git a/src/fnet/Makefile.in b/src/fnet/Makefile.in
new file mode 100644
index 000000000..b515d2333
--- /dev/null
+++ b/src/fnet/Makefile.in
@@ -0,0 +1,43 @@
1all: fnet
2
3prefix=@prefix@
4exec_prefix=@exec_prefix@
5libdir=@libdir@
6sysconfdir=@sysconfdir@
7
8VERSION=@PACKAGE_VERSION@
9NAME=@PACKAGE_NAME@
10HAVE_SECCOMP_H=@HAVE_SECCOMP_H@
11HAVE_SECCOMP=@HAVE_SECCOMP@
12HAVE_CHROOT=@HAVE_CHROOT@
13HAVE_BIND=@HAVE_BIND@
14HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@
15HAVE_NETWORK=@HAVE_NETWORK@
16HAVE_USERNS=@HAVE_USERNS@
17HAVE_X11=@HAVE_X11@
18HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@
19HAVE_WHITELIST=@HAVE_WHITELIST@
20HAVE_GLOBALCFG=@HAVE_GLOBALCFG@
21HAVE_APPARMOR=@HAVE_APPARMOR@
22HAVE_OVERLAYFS=@HAVE_OVERLAYFS@
23HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@
24EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
25
26H_FILE_LIST = $(sort $(wildcard *.[h]))
27C_FILE_LIST = $(sort $(wildcard *.c))
28OBJS = $(C_FILE_LIST:.c=.o)
29BINOBJS = $(foreach file, $(OBJS), $file)
30CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
31LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
32
33%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/libnetlink.h
34 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
35
36fnet: $(OBJS) ../lib/libnetlink.o ../lib/common.o
37 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/libnetlink.o $(LIBS) $(EXTRA_LDFLAGS)
38
39clean:; rm -f *.o fnet
40
41distclean: clean
42 rm -fr Makefile
43
diff --git a/src/fnet/arp.c b/src/fnet/arp.c
new file mode 100644
index 000000000..96684fdf9
--- /dev/null
+++ b/src/fnet/arp.c
@@ -0,0 +1,208 @@
1/*
2 * Copyright (C) 2014-2016 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#include "fnet.h"
21#include <sys/socket.h>
22#include <sys/ioctl.h>
23#include <linux/if_ether.h> //TCP/IP Protocol Suite for Linux
24#include <net/if.h>
25#include <netinet/in.h>
26#include <linux/ip.h>
27#include <linux/udp.h>
28#include <linux/tcp.h>
29#include <linux/if_packet.h>
30
31typedef struct arp_hdr_t {
32 uint16_t htype;
33 uint16_t ptype;
34 uint8_t hlen;
35 uint8_t plen;
36 uint16_t opcode;
37 uint8_t sender_mac[6];
38 uint8_t sender_ip[4];
39 uint8_t target_mac[6];
40 uint8_t target_ip[4];
41} ArpHdr;
42
43
44// scan interface (--scan option)
45void arp_scan(const char *dev, uint32_t ifip, uint32_t ifmask) {
46 assert(dev);
47 assert(ifip);
48
49// printf("Scanning interface %s (%d.%d.%d.%d/%d)\n",
50// dev, PRINT_IP(ifip & ifmask), mask2bits(ifmask));
51
52 if (strlen(dev) > IFNAMSIZ) {
53 fprintf(stderr, "Error: invalid network device name %s\n", dev);
54 exit(1);
55 }
56
57 // find interface mac address
58 int sock;
59 if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
60 errExit("socket");
61 struct ifreq ifr;
62 memset(&ifr, 0, sizeof (ifr));
63 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
64 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
65 errExit("ioctl");
66 close(sock);
67 uint8_t mac[6];
68 memcpy (mac, ifr.ifr_hwaddr.sa_data, 6);
69
70 // open layer2 socket
71 if ((sock = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0)
72 errExit("socket");
73
74 // try all possible ip addresses in ascending order
75 uint32_t range = ~ifmask + 1; // the number of potential addresses
76 // this software is not supported for /31 networks
77 if (range < 4) {
78 fprintf(stderr, "Warning: this option is not supported for /31 networks\n");
79 close(sock);
80 return;
81 }
82
83 uint32_t dest = (ifip & ifmask) + 1;
84 uint32_t last = dest + range - 1;
85 uint32_t src = htonl(ifip);
86
87 // wait not more than one second for an answer
88 int header_printed = 0;
89 uint32_t last_ip = 0;
90 struct timeval ts;
91 ts.tv_sec = 2; // 2 seconds receive timeout
92 ts.tv_usec = 0;
93
94 while (1) {
95 fd_set rfds;
96 FD_ZERO(&rfds);
97 FD_SET(sock, &rfds);
98 fd_set wfds;
99 FD_ZERO(&wfds);
100 FD_SET(sock, &wfds);
101 int maxfd = sock;
102
103 uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
104 memset(frame, 0, ETH_FRAME_LEN);
105
106 int nready;
107 if (dest < last)
108 nready = select(maxfd + 1, &rfds, &wfds, (fd_set *) 0, NULL);
109 else
110 nready = select(maxfd + 1, &rfds, (fd_set *) 0, (fd_set *) 0, &ts);
111
112 if (nready < 0)
113 errExit("select");
114
115 if (nready == 0) { // timeout
116 break;
117 }
118
119 if (FD_ISSET(sock, &wfds) && dest < last) {
120 // configure layer2 socket address information
121 struct sockaddr_ll addr;
122 memset(&addr, 0, sizeof(addr));
123 if ((addr.sll_ifindex = if_nametoindex(dev)) == 0)
124 errExit("if_nametoindex");
125 addr.sll_family = AF_PACKET;
126 memcpy (addr.sll_addr, mac, 6);
127 addr.sll_halen = htons(6);
128
129 // build the arp packet header
130 ArpHdr hdr;
131 memset(&hdr, 0, sizeof(hdr));
132 hdr.htype = htons(1);
133 hdr.ptype = htons(ETH_P_IP);
134 hdr.hlen = 6;
135 hdr.plen = 4;
136 hdr.opcode = htons(1); //ARPOP_REQUEST
137 memcpy(hdr.sender_mac, mac, 6);
138 memcpy(hdr.sender_ip, (uint8_t *)&src, 4);
139 uint32_t dst = htonl(dest);
140 memcpy(hdr.target_ip, (uint8_t *)&dst, 4);
141
142 // build ethernet frame
143 uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
144 memset(frame, 0, sizeof(frame));
145 frame[0] = frame[1] = frame[2] = frame[3] = frame[4] = frame[5] = 0xff;
146 memcpy(frame + 6, mac, 6);
147 frame[12] = ETH_P_ARP / 256;
148 frame[13] = ETH_P_ARP % 256;
149 memcpy (frame + 14, &hdr, sizeof(hdr));
150
151 // send packet
152 int len;
153 if ((len = sendto (sock, frame, 14 + sizeof(ArpHdr), 0, (struct sockaddr *) &addr, sizeof (addr))) <= 0)
154 errExit("send");
155//printf("send %d bytes to %d.%d.%d.%d\n", len, PRINT_IP(dest));
156 fflush(0);
157 dest++;
158 }
159
160 if (FD_ISSET(sock, &rfds)) {
161 // read the incoming packet
162 int len = recvfrom(sock, frame, ETH_FRAME_LEN, 0, NULL, NULL);
163 if (len < 0) {
164 perror("recvfrom");
165 }
166
167 // parse the incoming packet
168 if ((unsigned int) len < 14 + sizeof(ArpHdr))
169 continue;
170
171 // look only at ARP packets
172 if (frame[12] != (ETH_P_ARP / 256) || frame[13] != (ETH_P_ARP % 256))
173 continue;
174
175 ArpHdr hdr;
176 memcpy(&hdr, frame + 14, sizeof(ArpHdr));
177
178 if (hdr.opcode == htons(2)) {
179 // check my mac and my address
180 if (memcmp(mac, hdr.target_mac, 6) != 0)
181 continue;
182 uint32_t ip;
183 memcpy(&ip, hdr.target_ip, 4);
184 if (ip != src)
185 continue;
186 memcpy(&ip, hdr.sender_ip, 4);
187 ip = ntohl(ip);
188
189 if (ip == last_ip) // filter duplicates
190 continue;
191 last_ip = ip;
192
193 // printing
194 if (header_printed == 0) {
195 printf(" Network scan:\n");
196 header_printed = 1;
197 }
198 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
199 PRINT_MAC(hdr.sender_mac), PRINT_IP(ip));
200 }
201 }
202 }
203
204 close(sock);
205}
206
207
208
diff --git a/src/fnet/fnet.h b/src/fnet/fnet.h
new file mode 100644
index 000000000..0c5e5baef
--- /dev/null
+++ b/src/fnet/fnet.h
@@ -0,0 +1,49 @@
1 /*
2 * Copyright (C) 2014-2016 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#ifndef FNET_H
21#define FNET_H
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <assert.h>
27#include "../include/common.h"
28
29// veth.c
30int net_create_veth(const char *dev, const char *nsdev, unsigned pid);
31int net_create_macvlan(const char *dev, const char *parent, unsigned pid);
32int net_move_interface(const char *dev, unsigned pid);
33
34// interface.c
35void net_bridge_add_interface(const char *bridge, const char *dev);
36void net_if_up(const char *ifname);
37int net_get_mtu(const char *ifname);
38void net_set_mtu(const char *ifname, int mtu);
39void net_ifprint(int scan);
40int net_get_mac(const char *ifname, unsigned char mac[6]);
41void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask, int mtu);
42int net_if_mac(const char *ifname, const unsigned char mac[6]);
43void net_if_ip6(const char *ifname, const char *addr6);
44
45
46// arp.c
47void arp_scan(const char *dev, uint32_t ifip, uint32_t ifmask);
48
49#endif
diff --git a/src/fnet/interface.c b/src/fnet/interface.c
new file mode 100644
index 000000000..67af062bf
--- /dev/null
+++ b/src/fnet/interface.c
@@ -0,0 +1,395 @@
1 /*
2 * Copyright (C) 2014-2016 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#include "fnet.h"
22#include <arpa/inet.h>
23#include <sys/socket.h>
24#include <sys/ioctl.h>
25#include <netdb.h>
26#include <ifaddrs.h>
27#include <net/if.h>
28#include <net/if_arp.h>
29#include <net/route.h>
30#include <linux/if_bridge.h>
31
32// add a veth device to a bridge
33void net_bridge_add_interface(const char *bridge, const char *dev) {
34 if (strlen(bridge) > IFNAMSIZ) {
35 fprintf(stderr, "Error fnet: invalid network device name %s\n", bridge);
36 exit(1);
37 }
38
39 // somehow adding the interface to the bridge resets MTU on bridge device!!!
40 // workaround: restore MTU on the bridge device
41 // todo: put a real fix in
42 int mtu1 = net_get_mtu(bridge);
43
44 struct ifreq ifr;
45 int err;
46 int ifindex = if_nametoindex(dev);
47
48 if (ifindex <= 0)
49 errExit("if_nametoindex");
50
51 int sock;
52 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
53 errExit("socket");
54
55 memset(&ifr, 0, sizeof(ifr));
56 strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
57#ifdef SIOCBRADDIF
58 ifr.ifr_ifindex = ifindex;
59 err = ioctl(sock, SIOCBRADDIF, &ifr);
60 if (err < 0)
61#endif
62 {
63 unsigned long args[4] = { BRCTL_ADD_IF, ifindex, 0, 0 };
64
65 ifr.ifr_data = (char *) args;
66 err = ioctl(sock, SIOCDEVPRIVATE, &ifr);
67 }
68 (void) err;
69 close(sock);
70
71 int mtu2 = net_get_mtu(bridge);
72 if (mtu1 != mtu2) {
73 net_set_mtu(bridge, mtu1);
74 }
75}
76
77
78// bring interface up
79void net_if_up(const char *ifname) {
80 if (strlen(ifname) > IFNAMSIZ) {
81 fprintf(stderr, "Error fnet: invalid network device name %s\n", ifname);
82 exit(1);
83 }
84
85 int sock = socket(AF_INET,SOCK_DGRAM,0);
86 if (sock < 0)
87 errExit("socket");
88
89 // get the existing interface flags
90 struct ifreq ifr;
91 memset(&ifr, 0, sizeof(ifr));
92 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
93 ifr.ifr_addr.sa_family = AF_INET;
94
95 // read the existing flags
96 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
97 close(sock);
98 printf("Error fnet: cannot bring up interface %s\n", ifname);
99 errExit("ioctl");
100 }
101
102 ifr.ifr_flags |= IFF_UP;
103
104 // set the new flags
105 if (ioctl( sock, SIOCSIFFLAGS, &ifr ) < 0) {
106 close(sock);
107 printf("Error fnet: cannot bring up interface %s\n", ifname);
108 errExit("ioctl");
109 }
110
111 // checking
112 // read the existing flags
113 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
114 close(sock);
115 printf("Error fnet: cannot bring up interface %s\n", ifname);
116 errExit("ioctl");
117 }
118
119 // wait not more than 500ms for the interface to come up
120 int cnt = 0;
121 while (cnt < 50) {
122 usleep(10000); // sleep 10ms
123
124 // read the existing flags
125 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
126 close(sock);
127 printf("Error fnet: cannot bring up interface %s\n", ifname);
128 errExit("ioctl");
129 }
130 if (ifr.ifr_flags & IFF_RUNNING)
131 break;
132 cnt++;
133 }
134
135 close(sock);
136}
137
138int net_get_mtu(const char *ifname) {
139 int mtu = 0;
140 if (strlen(ifname) > IFNAMSIZ) {
141 fprintf(stderr, "Error fnet: invalid network device name %s\n", ifname);
142 exit(1);
143 }
144
145 int s;
146 struct ifreq ifr;
147
148 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
149 errExit("socket");
150
151 memset(&ifr, 0, sizeof(ifr));
152 ifr.ifr_addr.sa_family = AF_INET;
153 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
154 if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) == 0)
155 mtu = ifr.ifr_mtu;
156 close(s);
157
158
159 return mtu;
160}
161
162void net_set_mtu(const char *ifname, int mtu) {
163 if (strlen(ifname) > IFNAMSIZ) {
164 fprintf(stderr, "Error fnet: invalid network device name %s\n", ifname);
165 exit(1);
166 }
167
168 int s;
169 struct ifreq ifr;
170
171 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
172 errExit("socket");
173
174 memset(&ifr, 0, sizeof(ifr));
175 ifr.ifr_addr.sa_family = AF_INET;
176 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
177 ifr.ifr_mtu = mtu;
178 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) != 0)
179 fprintf(stderr, "Warning fnet: cannot set mtu for interface %s\n", ifname);
180 close(s);
181}
182
183// scan interfaces in current namespace and print IP address/mask for each interface
184void net_ifprint(int scan) {
185 uint32_t ip;
186 uint32_t mask;
187 struct ifaddrs *ifaddr, *ifa;
188
189 if (getifaddrs(&ifaddr) == -1)
190 errExit("getifaddrs");
191
192 printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n",
193 "Interface", "MAC", "IP", "Mask", "Status");
194 // walk through the linked list
195 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
196 if (ifa->ifa_addr == NULL)
197 continue;
198
199 if (ifa->ifa_addr->sa_family == AF_INET) {
200 struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask;
201 mask = ntohl(si->sin_addr.s_addr);
202 si = (struct sockaddr_in *) ifa->ifa_addr;
203 ip = ntohl(si->sin_addr.s_addr);
204
205 // interface status
206 char *status;
207 if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
208 status = "UP";
209 else
210 status = "DOWN";
211
212 // ip address and mask
213 char ipstr[30];
214 sprintf(ipstr, "%d.%d.%d.%d", PRINT_IP(ip));
215 char maskstr[30];
216 sprintf(maskstr, "%d.%d.%d.%d", PRINT_IP(mask));
217
218 // mac address
219 unsigned char mac[6];
220 net_get_mac(ifa->ifa_name, mac);
221 char macstr[30];
222 if (strcmp(ifa->ifa_name, "lo") == 0)
223 macstr[0] = '\0';
224 else
225 sprintf(macstr, "%02x:%02x:%02x:%02x:%02x:%02x", PRINT_MAC(mac));
226
227 // print
228 printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n",
229 ifa->ifa_name, macstr, ipstr, maskstr, status);
230
231 // network scanning
232 if (!scan) // scanning disabled
233 continue;
234 if (strcmp(ifa->ifa_name, "lo") == 0) // no loopbabck scanning
235 continue;
236 if (mask2bits(mask) < 16) // not scanning large networks
237 continue;
238 if (!ip) // if not configured
239 continue;
240 // only if the interface is up and running
241 if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
242 arp_scan(ifa->ifa_name, ip, mask);
243 }
244 }
245 freeifaddrs(ifaddr);
246}
247
248int net_get_mac(const char *ifname, unsigned char mac[6]) {
249
250 struct ifreq ifr;
251 int sock;
252
253 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
254 errExit("socket");
255
256 memset(&ifr, 0, sizeof(ifr));
257 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
258 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
259
260 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1)
261 errExit("ioctl");
262 memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
263
264 close(sock);
265 return 0;
266}
267
268// configure interface ipv4 address
269void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask, int mtu) {
270 if (strlen(ifname) > IFNAMSIZ) {
271 fprintf(stderr, "Error: invalid network device name %s\n", ifname);
272 exit(1);
273 }
274
275 int sock = socket(AF_INET,SOCK_DGRAM,0);
276 if (sock < 0)
277 errExit("socket");
278
279 struct ifreq ifr;
280 memset(&ifr, 0, sizeof(ifr));
281 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
282 ifr.ifr_addr.sa_family = AF_INET;
283
284 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(ip);
285 if (ioctl( sock, SIOCSIFADDR, &ifr ) < 0) {
286 close(sock);
287 errExit("ioctl");
288 }
289
290 if (ip != 0) {
291 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(mask);
292 if (ioctl( sock, SIOCSIFNETMASK, &ifr ) < 0) {
293 close(sock);
294 errExit("ioctl");
295 }
296 }
297
298 // configure mtu
299 if (mtu > 0) {
300 ifr.ifr_mtu = mtu;
301 if (ioctl( sock, SIOCSIFMTU, &ifr ) < 0) {
302 close(sock);
303 errExit("ioctl");
304 }
305 }
306
307 close(sock);
308 usleep(10000); // sleep 10ms
309}
310
311int net_if_mac(const char *ifname, const unsigned char mac[6]) {
312 struct ifreq ifr;
313 int sock;
314
315 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
316 errExit("socket");
317
318 memset(&ifr, 0, sizeof(ifr));
319 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
320 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
321 memcpy(ifr.ifr_hwaddr.sa_data, mac, 6);
322
323 if (ioctl(sock, SIOCSIFHWADDR, &ifr) == -1)
324 errExit("ioctl");
325 close(sock);
326 return 0;
327}
328
329// configure interface ipv6 address
330// ex: firejail --net=eth0 --ip6=2001:0db8:0:f101::1/64
331struct ifreq6 {
332 struct in6_addr ifr6_addr;
333 uint32_t ifr6_prefixlen;
334 unsigned int ifr6_ifindex;
335};
336void net_if_ip6(const char *ifname, const char *addr6) {
337 if (strchr(addr6, ':') == NULL) {
338 fprintf(stderr, "Error fnet: invalid IPv6 address %s\n", addr6);
339 exit(1);
340 }
341
342 // extract prefix
343 unsigned long prefix;
344 char *ptr;
345 if ((ptr = strchr(addr6, '/'))) {
346 prefix = atol(ptr + 1);
347 if (prefix > 128) {
348 fprintf(stderr, "Error fnet: invalid prefix for IPv6 address %s\n", addr6);
349 exit(1);
350 }
351 *ptr = '\0'; // mark the end of the address
352 }
353 else
354 prefix = 128;
355
356 // extract address
357 struct sockaddr_in6 sin6;
358 memset(&sin6, 0, sizeof(sin6));
359 sin6.sin6_family = AF_INET6;
360 int rv = inet_pton(AF_INET6, addr6, sin6.sin6_addr.s6_addr);
361 if (rv <= 0) {
362 fprintf(stderr, "Error fnet: invalid IPv6 address %s\n", addr6);
363 exit(1);
364 }
365
366 // open socket
367 int sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
368 if (sock < 0) {
369 fprintf(stderr, "Error fnet: IPv6 is not supported on this system\n");
370 exit(1);
371 }
372
373 // find interface index
374 struct ifreq ifr;
375 memset(&ifr, 0, sizeof(ifr));
376 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
377 ifr.ifr_addr.sa_family = AF_INET;
378 if (ioctl(sock, SIOGIFINDEX, &ifr) < 0) {
379 perror("ioctl SIOGIFINDEX");
380 exit(1);
381 }
382
383 // configure address
384 struct ifreq6 ifr6;
385 memset(&ifr6, 0, sizeof(ifr6));
386 ifr6.ifr6_prefixlen = prefix;
387 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
388 memcpy((char *) &ifr6.ifr6_addr, (char *) &sin6.sin6_addr, sizeof(struct in6_addr));
389 if (ioctl(sock, SIOCSIFADDR, &ifr6) < 0) {
390 perror("ioctl SIOCSIFADDR");
391 exit(1);
392 }
393
394 close(sock);
395}
diff --git a/src/fnet/main.c b/src/fnet/main.c
new file mode 100644
index 000000000..4ae9eb6e3
--- /dev/null
+++ b/src/fnet/main.c
@@ -0,0 +1,103 @@
1 /*
2 * Copyright (C) 2014-2016 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#include "fnet.h"
21
22static void usage(void) {
23 printf("Usage:\n");
24 printf("\tfnet create veth dev1 dev2 bridge child\n");
25 printf("\tfnet create macvlan dev parent child\n");
26 printf("\tfnet moveif dev proc\n");
27 printf("\tfnet printif\n");
28 printf("\tfnet printif scan\n");
29 printf("\tfnet config interface dev ip mask mtu\n");
30 printf("\tfnet config mac addr\n");
31 printf("\tfnet config ipv6 dev ipn");
32 printf("\tfmet ifup dev\n");
33}
34
35int main(int argc, char **argv) {
36#if 0
37{
38//system("cat /proc/self/status");
39int i;
40for (i = 0; i < argc; i++)
41 printf("*%s* ", argv[i]);
42printf("\n");
43}
44#endif
45 if (argc < 2)
46 return 1;
47
48
49
50 if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) {
51 usage();
52 return 0;
53 }
54 else if (argc == 3 && strcmp(argv[1], "ifup") == 0) {
55 net_if_up(argv[2]);
56 }
57 else if (argc == 2 && strcmp(argv[1], "printif") == 0) {
58 net_ifprint(0);
59 }
60 else if (argc == 3 && strcmp(argv[1], "printif") == 0 && strcmp(argv[2], "scan") == 0) {
61 net_ifprint(1);
62 }
63 else if (argc == 7 && strcmp(argv[1], "create") == 0 && strcmp(argv[2], "veth") == 0) {
64 // create veth pair and move one end in the the namespace
65 net_create_veth(argv[3], argv[4], atoi(argv[6]));
66 // connect the ohter veth end to the bridge ...
67 net_bridge_add_interface(argv[5], argv[3]);
68 // ... and bring it up
69 net_if_up(argv[3]);
70 }
71 else if (argc == 6 && strcmp(argv[1], "create") == 0 && strcmp(argv[2], "macvlan") == 0) {
72 net_create_macvlan(argv[3], argv[4], atoi(argv[5]));
73 }
74 else if (argc == 7 && strcmp(argv[1], "config") == 0 && strcmp(argv[2], "interface") == 0) {
75 char *dev = argv[3];
76 uint32_t ip = (uint32_t) atoll(argv[4]);
77 uint32_t mask = (uint32_t) atoll(argv[5]);
78 int mtu = atoi(argv[6]);
79 // configure interface
80 net_if_ip(dev, ip, mask, mtu);
81 // ... and bring it up
82 net_if_up(dev);
83 }
84 else if (argc == 5 && strcmp(argv[1], "config") == 0 && strcmp(argv[2], "mac") == 0) {
85 unsigned char mac[6];
86 if (atomac(argv[4], mac)) {
87 fprintf(stderr, "Error fnet: invalid mac address %s\n", argv[4]);
88 }
89 net_if_mac(argv[3], mac);
90 }
91 else if (argc == 4 && strcmp(argv[1], "moveif") == 0) {
92 net_move_interface(argv[2], atoi(argv[3]));
93 }
94 else if (argc == 5 && strcmp(argv[1], "config") == 0 && strcmp(argv[2], "ipv6") == 0) {
95 net_if_ip6(argv[3], argv[4]);
96 }
97 else {
98 fprintf(stderr, "Error fnet: invalid arguments\n");
99 return 1;
100 }
101
102 return 0;
103}
diff --git a/src/firejail/veth.c b/src/fnet/veth.c
index df3c1d1f9..d06bc9256 100644
--- a/src/firejail/veth.c
+++ b/src/fnet/veth.c
@@ -45,7 +45,7 @@
45 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 45 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
46*/ 46*/
47 47
48#include "firejail.h" 48#include "fnet.h"
49#include "../include/libnetlink.h" 49#include "../include/libnetlink.h"
50#include <linux/veth.h> 50#include <linux/veth.h>
51#include <net/if.h> 51#include <net/if.h>
@@ -63,8 +63,6 @@ int net_create_veth(const char *dev, const char *nsdev, unsigned pid) {
63 int len; 63 int len;
64 struct iplink_req req; 64 struct iplink_req req;
65 65
66 if (arg_debug)
67 printf("create veth %s/%s/%u\n", dev, nsdev, pid);
68 assert(dev); 66 assert(dev);
69 assert(nsdev); 67 assert(nsdev);
70 assert(pid); 68 assert(pid);
@@ -120,8 +118,6 @@ int net_create_veth(const char *dev, const char *nsdev, unsigned pid) {
120int net_create_macvlan(const char *dev, const char *parent, unsigned pid) { 118int net_create_macvlan(const char *dev, const char *parent, unsigned pid) {
121 int len; 119 int len;
122 struct iplink_req req; 120 struct iplink_req req;
123 if (arg_debug)
124 printf("create macvlan %s, parent %s\n", dev, parent);
125 assert(dev); 121 assert(dev);
126 assert(parent); 122 assert(parent);
127 123
@@ -184,8 +180,6 @@ int net_create_macvlan(const char *dev, const char *parent, unsigned pid) {
184// when the interface is moved, netlink does not preserve interface configuration 180// when the interface is moved, netlink does not preserve interface configuration
185int net_move_interface(const char *dev, unsigned pid) { 181int net_move_interface(const char *dev, unsigned pid) {
186 struct iplink_req req; 182 struct iplink_req req;
187 if (arg_debug)
188 printf("move device %s inside the namespace\n", dev);
189 assert(dev); 183 assert(dev);
190 184
191 if (rtnl_open(&rth, 0) < 0) { 185 if (rtnl_open(&rth, 0) < 0) {
diff --git a/src/fseccomp/Makefile.in b/src/fseccomp/Makefile.in
new file mode 100644
index 000000000..110d2c95f
--- /dev/null
+++ b/src/fseccomp/Makefile.in
@@ -0,0 +1,43 @@
1all: fseccomp
2
3prefix=@prefix@
4exec_prefix=@exec_prefix@
5libdir=@libdir@
6sysconfdir=@sysconfdir@
7
8VERSION=@PACKAGE_VERSION@
9NAME=@PACKAGE_NAME@
10HAVE_SECCOMP_H=@HAVE_SECCOMP_H@
11HAVE_SECCOMP=@HAVE_SECCOMP@
12HAVE_CHROOT=@HAVE_CHROOT@
13HAVE_BIND=@HAVE_BIND@
14HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@
15HAVE_NETWORK=@HAVE_NETWORK@
16HAVE_USERNS=@HAVE_USERNS@
17HAVE_X11=@HAVE_X11@
18HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@
19HAVE_WHITELIST=@HAVE_WHITELIST@
20HAVE_GLOBALCFG=@HAVE_GLOBALCFG@
21HAVE_APPARMOR=@HAVE_APPARMOR@
22HAVE_OVERLAYFS=@HAVE_OVERLAYFS@
23HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@
24EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
25
26H_FILE_LIST = $(sort $(wildcard *.[h]))
27C_FILE_LIST = $(sort $(wildcard *.c))
28OBJS = $(C_FILE_LIST:.c=.o)
29BINOBJS = $(foreach file, $(OBJS), $file)
30CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
31LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
32
33%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h
34 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
35
36fseccomp: $(OBJS) ../lib/libnetlink.o ../lib/common.o
37 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
38
39clean:; rm -f *.o fseccomp
40
41distclean: clean
42 rm -fr Makefile
43
diff --git a/src/fseccomp/errno.c b/src/fseccomp/errno.c
new file mode 100644
index 000000000..dbee916d4
--- /dev/null
+++ b/src/fseccomp/errno.c
@@ -0,0 +1,204 @@
1/*
2 * Copyright (C) 2014-2016 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#include "fseccomp.h"
21
22#include <errno.h>
23//#include <attr/xattr.h>
24
25typedef struct {
26 char *name;
27 int nr;
28} ErrnoEntry;
29
30static ErrnoEntry errnolist[] = {
31//
32// code generated using tools/extract-errnos
33//
34 {"EPERM", EPERM},
35 {"ENOENT", ENOENT},
36 {"ESRCH", ESRCH},
37 {"EINTR", EINTR},
38 {"EIO", EIO},
39 {"ENXIO", ENXIO},
40 {"E2BIG", E2BIG},
41 {"ENOEXEC", ENOEXEC},
42 {"EBADF", EBADF},
43 {"ECHILD", ECHILD},
44 {"EAGAIN", EAGAIN},
45 {"ENOMEM", ENOMEM},
46 {"EACCES", EACCES},
47 {"EFAULT", EFAULT},
48 {"ENOTBLK", ENOTBLK},
49 {"EBUSY", EBUSY},
50 {"EEXIST", EEXIST},
51 {"EXDEV", EXDEV},
52 {"ENODEV", ENODEV},
53 {"ENOTDIR", ENOTDIR},
54 {"EISDIR", EISDIR},
55 {"EINVAL", EINVAL},
56 {"ENFILE", ENFILE},
57 {"EMFILE", EMFILE},
58 {"ENOTTY", ENOTTY},
59 {"ETXTBSY", ETXTBSY},
60 {"EFBIG", EFBIG},
61 {"ENOSPC", ENOSPC},
62 {"ESPIPE", ESPIPE},
63 {"EROFS", EROFS},
64 {"EMLINK", EMLINK},
65 {"EPIPE", EPIPE},
66 {"EDOM", EDOM},
67 {"ERANGE", ERANGE},
68 {"EDEADLK", EDEADLK},
69 {"ENAMETOOLONG", ENAMETOOLONG},
70 {"ENOLCK", ENOLCK},
71 {"ENOSYS", ENOSYS},
72 {"ENOTEMPTY", ENOTEMPTY},
73 {"ELOOP", ELOOP},
74 {"EWOULDBLOCK", EWOULDBLOCK},
75 {"ENOMSG", ENOMSG},
76 {"EIDRM", EIDRM},
77 {"ECHRNG", ECHRNG},
78 {"EL2NSYNC", EL2NSYNC},
79 {"EL3HLT", EL3HLT},
80 {"EL3RST", EL3RST},
81 {"ELNRNG", ELNRNG},
82 {"EUNATCH", EUNATCH},
83 {"ENOCSI", ENOCSI},
84 {"EL2HLT", EL2HLT},
85 {"EBADE", EBADE},
86 {"EBADR", EBADR},
87 {"EXFULL", EXFULL},
88 {"ENOANO", ENOANO},
89 {"EBADRQC", EBADRQC},
90 {"EBADSLT", EBADSLT},
91 {"EDEADLOCK", EDEADLOCK},
92 {"EBFONT", EBFONT},
93 {"ENOSTR", ENOSTR},
94 {"ENODATA", ENODATA},
95 {"ETIME", ETIME},
96 {"ENOSR", ENOSR},
97 {"ENONET", ENONET},
98 {"ENOPKG", ENOPKG},
99 {"EREMOTE", EREMOTE},
100 {"ENOLINK", ENOLINK},
101 {"EADV", EADV},
102 {"ESRMNT", ESRMNT},
103 {"ECOMM", ECOMM},
104 {"EPROTO", EPROTO},
105 {"EMULTIHOP", EMULTIHOP},
106 {"EDOTDOT", EDOTDOT},
107 {"EBADMSG", EBADMSG},
108 {"EOVERFLOW", EOVERFLOW},
109 {"ENOTUNIQ", ENOTUNIQ},
110 {"EBADFD", EBADFD},
111 {"EREMCHG", EREMCHG},
112 {"ELIBACC", ELIBACC},
113 {"ELIBBAD", ELIBBAD},
114 {"ELIBSCN", ELIBSCN},
115 {"ELIBMAX", ELIBMAX},
116 {"ELIBEXEC", ELIBEXEC},
117 {"EILSEQ", EILSEQ},
118 {"ERESTART", ERESTART},
119 {"ESTRPIPE", ESTRPIPE},
120 {"EUSERS", EUSERS},
121 {"ENOTSOCK", ENOTSOCK},
122 {"EDESTADDRREQ", EDESTADDRREQ},
123 {"EMSGSIZE", EMSGSIZE},
124 {"EPROTOTYPE", EPROTOTYPE},
125 {"ENOPROTOOPT", ENOPROTOOPT},
126 {"EPROTONOSUPPORT", EPROTONOSUPPORT},
127 {"ESOCKTNOSUPPORT", ESOCKTNOSUPPORT},
128 {"EOPNOTSUPP", EOPNOTSUPP},
129 {"EPFNOSUPPORT", EPFNOSUPPORT},
130 {"EAFNOSUPPORT", EAFNOSUPPORT},
131 {"EADDRINUSE", EADDRINUSE},
132 {"EADDRNOTAVAIL", EADDRNOTAVAIL},
133 {"ENETDOWN", ENETDOWN},
134 {"ENETUNREACH", ENETUNREACH},
135 {"ENETRESET", ENETRESET},
136 {"ECONNABORTED", ECONNABORTED},
137 {"ECONNRESET", ECONNRESET},
138 {"ENOBUFS", ENOBUFS},
139 {"EISCONN", EISCONN},
140 {"ENOTCONN", ENOTCONN},
141 {"ESHUTDOWN", ESHUTDOWN},
142 {"ETOOMANYREFS", ETOOMANYREFS},
143 {"ETIMEDOUT", ETIMEDOUT},
144 {"ECONNREFUSED", ECONNREFUSED},
145 {"EHOSTDOWN", EHOSTDOWN},
146 {"EHOSTUNREACH", EHOSTUNREACH},
147 {"EALREADY", EALREADY},
148 {"EINPROGRESS", EINPROGRESS},
149 {"ESTALE", ESTALE},
150 {"EUCLEAN", EUCLEAN},
151 {"ENOTNAM", ENOTNAM},
152 {"ENAVAIL", ENAVAIL},
153 {"EISNAM", EISNAM},
154 {"EREMOTEIO", EREMOTEIO},
155 {"EDQUOT", EDQUOT},
156 {"ENOMEDIUM", ENOMEDIUM},
157 {"EMEDIUMTYPE", EMEDIUMTYPE},
158 {"ECANCELED", ECANCELED},
159 {"ENOKEY", ENOKEY},
160 {"EKEYEXPIRED", EKEYEXPIRED},
161 {"EKEYREVOKED", EKEYREVOKED},
162 {"EKEYREJECTED", EKEYREJECTED},
163 {"EOWNERDEAD", EOWNERDEAD},
164 {"ENOTRECOVERABLE", ENOTRECOVERABLE},
165 {"ERFKILL", ERFKILL},
166 {"EHWPOISON", EHWPOISON},
167 {"ENOTSUP", ENOTSUP},
168#ifdef ENOATTR
169 {"ENOATTR", ENOATTR},
170#endif
171};
172
173int errno_find_name(const char *name) {
174 int i;
175 int elems = sizeof(errnolist) / sizeof(errnolist[0]);
176 for (i = 0; i < elems; i++) {
177 if (strcasecmp(name, errnolist[i].name) == 0)
178 return errnolist[i].nr;
179 }
180
181 return -1;
182}
183
184char *errno_find_nr(int nr) {
185 int i;
186 int elems = sizeof(errnolist) / sizeof(errnolist[0]);
187 for (i = 0; i < elems; i++) {
188 if (nr == errnolist[i].nr)
189 return errnolist[i].name;
190 }
191
192 return "unknown";
193}
194
195
196
197void errno_print(void) {
198 int i;
199 int elems = sizeof(errnolist) / sizeof(errnolist[0]);
200 for (i = 0; i < elems; i++) {
201 printf("%d\t- %s\n", errnolist[i].nr, errnolist[i].name);
202 }
203 printf("\n");
204}
diff --git a/src/fseccomp/fseccomp.h b/src/fseccomp/fseccomp.h
new file mode 100644
index 000000000..504f1c23f
--- /dev/null
+++ b/src/fseccomp/fseccomp.h
@@ -0,0 +1,68 @@
1/*
2 * Copyright (C) 2014-2016 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#ifndef FSECCOMP_H
21#define FSECCOMP_H
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <assert.h>
26#include "../include/common.h"
27
28// syscall.c
29void syscall_print(void);
30int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int arg), int fd, int arg);
31int syscall_find_name(const char *name);
32char *syscall_find_nr(int nr);
33
34// errno.c
35void errno_print(void);
36int errno_find_name(const char *name);
37char *errno_find_nr(int nr);
38
39// protocol.c
40void protocol_print(void);
41void protocol_build_filter(const char *prlist, const char *fname);
42
43// seccomp_secondary.c
44void seccomp_secondary_64(const char *fname);
45void seccomp_secondary_32(const char *fname);
46
47// seccomp_file.c
48void filter_init(int fd);
49void filter_add_whitelist(int fd, int syscall, int arg);
50void filter_add_blacklist(int fd, int syscall, int arg);
51void filter_add_errno(int fd, int syscall, int arg);
52void filter_end_blacklist(int fd);
53void filter_end_whitelist(int fd);
54
55// seccomp.c
56// default list
57void seccomp_default(const char *fname, int allow_debuggers);
58// drop list
59void seccomp_drop(const char *fname, char *list, int allow_debuggers);
60// default+drop list
61void seccomp_default_drop(const char *fname, char *list, int allow_debuggers);
62// whitelisted filter
63void seccomp_keep(const char *fname, char *list);
64
65// seccomp_print
66void filter_print(const char *fname);
67
68#endif
diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c
new file mode 100644
index 000000000..22b13bcd9
--- /dev/null
+++ b/src/fseccomp/main.c
@@ -0,0 +1,91 @@
1/*
2 * Copyright (C) 2014-2016 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#include "fseccomp.h"
21
22static void usage(void) {
23 printf("Usage:\n");
24 printf("\tfseccomp debug-syscalls\n");
25 printf("\tfseccomp debug-errnos\n");
26 printf("\tfseccomp debug-protocols\n");
27 printf("\tfseccomp protocol build list file\n");
28 printf("\tfseccomp secondary 64 file\n");
29 printf("\tfseccomp secondary 32 file\n");
30 printf("\tfseccomp default file\n");
31 printf("\tfseccomp default file allow-debuggers\n");
32 printf("\tfseccomp drop file list\n");
33 printf("\tfseccomp drop file list allow-debuggers\n");
34 printf("\tfseccomp default drop file list\n");
35 printf("\tfseccomp default drop file list allow-debuggers\n");
36 printf("\tfseccomp keep file list\n");
37 printf("\tfseccomp print file\n");
38}
39
40int main(int argc, char **argv) {
41#if 0
42{
43system("cat /proc/self/status");
44int i;
45for (i = 0; i < argc; i++)
46 printf("*%s* ", argv[i]);
47printf("\n");
48}
49#endif
50 if (argc < 2)
51 return 1;
52
53 if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) {
54 usage();
55 return 0;
56 }
57 else if (argc == 2 && strcmp(argv[1], "debug-syscalls") == 0)
58 syscall_print();
59 else if (argc == 2 && strcmp(argv[1], "debug-errnos") == 0)
60 errno_print();
61 else if (argc == 2 && strcmp(argv[1], "debug-protocols") == 0)
62 protocol_print();
63 else if (argc == 5 && strcmp(argv[1], "protocol") == 0 && strcmp(argv[2], "build") == 0)
64 protocol_build_filter(argv[3], argv[4]);
65 else if (argc == 4 && strcmp(argv[1], "secondary") == 0 && strcmp(argv[2], "64") == 0)
66 seccomp_secondary_64(argv[3]);
67 else if (argc == 4 && strcmp(argv[1], "secondary") == 0 && strcmp(argv[2], "32") == 0)
68 seccomp_secondary_32(argv[3]);
69 else if (argc == 3 && strcmp(argv[1], "default") == 0)
70 seccomp_default(argv[2], 0);
71 else if (argc == 4 && strcmp(argv[1], "default") == 0 && strcmp(argv[3], "allow-debuggers") == 0)
72 seccomp_default(argv[2], 1);
73 else if (argc == 4 && strcmp(argv[1], "drop") == 0)
74 seccomp_drop(argv[2], argv[3], 0);
75 else if (argc == 5 && strcmp(argv[1], "drop") == 0 && strcmp(argv[4], "allow-debuggers") == 0)
76 seccomp_drop(argv[2], argv[3], 1);
77 else if (argc == 5 && strcmp(argv[1], "default") == 0 && strcmp(argv[2], "drop") == 0)
78 seccomp_default_drop(argv[3], argv[4], 0);
79 else if (argc == 6 && strcmp(argv[1], "default") == 0 && strcmp(argv[2], "drop") == 0 && strcmp(argv[5], "allow-debuggers") == 0)
80 seccomp_default_drop(argv[3], argv[4], 1);
81 else if (argc == 4 && strcmp(argv[1], "keep") == 0)
82 seccomp_keep(argv[2], argv[3]);
83 else if (argc == 3 && strcmp(argv[1], "print") == 0)
84 filter_print(argv[2]);
85 else {
86 fprintf(stderr, "Error fseccomp: invalid arguments\n");
87 return 1;
88 }
89
90 return 0;
91} \ No newline at end of file
diff --git a/src/fseccomp/protocol.c b/src/fseccomp/protocol.c
new file mode 100644
index 000000000..38c5f9d88
--- /dev/null
+++ b/src/fseccomp/protocol.c
@@ -0,0 +1,219 @@
1/*
2 * Copyright (C) 2014-2016 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/*
22 struct sock_filter filter[] = {
23 VALIDATE_ARCHITECTURE,
24 EXAMINE_SYSCALL,
25 ONLY(SYS_socket),
26 EXAMINE_ARGUMENT(0), // allow only AF_INET and AF_INET6, drop everything else
27 WHITELIST(AF_INET),
28 WHITELIST(AF_INET6),
29 WHITELIST(AF_PACKET),
30 RETURN_ERRNO(ENOTSUP)
31 };
32 struct sock_fprog prog = {
33 .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
34 .filter = filter,
35 };
36
37
38 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
39 perror("prctl(NO_NEW_PRIVS)");
40 return 1;
41 }
42 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
43 perror("prctl");
44 return 1;
45 }
46*/
47
48#include "fseccomp.h"
49#include "../include/seccomp.h"
50#include <sys/syscall.h>
51#include <sys/types.h>
52#include <sys/socket.h>
53
54static char *protocol[] = {
55 "unix",
56 "inet",
57 "inet6",
58 "netlink",
59 "packet",
60 NULL
61};
62
63static struct sock_filter protocol_filter_command[] = {
64 WHITELIST(AF_UNIX),
65 WHITELIST(AF_INET),
66 WHITELIST(AF_INET6),
67 WHITELIST(AF_NETLINK),
68 WHITELIST(AF_PACKET)
69};
70// Note: protocol[] and protocol_filter_command are synchronized
71
72// command length
73struct sock_filter whitelist[] = {
74 WHITELIST(AF_UNIX)
75};
76unsigned whitelist_len = sizeof(whitelist) / sizeof(struct sock_filter);
77
78static struct sock_filter *find_protocol_domain(const char *p) {
79 int i = 0;
80 while (protocol[i] != NULL) {
81 if (strcmp(protocol[i], p) == 0)
82 return &protocol_filter_command[i * whitelist_len];
83 i++;
84 }
85
86 return NULL;
87}
88
89
90void protocol_print(void) {
91#ifndef SYS_socket
92 fprintf(stderr, "Warning fseccomp: firejail --protocol not supported on this platform\n");
93 return;
94#endif
95
96 int i = 0;
97 while (protocol[i] != NULL) {
98 printf("%s, ", protocol[i]);
99 i++;
100 }
101 printf("\n");
102}
103
104// install protocol filter
105void protocol_build_filter(const char *prlist, const char *fname) {
106 assert(prlist);
107 assert(fname);
108
109#ifndef SYS_socket
110 fprintf(stderr, "Warning: --protocol not supported on this platform\n");
111 return;
112#else
113 // build the filter
114 struct sock_filter filter[32]; // big enough
115 memset(&filter[0], 0, sizeof(filter));
116 uint8_t *ptr = (uint8_t *) &filter[0];
117
118 // header
119 struct sock_filter filter_start[] = {
120 VALIDATE_ARCHITECTURE,
121 EXAMINE_SYSCALL,
122 ONLY(SYS_socket),
123 EXAMINE_ARGUMENT(0)
124 };
125 memcpy(ptr, &filter_start[0], sizeof(filter_start));
126 ptr += sizeof(filter_start);
127
128#if 0
129printf("entries %u\n", (unsigned) (sizeof(filter_start) / sizeof(struct sock_filter)));
130{
131 unsigned j;
132 unsigned char *ptr2 = (unsigned char *) &filter[0];
133 for (j = 0; j < sizeof(filter); j++, ptr2++) {
134 if ((j % (sizeof(struct sock_filter))) == 0)
135 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
136 printf("%02x, ", (*ptr2) & 0xff);
137 }
138 printf("\n");
139}
140printf("whitelist_len %u, struct sock_filter len %u\n", whitelist_len, (unsigned) sizeof(struct sock_filter));
141#endif
142
143
144 // parse list and add commands
145 char *tmplist = strdup(prlist);
146 if (!tmplist)
147 errExit("strdup");
148 char *token = strtok(tmplist, ",");
149 if (!token)
150 errExit("strtok");
151
152 while (token) {
153 struct sock_filter *domain = find_protocol_domain(token);
154 if (domain == NULL) {
155 fprintf(stderr, "Error fseccomp: %s is not a valid protocol\n", token);
156 exit(1);
157 }
158 memcpy(ptr, domain, whitelist_len * sizeof(struct sock_filter));
159 ptr += whitelist_len * sizeof(struct sock_filter);
160 token = strtok(NULL, ",");
161
162#if 0
163printf("entries %u\n", (unsigned) ((uint64_t) ptr - (uint64_t) (filter)) / (unsigned) sizeof(struct sock_filter));
164{
165 unsigned j;
166 unsigned char *ptr2 = (unsigned char *) &filter[0];
167 for (j = 0; j < sizeof(filter); j++, ptr2++) {
168 if ((j % (sizeof(struct sock_filter))) == 0)
169 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
170 printf("%02x, ", (*ptr2) & 0xff);
171 }
172 printf("\n");
173}
174#endif
175
176
177 }
178 free(tmplist);
179
180 // add end of filter
181 struct sock_filter filter_end[] = {
182 RETURN_ERRNO(ENOTSUP)
183 };
184 memcpy(ptr, &filter_end[0], sizeof(filter_end));
185 ptr += sizeof(filter_end);
186
187#if 0
188printf("entries %u\n", (unsigned) ((uint64_t) ptr - (uint64_t) (filter)) / (unsigned) sizeof(struct sock_filter));
189{
190 unsigned j;
191 unsigned char *ptr2 = (unsigned char *) &filter[0];
192 for (j = 0; j < sizeof(filter); j++, ptr2++) {
193 if ((j % (sizeof(struct sock_filter))) == 0)
194 printf("\n%u: ", 1 + (unsigned) (j / (sizeof(struct sock_filter))));
195 printf("%02x, ", (*ptr2) & 0xff);
196 }
197 printf("\n");
198}
199#endif
200 // save filter to file
201 int dst = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
202 if (dst < 0) {
203 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname);
204 exit(1);
205 }
206
207 int size = (int) ((uintptr_t) ptr - (uintptr_t) (filter));
208 int written = 0;
209 while (written < size) {
210 int rv = write(dst, (unsigned char *) filter + written, size - written);
211 if (rv == -1) {
212 fprintf(stderr, "Error fseccomp: cannot write %s file\n", fname);
213 exit(1);
214 }
215 written += rv;
216 }
217 close(dst);
218#endif // SYS_socket
219}
diff --git a/src/fseccomp/seccomp.c b/src/fseccomp/seccomp.c
new file mode 100644
index 000000000..cc6edc8ca
--- /dev/null
+++ b/src/fseccomp/seccomp.c
@@ -0,0 +1,292 @@
1/*
2 * Copyright (C) 2014-2016 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#include "fseccomp.h"
21#include "../include/seccomp.h"
22#include <sys/syscall.h>
23
24static void add_default_list(int fd, int allow_debuggers) {
25#ifdef SYS_mount
26 filter_add_blacklist(fd, SYS_mount, 0);
27#endif
28#ifdef SYS_umount2
29 filter_add_blacklist(fd, SYS_umount2, 0);
30#endif
31
32 if (!allow_debuggers) {
33#ifdef SYS_ptrace
34 filter_add_blacklist(fd, SYS_ptrace, 0);
35#endif
36 }
37
38#ifdef SYS_kexec_load
39 filter_add_blacklist(fd, SYS_kexec_load, 0);
40#endif
41#ifdef SYS_kexec_file_load
42 filter_add_blacklist(fd, SYS_kexec_file_load, 0);
43#endif
44#ifdef SYS_open_by_handle_at
45 filter_add_blacklist(fd, SYS_open_by_handle_at, 0);
46#endif
47#ifdef SYS_name_to_handle_at
48 filter_add_blacklist(fd, SYS_name_to_handle_at, 0);
49#endif
50#ifdef SYS_init_module
51 filter_add_blacklist(fd, SYS_init_module, 0);
52#endif
53#ifdef SYS_finit_module
54 filter_add_blacklist(fd, SYS_finit_module, 0);
55#endif
56#ifdef SYS_create_module
57 filter_add_blacklist(fd, SYS_create_module, 0);
58#endif
59#ifdef SYS_delete_module
60 filter_add_blacklist(fd, SYS_delete_module, 0);
61#endif
62#ifdef SYS_iopl
63 filter_add_blacklist(fd, SYS_iopl, 0);
64#endif
65#ifdef SYS_ioperm
66 filter_add_blacklist(fd, SYS_ioperm, 0);
67#endif
68#ifdef SYS_ioprio_set
69 filter_add_blacklist(fd, SYS_ioprio_set, 0);
70#endif
71#ifdef SYS_ni_syscall
72 filter_add_blacklist(fd, SYS_ni_syscall, 0);
73#endif
74#ifdef SYS_swapon
75 filter_add_blacklist(fd, SYS_swapon, 0);
76#endif
77#ifdef SYS_swapoff
78 filter_add_blacklist(fd, SYS_swapoff, 0);
79#endif
80#ifdef SYS_syslog
81 filter_add_blacklist(fd, SYS_syslog, 0);
82#endif
83
84 if (!allow_debuggers) {
85#ifdef SYS_process_vm_readv
86 filter_add_blacklist(fd, SYS_process_vm_readv, 0);
87#endif
88 }
89
90#ifdef SYS_process_vm_writev
91 filter_add_blacklist(fd, SYS_process_vm_writev, 0);
92#endif
93
94 // mknod removed in 0.9.29 - it brakes Zotero extension
95 //#ifdef SYS_mknod
96 // filter_add_blacklist(SYS_mknod, 0);
97 //#endif
98
99#ifdef SYS_sysfs
100 filter_add_blacklist(fd, SYS_sysfs, 0);
101#endif
102#ifdef SYS__sysctl
103 filter_add_blacklist(fd, SYS__sysctl, 0);
104#endif
105#ifdef SYS_adjtimex
106 filter_add_blacklist(fd, SYS_adjtimex, 0);
107#endif
108#ifdef SYS_clock_adjtime
109 filter_add_blacklist(fd, SYS_clock_adjtime, 0);
110#endif
111#ifdef SYS_lookup_dcookie
112 filter_add_blacklist(fd, SYS_lookup_dcookie, 0);
113#endif
114#ifdef SYS_perf_event_open
115 filter_add_blacklist(fd, SYS_perf_event_open, 0);
116#endif
117#ifdef SYS_fanotify_init
118 filter_add_blacklist(fd, SYS_fanotify_init, 0);
119#endif
120#ifdef SYS_kcmp
121 filter_add_blacklist(fd, SYS_kcmp, 0);
122#endif
123#ifdef SYS_add_key
124 filter_add_blacklist(fd, SYS_add_key, 0);
125#endif
126#ifdef SYS_request_key
127 filter_add_blacklist(fd, SYS_request_key, 0);
128#endif
129#ifdef SYS_keyctl
130 filter_add_blacklist(fd, SYS_keyctl, 0);
131#endif
132#ifdef SYS_uselib
133 filter_add_blacklist(fd, SYS_uselib, 0);
134#endif
135#ifdef SYS_acct
136 filter_add_blacklist(fd, SYS_acct, 0);
137#endif
138#ifdef SYS_modify_ldt
139 filter_add_blacklist(fd, SYS_modify_ldt, 0);
140#endif
141#ifdef SYS_pivot_root
142 filter_add_blacklist(fd, SYS_pivot_root, 0);
143#endif
144#ifdef SYS_io_setup
145 filter_add_blacklist(fd, SYS_io_setup, 0);
146#endif
147#ifdef SYS_io_destroy
148 filter_add_blacklist(fd, SYS_io_destroy, 0);
149#endif
150#ifdef SYS_io_getevents
151 filter_add_blacklist(fd, SYS_io_getevents, 0);
152#endif
153#ifdef SYS_io_submit
154 filter_add_blacklist(fd, SYS_io_submit, 0);
155#endif
156#ifdef SYS_io_cancel
157 filter_add_blacklist(fd, SYS_io_cancel, 0);
158#endif
159#ifdef SYS_remap_file_pages
160 filter_add_blacklist(fd, SYS_remap_file_pages, 0);
161#endif
162#ifdef SYS_mbind
163 filter_add_blacklist(fd, SYS_mbind, 0);
164#endif
165#ifdef SYS_get_mempolicy
166 filter_add_blacklist(fd, SYS_get_mempolicy, 0);
167#endif
168#ifdef SYS_set_mempolicy
169 filter_add_blacklist(fd, SYS_set_mempolicy, 0);
170#endif
171#ifdef SYS_migrate_pages
172 filter_add_blacklist(fd, SYS_migrate_pages, 0);
173#endif
174#ifdef SYS_move_pages
175 filter_add_blacklist(fd, SYS_move_pages, 0);
176#endif
177#ifdef SYS_vmsplice
178 filter_add_blacklist(fd, SYS_vmsplice, 0);
179#endif
180#ifdef SYS_chroot
181 filter_add_blacklist(fd, SYS_chroot, 0);
182#endif
183#ifdef SYS_tuxcall
184 filter_add_blacklist(fd, SYS_tuxcall, 0);
185#endif
186#ifdef SYS_reboot
187 filter_add_blacklist(fd, SYS_reboot, 0);
188#endif
189#ifdef SYS_nfsservctl
190 filter_add_blacklist(fd, SYS_nfsservctl, 0);
191#endif
192#ifdef SYS_get_kernel_syms
193 filter_add_blacklist(fd, SYS_get_kernel_syms, 0);
194#endif
195}
196
197// default list
198void seccomp_default(const char *fname, int allow_debuggers) {
199 assert(fname);
200
201 // open file
202 int fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
203 if (fd < 0) {
204 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname);
205 exit(1);
206 }
207
208 // build filter
209 filter_init(fd);
210 add_default_list(fd, allow_debuggers);
211 filter_end_blacklist(fd);
212
213 // close file
214 close(fd);
215}
216
217// drop list
218void seccomp_drop(const char *fname, char *list, int allow_debuggers) {
219 assert(fname);
220 (void) allow_debuggers; // todo: to implemnet it
221
222 // open file
223 int fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
224 if (fd < 0) {
225 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname);
226 exit(1);
227 }
228
229 // build filter
230 filter_init(fd);
231 if (syscall_check_list(list, filter_add_blacklist, fd, 0)) {
232 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n");
233 exit(1);
234 }
235 filter_end_blacklist(fd);
236
237 // close file
238 close(fd);
239}
240
241// default+drop
242void seccomp_default_drop(const char *fname, char *list, int allow_debuggers) {
243 assert(fname);
244
245 // open file
246 int fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
247 if (fd < 0) {
248 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname);
249 exit(1);
250 }
251
252 // build filter
253 filter_init(fd);
254 add_default_list(fd, allow_debuggers);
255 if (syscall_check_list(list, filter_add_blacklist, fd, 0)) {
256 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n");
257 exit(1);
258 }
259 filter_end_blacklist(fd);
260
261 // close file
262 close(fd);
263}
264
265void seccomp_keep(const char *fname, char *list) {
266 // open file
267 int fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
268 if (fd < 0) {
269 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname);
270 exit(1);
271 }
272
273 // build filter
274 filter_init(fd);
275 // these 4 syscalls are used by firejail after the seccomp filter is initialized
276 filter_add_whitelist(fd, SYS_setuid, 0);
277 filter_add_whitelist(fd, SYS_setgid, 0);
278 filter_add_whitelist(fd, SYS_setgroups, 0);
279 filter_add_whitelist(fd, SYS_dup, 0);
280 filter_add_whitelist(fd, SYS_prctl, 0);
281
282 if (syscall_check_list(list, filter_add_whitelist, fd, 0)) {
283 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n");
284 exit(1);
285 }
286
287 filter_end_whitelist(fd);
288
289 // close file
290 close(fd);
291}
292
diff --git a/src/fseccomp/seccomp_file.c b/src/fseccomp/seccomp_file.c
new file mode 100644
index 000000000..10ef9dd31
--- /dev/null
+++ b/src/fseccomp/seccomp_file.c
@@ -0,0 +1,108 @@
1/*
2 * Copyright (C) 2014-2016 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#include "fseccomp.h"
21#include "../include/seccomp.h"
22#include <sys/syscall.h>
23
24static void write_to_file(int fd, void *data, int size) {
25 assert(data);
26 assert(size);
27
28 int written = 0;
29 while (written < size) {
30 int rv = write(fd, (unsigned char *) data + written, size - written);
31 if (rv == -1) {
32 fprintf(stderr, "Error fseccomp: cannot write seccomp file\n");
33 exit(1);
34 }
35 written += rv;
36 }
37}
38
39void filter_init(int fd) {
40#if defined(__x86_64__)
41#define X32_SYSCALL_BIT 0x40000000
42 struct sock_filter filter[] = {
43 VALIDATE_ARCHITECTURE,
44 EXAMINE_SYSCALL,
45 // handle X32 ABI
46 BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, X32_SYSCALL_BIT, 1, 0),
47 BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, 0, 1, 0),
48 RETURN_ERRNO(EPERM)
49 };
50#else
51 struct sock_filter filter[] = {
52 VALIDATE_ARCHITECTURE,
53 EXAMINE_SYSCALL
54 };
55#endif
56
57#if 0
58{
59 int i;
60 unsigned char *ptr = (unsigned char *) &filter[0];
61 for (i = 0; i < sizeof(filter); i++, ptr++)
62 printf("%x, ", (*ptr) & 0xff);
63 printf("\n");
64}
65#endif
66
67 write_to_file(fd, filter, sizeof(filter));
68}
69
70void filter_add_whitelist(int fd, int syscall, int arg) {
71 (void) arg;
72
73 struct sock_filter filter[] = {
74 WHITELIST(syscall)
75 };
76 write_to_file(fd, filter, sizeof(filter));
77}
78
79void filter_add_blacklist(int fd, int syscall, int arg) {
80 (void) arg;
81
82 struct sock_filter filter[] = {
83 BLACKLIST(syscall)
84 };
85 write_to_file(fd, filter, sizeof(filter));
86}
87
88void filter_add_errno(int fd, int syscall, int arg) {
89 struct sock_filter filter[] = {
90 BLACKLIST_ERRNO(syscall, arg)
91 };
92 write_to_file(fd, filter, sizeof(filter));
93}
94
95void filter_end_blacklist(int fd) {
96 struct sock_filter filter[] = {
97 RETURN_ALLOW
98 };
99 write_to_file(fd, filter, sizeof(filter));
100}
101
102void filter_end_whitelist(int fd) {
103 struct sock_filter filter[] = {
104 KILL_PROCESS
105 };
106 write_to_file(fd, filter, sizeof(filter));
107}
108
diff --git a/src/fseccomp/seccomp_print.c b/src/fseccomp/seccomp_print.c
new file mode 100644
index 000000000..7dc983b12
--- /dev/null
+++ b/src/fseccomp/seccomp_print.c
@@ -0,0 +1,116 @@
1/*
2 * Copyright (C) 2014-2016 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#include "fseccomp.h"
21#include "../include/seccomp.h"
22#include <sys/syscall.h>
23
24static struct sock_filter *filter = NULL;
25static int filter_cnt = 0;
26
27static void load_seccomp(const char *fname) {
28 assert(fname);
29
30 // check file
31 struct stat s;
32 if (stat(fname, &s) == -1) {
33 fprintf(stderr, "Error fseccomp: cannot read protocol filter file\n");
34 exit(1);
35 }
36 int size = s.st_size;
37 unsigned short entries = (unsigned short) size / (unsigned short) sizeof(struct sock_filter);
38 filter_cnt = entries;
39//printf("size %d, entries %d\n", s.st_size, entries);
40
41 filter = malloc(sizeof(struct sock_filter) * entries);
42 if (!filter)
43 errExit("malloc");
44
45 // read filter
46 memset(filter, 0, sizeof(struct sock_filter) * entries);
47 int src = open(fname, O_RDONLY);
48 int rd = 0;
49 while (rd < size) {
50 int rv = read(src, (unsigned char *) filter + rd, size - rd);
51 if (rv == -1) {
52 fprintf(stderr, "Error fseccomp: cannot read %s file\n", fname);
53 exit(1);
54 }
55 rd += rv;
56 }
57 close(src);
58}
59
60// debug filter
61void filter_print(const char *fname) {
62 assert(fname);
63 load_seccomp(fname);
64
65 // start filter
66 struct sock_filter start[] = {
67 VALIDATE_ARCHITECTURE,
68 EXAMINE_SYSCALL
69 };
70
71 // print sizes
72 printf("SECCOMP Filter:\n");
73
74 // test the start of the filter
75 if (memcmp(&start[0], filter, sizeof(start)) == 0) {
76 printf(" VALIDATE_ARCHITECTURE\n");
77 printf(" EXAMINE_SYSCAL\n");
78 }
79 else {
80 printf("Invalid seccomp filter %s\n", fname);
81 return;
82 }
83
84 // loop trough blacklists
85 int i = 4;
86 while (i < filter_cnt) {
87 // minimal parsing!
88 unsigned char *ptr = (unsigned char *) &filter[i];
89 int *nr = (int *) (ptr + 4);
90 if (*ptr == 0x15 && *(ptr +14) == 0xff && *(ptr + 15) == 0x7f ) {
91 printf(" WHITELIST %d %s\n", *nr, syscall_find_nr(*nr));
92 i += 2;
93 }
94 else if (*ptr == 0x15 && *(ptr +14) == 0 && *(ptr + 15) == 0) {
95 printf(" BLACKLIST %d %s\n", *nr, syscall_find_nr(*nr));
96 i += 2;
97 }
98 else if (*ptr == 0x15 && *(ptr +14) == 0x5 && *(ptr + 15) == 0) {
99 int err = *(ptr + 13) << 8 | *(ptr + 12);
100 printf(" ERRNO %d %s %d %s\n", *nr, syscall_find_nr(*nr), err, errno_find_nr(err));
101 i += 2;
102 }
103 else if (*ptr == 0x06 && *(ptr +6) == 0 && *(ptr + 7) == 0 ) {
104 printf(" KILL_PROCESS\n");
105 i++;
106 }
107 else if (*ptr == 0x06 && *(ptr +6) == 0xff && *(ptr + 7) == 0x7f ) {
108 printf(" RETURN_ALLOW\n");
109 i++;
110 }
111 else {
112 printf(" UNKNOWN ENTRY!!!\n");
113 i++;
114 }
115 }
116}
diff --git a/src/fseccomp/seccomp_secondary.c b/src/fseccomp/seccomp_secondary.c
new file mode 100644
index 000000000..a856e5aef
--- /dev/null
+++ b/src/fseccomp/seccomp_secondary.c
@@ -0,0 +1,183 @@
1/*
2 * Copyright (C) 2014-2016 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#include "fseccomp.h"
21#include "../include/seccomp.h"
22#include <sys/syscall.h>
23
24void seccomp_secondary_64(const char *fname) {
25 // hardcoded syscall values
26 struct sock_filter filter[] = {
27 VALIDATE_ARCHITECTURE_64,
28 EXAMINE_SYSCALL,
29 BLACKLIST(165), // mount
30 BLACKLIST(166), // umount2
31// todo: implement --allow-debuggers
32 BLACKLIST(101), // ptrace
33 BLACKLIST(246), // kexec_load
34 BLACKLIST(304), // open_by_handle_at
35 BLACKLIST(303), // name_to_handle_at
36 BLACKLIST(174), // create_module
37 BLACKLIST(175), // init_module
38 BLACKLIST(313), // finit_module
39 BLACKLIST(176), // delete_module
40 BLACKLIST(172), // iopl
41 BLACKLIST(173), // ioperm
42 BLACKLIST(251), // ioprio_set
43 BLACKLIST(167), // swapon
44 BLACKLIST(168), // swapoff
45 BLACKLIST(103), // syslog
46 BLACKLIST(310), // process_vm_readv
47 BLACKLIST(311), // process_vm_writev
48 BLACKLIST(139), // sysfs
49 BLACKLIST(156), // _sysctl
50 BLACKLIST(159), // adjtimex
51 BLACKLIST(305), // clock_adjtime
52 BLACKLIST(212), // lookup_dcookie
53 BLACKLIST(298), // perf_event_open
54 BLACKLIST(300), // fanotify_init
55 BLACKLIST(312), // kcmp
56 BLACKLIST(248), // add_key
57 BLACKLIST(249), // request_key
58 BLACKLIST(250), // keyctl
59 BLACKLIST(134), // uselib
60 BLACKLIST(163), // acct
61 BLACKLIST(154), // modify_ldt
62 BLACKLIST(155), // pivot_root
63 BLACKLIST(206), // io_setup
64 BLACKLIST(207), // io_destroy
65 BLACKLIST(208), // io_getevents
66 BLACKLIST(209), // io_submit
67 BLACKLIST(210), // io_cancel
68 BLACKLIST(216), // remap_file_pages
69 BLACKLIST(237), // mbind
70 BLACKLIST(239), // get_mempolicy
71 BLACKLIST(238), // set_mempolicy
72 BLACKLIST(256), // migrate_pages
73 BLACKLIST(279), // move_pages
74 BLACKLIST(278), // vmsplice
75 BLACKLIST(161), // chroot
76 BLACKLIST(184), // tuxcall
77 BLACKLIST(169), // reboot
78 BLACKLIST(180), // nfsservctl
79 BLACKLIST(177), // get_kernel_syms
80
81 RETURN_ALLOW
82 };
83
84 // save filter to file
85 int dst = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
86 if (dst < 0) {
87 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname);
88 exit(1);
89 }
90
91 int size = (int) sizeof(filter);
92 int written = 0;
93 while (written < size) {
94 int rv = write(dst, (unsigned char *) filter + written, size - written);
95 if (rv == -1) {
96 fprintf(stderr, "Error fseccomp: cannot write %s file\n", fname);
97 exit(1);
98 }
99 written += rv;
100 }
101 close(dst);
102}
103
104// i386 filter installed on amd64 architectures
105void seccomp_secondary_32(const char *fname) {
106 // hardcoded syscall values
107 struct sock_filter filter[] = {
108 VALIDATE_ARCHITECTURE_32,
109 EXAMINE_SYSCALL,
110 BLACKLIST(21), // mount
111 BLACKLIST(52), // umount2
112// todo: implement --allow-debuggers
113 BLACKLIST(26), // ptrace
114 BLACKLIST(283), // kexec_load
115 BLACKLIST(341), // name_to_handle_at
116 BLACKLIST(342), // open_by_handle_at
117 BLACKLIST(127), // create_module
118 BLACKLIST(128), // init_module
119 BLACKLIST(350), // finit_module
120 BLACKLIST(129), // delete_module
121 BLACKLIST(110), // iopl
122 BLACKLIST(101), // ioperm
123 BLACKLIST(289), // ioprio_set
124 BLACKLIST(87), // swapon
125 BLACKLIST(115), // swapoff
126 BLACKLIST(103), // syslog
127 BLACKLIST(347), // process_vm_readv
128 BLACKLIST(348), // process_vm_writev
129 BLACKLIST(135), // sysfs
130 BLACKLIST(149), // _sysctl
131 BLACKLIST(124), // adjtimex
132 BLACKLIST(343), // clock_adjtime
133 BLACKLIST(253), // lookup_dcookie
134 BLACKLIST(336), // perf_event_open
135 BLACKLIST(338), // fanotify_init
136 BLACKLIST(349), // kcmp
137 BLACKLIST(286), // add_key
138 BLACKLIST(287), // request_key
139 BLACKLIST(288), // keyctl
140 BLACKLIST(86), // uselib
141 BLACKLIST(51), // acct
142 BLACKLIST(123), // modify_ldt
143 BLACKLIST(217), // pivot_root
144 BLACKLIST(245), // io_setup
145 BLACKLIST(246), // io_destroy
146 BLACKLIST(247), // io_getevents
147 BLACKLIST(248), // io_submit
148 BLACKLIST(249), // io_cancel
149 BLACKLIST(257), // remap_file_pages
150 BLACKLIST(274), // mbind
151 BLACKLIST(275), // get_mempolicy
152 BLACKLIST(276), // set_mempolicy
153 BLACKLIST(294), // migrate_pages
154 BLACKLIST(317), // move_pages
155 BLACKLIST(316), // vmsplice
156 BLACKLIST(61), // chroot
157 BLACKLIST(88), // reboot
158 BLACKLIST(169), // nfsservctl
159 BLACKLIST(130), // get_kernel_syms
160
161 RETURN_ALLOW
162 };
163
164 // save filter to file
165 int dst = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
166 if (dst < 0) {
167 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname);
168 exit(1);
169 }
170
171 int size = (int) sizeof(filter);
172 int written = 0;
173 while (written < size) {
174 int rv = write(dst, (unsigned char *) filter + written, size - written);
175 if (rv == -1) {
176 fprintf(stderr, "Error fseccomp: cannot write %s file\n", fname);
177 exit(1);
178 }
179 written += rv;
180 }
181 close(dst);
182}
183
diff --git a/src/firejail/syscall.c b/src/fseccomp/syscall.c
index 985cc8bb8..e2052efde 100644
--- a/src/firejail/syscall.c
+++ b/src/fseccomp/syscall.c
@@ -17,9 +17,7 @@
17 * with this program; if not, write to the Free Software Foundation, Inc., 17 * with this program; if not, write to the Free Software Foundation, Inc.,
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 20#include "fseccomp.h"
21#ifdef HAVE_SECCOMP
22#include "firejail.h"
23#include <sys/syscall.h> 21#include <sys/syscall.h>
24 22
25typedef struct { 23typedef struct {
@@ -31,13 +29,25 @@ static SyscallEntry syslist[] = {
31// 29//
32// code generated using tools/extract-syscall 30// code generated using tools/extract-syscall
33// 31//
34#include "syscall.h" 32#include "../include/syscall.h"
35// 33//
36// end of generated code 34// end of generated code
37// 35//
38}; // end of syslist 36}; // end of syslist
39 37
40const char *syscall_find_nr(int nr) { 38// return -1 if error, or syscall number
39int syscall_find_name(const char *name) {
40 int i;
41 int elems = sizeof(syslist) / sizeof(syslist[0]);
42 for (i = 0; i < elems; i++) {
43 if (strcmp(name, syslist[i].name) == 0)
44 return syslist[i].nr;
45 }
46
47 return -1;
48}
49
50char *syscall_find_nr(int nr) {
41 int i; 51 int i;
42 int elems = sizeof(syslist) / sizeof(syslist[0]); 52 int elems = sizeof(syslist) / sizeof(syslist[0]);
43 for (i = 0; i < elems; i++) { 53 for (i = 0; i < elems; i++) {
@@ -48,20 +58,17 @@ const char *syscall_find_nr(int nr) {
48 return "unknown"; 58 return "unknown";
49} 59}
50 60
51// return -1 if error, or syscall number 61void syscall_print(void) {
52static int syscall_find_name(const char *name) {
53 int i; 62 int i;
54 int elems = sizeof(syslist) / sizeof(syslist[0]); 63 int elems = sizeof(syslist) / sizeof(syslist[0]);
55 for (i = 0; i < elems; i++) { 64 for (i = 0; i < elems; i++) {
56 if (strcmp(name, syslist[i].name) == 0) 65 printf("%d\t- %s\n", syslist[i].nr, syslist[i].name);
57 return syslist[i].nr;
58 } 66 }
59 67 printf("\n");
60 return -1;
61} 68}
62 69
63// return 1 if error, 0 if OK 70// return 1 if error, 0 if OK
64int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg), int arg) { 71int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int arg), int fd, int arg) {
65 // don't allow empty lists 72 // don't allow empty lists
66 if (slist == NULL || *slist == '\0') { 73 if (slist == NULL || *slist == '\0') {
67 fprintf(stderr, "Error: empty syscall lists are not allowed\n"); 74 fprintf(stderr, "Error: empty syscall lists are not allowed\n");
@@ -84,7 +91,7 @@ int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg)
84 if (nr == -1) 91 if (nr == -1)
85 fprintf(stderr, "Warning: syscall %s not found\n", start); 92 fprintf(stderr, "Warning: syscall %s not found\n", start);
86 else if (callback != NULL) 93 else if (callback != NULL)
87 callback(nr, arg); 94 callback(fd, nr, arg);
88 95
89 start = ptr + 1; 96 start = ptr + 1;
90 } 97 }
@@ -95,22 +102,9 @@ int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg)
95 if (nr == -1) 102 if (nr == -1)
96 fprintf(stderr, "Warning: syscall %s not found\n", start); 103 fprintf(stderr, "Warning: syscall %s not found\n", start);
97 else if (callback != NULL) 104 else if (callback != NULL)
98 callback(nr, arg); 105 callback(fd, nr, arg);
99 } 106 }
100 107
101 free(str); 108 free(str);
102 return 0; 109 return 0;
103} 110}
104
105void syscall_print(void) {
106 EUID_ASSERT();
107
108 int i;
109 int elems = sizeof(syslist) / sizeof(syslist[0]);
110 for (i = 0; i < elems; i++) {
111 printf("%d\t- %s\n", syslist[i].nr, syslist[i].name);
112 }
113 printf("\n");
114}
115
116#endif // HAVE_SECCOMP
diff --git a/src/include/common.h b/src/include/common.h
index e28870807..f7c8ea725 100644
--- a/src/include/common.h
+++ b/src/include/common.h
@@ -113,5 +113,5 @@ int join_namespace(pid_t pid, char *type);
113int name2pid(const char *name, pid_t *pid); 113int name2pid(const char *name, pid_t *pid);
114char *pid_proc_comm(const pid_t pid); 114char *pid_proc_comm(const pid_t pid);
115char *pid_proc_cmdline(const pid_t pid); 115char *pid_proc_cmdline(const pid_t pid);
116int pid_proc_cmdline_x11(const pid_t pid); 116int pid_proc_cmdline_x11_xpra_xephyr(const pid_t pid);
117#endif 117#endif
diff --git a/src/firejail/seccomp.h b/src/include/seccomp.h
index 7d646dd9e..7d646dd9e 100644
--- a/src/firejail/seccomp.h
+++ b/src/include/seccomp.h
diff --git a/src/firejail/syscall.h b/src/include/syscall.h
index 68d4b5736..9a29779c9 100644
--- a/src/firejail/syscall.h
+++ b/src/include/syscall.h
@@ -20,7 +20,6 @@
20 20
21// content extracted from /bits/syscall.h file form glibc 2.22 21// content extracted from /bits/syscall.h file form glibc 2.22
22// using ../tools/extract_syscall tool 22// using ../tools/extract_syscall tool
23
24#if !defined __x86_64__ 23#if !defined __x86_64__
25#ifdef SYS__llseek 24#ifdef SYS__llseek
26#ifdef __NR__llseek 25#ifdef __NR__llseek
diff --git a/src/lib/common.c b/src/lib/common.c
index acb6bd3b4..fc4c167ba 100644
--- a/src/lib/common.c
+++ b/src/lib/common.c
@@ -201,7 +201,7 @@ char *pid_proc_cmdline(const pid_t pid) {
201} 201}
202 202
203// return 1 if firejail --x11 on command line 203// return 1 if firejail --x11 on command line
204int pid_proc_cmdline_x11(const pid_t pid) { 204int pid_proc_cmdline_x11_xpra_xephyr(const pid_t pid) {
205 // if comm is not firejail return 0 205 // if comm is not firejail return 0
206 char *comm = pid_proc_comm(pid); 206 char *comm = pid_proc_comm(pid);
207 if (strcmp(comm, "firejail") != 0) { 207 if (strcmp(comm, "firejail") != 0) {
@@ -248,8 +248,11 @@ int pid_proc_cmdline_x11(const pid_t pid) {
248 break; 248 break;
249 if (strncmp(arg, "--", 2) != 0) 249 if (strncmp(arg, "--", 2) != 0)
250 break; 250 break;
251 251
252 // check x11 252 if (strcmp(arg, "--x11=xorg") == 0)
253 return 0;
254
255 // check x11 xpra or xephyr
253 if (strncmp(arg, "--x11", 5) == 0) 256 if (strncmp(arg, "--x11", 5) == 0)
254 return 1; 257 return 1;
255 i += strlen(arg); 258 i += strlen(arg);
diff --git a/src/lib/pid.c b/src/lib/pid.c
index bbb123b81..ef1a428fb 100644
--- a/src/lib/pid.c
+++ b/src/lib/pid.c
@@ -341,7 +341,7 @@ void pid_read(pid_t mon_pid) {
341 } 341 }
342 342
343 if ((strncmp(ptr, "firejail", 8) == 0) && (mon_pid == 0 || mon_pid == pid)) { 343 if ((strncmp(ptr, "firejail", 8) == 0) && (mon_pid == 0 || mon_pid == pid)) {
344 if (pid_proc_cmdline_x11(pid)) 344 if (pid_proc_cmdline_x11_xpra_xephyr(pid))
345 pids[pid].level = -1; 345 pids[pid].level = -1;
346 else 346 else
347 pids[pid].level = 1; 347 pids[pid].level = 1;
diff --git a/src/man/firejail-login.txt b/src/man/firejail-login.txt
index 691217253..796179d0b 100644
--- a/src/man/firejail-login.txt
+++ b/src/man/firejail-login.txt
@@ -13,6 +13,10 @@ Example:
13 13
14 netblue:--net=none --protocol=unix 14 netblue:--net=none --protocol=unix
15 15
16Wildcard patterns are accepted in the user name field:
17
18 user*: --private
19
16.SH RESTRICTED SHELL 20.SH RESTRICTED SHELL
17To configure a restricted shell, replace /bin/bash with /usr/bin/firejail in 21To configure a restricted shell, replace /bin/bash with /usr/bin/firejail in
18/etc/passwd file for each user that needs to be restricted. Alternatively, 22/etc/passwd file for each user that needs to be restricted. Alternatively,
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt
index d420fab7a..09dc46bbc 100644
--- a/src/man/firejail-profile.txt
+++ b/src/man/firejail-profile.txt
@@ -218,7 +218,7 @@ Blacklist violations logged to syslog.
218Whitelist directory or file. A temporary file system is mounted on the top directory, and the 218Whitelist directory or file. A temporary file system is mounted on the top directory, and the
219whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent, 219whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent,
220everything else is discarded when the sandbox is closed. The top directory could be 220everything else is discarded when the sandbox is closed. The top directory could be
221user home, /dev, /media, /mnt, /opt, /var, and /tmp. 221user home, /dev, /media, /mnt, /opt, /srv, /var, and /tmp.
222.br 222.br
223 223
224.br 224.br
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index 4aebb71e8..666a6a8ef 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -1622,7 +1622,7 @@ $ firejail \-\-net=br0 --veth-name=if0
1622Whitelist directory or file. A temporary file system is mounted on the top directory, and the 1622Whitelist directory or file. A temporary file system is mounted on the top directory, and the
1623whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent, 1623whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent,
1624everything else is discarded when the sandbox is closed. The top directory could be 1624everything else is discarded when the sandbox is closed. The top directory could be
1625user home, /dev, /media, /mnt, /opt, /var, and /tmp. 1625user home, /dev, /media, /mnt, /opt, /srv, /var, and /tmp.
1626.br 1626.br
1627 1627
1628.br 1628.br
diff --git a/test/apps-x11-xorg/apps-x11-xorg.sh b/test/apps-x11-xorg/apps-x11-xorg.sh
new file mode 100755
index 000000000..b05914b52
--- /dev/null
+++ b/test/apps-x11-xorg/apps-x11-xorg.sh
@@ -0,0 +1,35 @@
1#!/bin/bash
2# This file is part of Firejail project
3# Copyright (C) 2014-2016 Firejail Authors
4# License GPL v2
5
6export MALLOC_CHECK_=3
7export MALLOC_PERTURB_=$(($RANDOM % 255 + 1))
8
9which firefox
10if [ "$?" -eq 0 ];
11then
12 echo "TESTING: firefox x11 xorg"
13 ./firefox.exp
14else
15 echo "TESTING SKIP: firefox not found"
16fi
17
18which transmission-gtk
19if [ "$?" -eq 0 ];
20then
21 echo "TESTING: transmission-gtk x11 xorg"
22 ./transmission-gtk.exp
23else
24 echo "TESTING SKIP: transmission-gtk not found"
25fi
26
27which icedove
28if [ "$?" -eq 0 ];
29then
30 echo "TESTING: icedove x11 xorg"
31 ./icedove.exp
32else
33 echo "TESTING SKIP: icedove not found"
34fi
35
diff --git a/test/apps-x11-xorg/firefox.exp b/test/apps-x11-xorg/firefox.exp
new file mode 100755
index 000000000..5231bf8ed
--- /dev/null
+++ b/test/apps-x11-xorg/firefox.exp
@@ -0,0 +1,90 @@
1#!/usr/bin/expect -f
2# This file is part of Firejail project
3# Copyright (C) 2014-2016 Firejail Authors
4# License GPL v2
5
6set timeout 10
7spawn $env(SHELL)
8match_max 100000
9
10send -- "firejail --name=test --x11=xorg firefox -no-remote www.gentoo.org\r"
11sleep 10
12
13spawn $env(SHELL)
14send -- "firejail --list\r"
15expect {
16 timeout {puts "TESTING ERROR 3\n";exit}
17 ":firejail"
18}
19expect {
20 timeout {puts "TESTING ERROR 3.1\n";exit}
21 "firefox" {puts "firefox detected\n";}
22 "iceweasel" {puts "iceweasel detected\n";}
23}
24expect {
25 timeout {puts "TESTING ERROR 3.2\n";exit}
26 "no-remote"
27}
28sleep 1
29# grsecurity exit
30send -- "file /proc/sys/kernel/grsecurity\r"
31expect {
32 timeout {puts "TESTING ERROR - grsecurity detection\n";exit}
33 "grsecurity: directory" {puts "grsecurity present, exiting...\n";exit}
34 "cannot open" {puts "grsecurity not present\n"}
35}
36send -- "firejail --name=blablabla\r"
37expect {
38 timeout {puts "TESTING ERROR 4\n";exit}
39 "Child process initialized"
40}
41sleep 2
42
43spawn $env(SHELL)
44send -- "firemon --seccomp\r"
45expect {
46 timeout {puts "TESTING ERROR 5\n";exit}
47 " firefox" {puts "firefox detected\n";}
48 " iceweasel" {puts "iceweasel detected\n";}
49}
50expect {
51 timeout {puts "TESTING ERROR 5.0\n";exit}
52 "no-remote"
53}
54expect {
55 timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit}
56 "Seccomp: 2"
57}
58expect {
59 timeout {puts "TESTING ERROR 5.1\n";exit}
60 "name=blablabla"
61}
62sleep 1
63send -- "firemon --caps\r"
64expect {
65 timeout {puts "TESTING ERROR 6\n";exit}
66 " firefox" {puts "firefox detected\n";}
67 " iceweasel" {puts "iceweasel detected\n";}
68}
69expect {
70 timeout {puts "TESTING ERROR 6.0\n";exit}
71 "no-remote"
72}
73expect {
74 timeout {puts "TESTING ERROR 6.1\n";exit}
75 "CapBnd:"
76}
77expect {
78 timeout {puts "TESTING ERROR 6.2\n";exit}
79 "0000000000000000"
80}
81expect {
82 timeout {puts "TESTING ERROR 6.3\n";exit}
83 "name=blablabla"
84}
85sleep 1
86send -- "firejail --shutdown=test\r"
87sleep 3
88
89puts "\nall done\n"
90
diff --git a/test/apps-x11-xorg/icedove.exp b/test/apps-x11-xorg/icedove.exp
new file mode 100755
index 000000000..f676264ed
--- /dev/null
+++ b/test/apps-x11-xorg/icedove.exp
@@ -0,0 +1,85 @@
1#!/usr/bin/expect -f
2# This file is part of Firejail project
3# Copyright (C) 2014-2016 Firejail Authors
4# License GPL v2
5
6set timeout 10
7spawn $env(SHELL)
8match_max 100000
9
10send -- "firejail --name=test --x11=xorg icedove\r"
11sleep 10
12
13spawn $env(SHELL)
14send -- "firejail --list\r"
15expect {
16 timeout {puts "TESTING ERROR 3\n";exit}
17 ":firejail"
18}
19expect {
20 timeout {puts "TESTING ERROR 3.1\n";exit}
21 "icedove"
22}
23sleep 1
24
25# grsecurity exit
26send -- "file /proc/sys/kernel/grsecurity\r"
27expect {
28 timeout {puts "TESTING ERROR - grsecurity detection\n";exit}
29 "grsecurity: directory" {puts "grsecurity present, exiting...\n";exit}
30 "cannot open" {puts "grsecurity not present\n"}
31}
32
33send -- "firejail --name=blablabla\r"
34expect {
35 timeout {puts "TESTING ERROR 4\n";exit}
36 "Child process initialized"
37}
38sleep 2
39
40spawn $env(SHELL)
41send -- "firemon --seccomp\r"
42expect {
43 timeout {puts "TESTING ERROR 5\n";exit}
44 ":firejail"
45}
46expect {
47 timeout {puts "TESTING ERROR 5.0\n";exit}
48 "icedove"
49}
50expect {
51 timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit}
52 "Seccomp: 2"
53}
54expect {
55 timeout {puts "TESTING ERROR 5.1\n";exit}
56 "name=blablabla"
57}
58sleep 2
59send -- "firemon --caps\r"
60expect {
61 timeout {puts "TESTING ERROR 6\n";exit}
62 ":firejail"
63}
64expect {
65 timeout {puts "TESTING ERROR 6.0\n";exit}
66 "icedove"
67}
68expect {
69 timeout {puts "TESTING ERROR 6.1\n";exit}
70 "CapBnd"
71}
72expect {
73 timeout {puts "TESTING ERROR 6.2\n";exit}
74 "0000000000000000"
75}
76expect {
77 timeout {puts "TESTING ERROR 6.3\n";exit}
78 "name=blablabla"
79}
80sleep 1
81send -- "firejail --shutdown=test\r"
82sleep 3
83
84puts "\nall done\n"
85
diff --git a/test/apps-x11-xorg/transmission-gtk.exp b/test/apps-x11-xorg/transmission-gtk.exp
new file mode 100755
index 000000000..a91a1be08
--- /dev/null
+++ b/test/apps-x11-xorg/transmission-gtk.exp
@@ -0,0 +1,85 @@
1#!/usr/bin/expect -f
2# This file is part of Firejail project
3# Copyright (C) 2014-2016 Firejail Authors
4# License GPL v2
5
6set timeout 10
7spawn $env(SHELL)
8match_max 100000
9
10send -- "firejail --name=test --x11=xorg transmission-gtk\r"
11sleep 10
12
13spawn $env(SHELL)
14send -- "firejail --list\r"
15expect {
16 timeout {puts "TESTING ERROR 3\n";exit}
17 ":firejail"
18}
19expect {
20 timeout {puts "TESTING ERROR 3.1\n";exit}
21 "transmission-gtk"
22}
23sleep 1
24
25# grsecurity exit
26send -- "file /proc/sys/kernel/grsecurity\r"
27expect {
28 timeout {puts "TESTING ERROR - grsecurity detection\n";exit}
29 "grsecurity: directory" {puts "grsecurity present, exiting...\n";exit}
30 "cannot open" {puts "grsecurity not present\n"}
31}
32
33send -- "firejail --name=blablabla\r"
34expect {
35 timeout {puts "TESTING ERROR 4\n";exit}
36 "Child process initialized"
37}
38sleep 2
39
40spawn $env(SHELL)
41send -- "firemon --seccomp\r"
42expect {
43 timeout {puts "TESTING ERROR 5\n";exit}
44 ":firejail"
45}
46expect {
47 timeout {puts "TESTING ERROR 5.0\n";exit}
48 "transmission-gtk"
49}
50expect {
51 timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit}
52 "Seccomp: 2"
53}
54expect {
55 timeout {puts "TESTING ERROR 5.1\n";exit}
56 "name=blablabla"
57}
58sleep 1
59send -- "firemon --caps\r"
60expect {
61 timeout {puts "TESTING ERROR 6\n";exit}
62 ":firejail"
63}
64expect {
65 timeout {puts "TESTING ERROR 6.0\n";exit}
66 "transmission-gtk"
67}
68expect {
69 timeout {puts "TESTING ERROR 6.1\n";exit}
70 "CapBnd"
71}
72expect {
73 timeout {puts "TESTING ERROR 6.2\n";exit}
74 "0000000000000000"
75}
76expect {
77 timeout {puts "TESTING ERROR 6.3\n";exit}
78 "name=blablabla"
79}
80sleep 1
81send -- "firejail --shutdown=test\r"
82sleep 3
83
84puts "\nall done\n"
85
diff --git a/test/environment/allow-debuggers.exp b/test/environment/allow-debuggers.exp
index dde9c4cc1..8a404decb 100755
--- a/test/environment/allow-debuggers.exp
+++ b/test/environment/allow-debuggers.exp
@@ -11,19 +11,27 @@ expect {
11 "Child process initialized" 11 "Child process initialized"
12} 12}
13expect { 13expect {
14 timeout {puts "TESTING ERROR 1\n";exit} 14 timeout {puts "TESTING ERROR 1\n";exit}
15 "exited with 0" 15 "ioctl"
16}
17expect {
18 timeout {puts "TESTING ERROR 2\n";exit}
19 "exit_group"
16} 20}
17after 100 21after 100
18 22
19send -- "firejail --allow-debuggers --profile=/etc/firejail/firefox.profile strace ls\r" 23send -- "firejail --allow-debuggers --profile=/etc/firejail/firefox.profile strace ls\r"
20expect { 24expect {
21 timeout {puts "TESTING ERROR 2\n";exit} 25 timeout {puts "TESTING ERROR 3\n";exit}
22 "Child process initialized" 26 "Child process initialized"
23} 27}
24expect { 28expect {
25 timeout {puts "TESTING ERROR 3\n";exit} 29 timeout {puts "TESTING ERROR 4\n";exit}
26 "exited with 0" 30 "ioctl"
31}
32expect {
33 timeout {puts "TESTING ERROR 5\n";exit}
34 "exit_group"
27} 35}
28after 100 36after 100
29 37
diff --git a/test/filters/filters.sh b/test/filters/filters.sh
index 5093c8614..5c7c98b3e 100755
--- a/test/filters/filters.sh
+++ b/test/filters/filters.sh
@@ -12,11 +12,21 @@ echo "TESTING: noroot (test/filters/noroot.exp)"
12echo "TESTING: capabilities (test/filters/caps.exp)" 12echo "TESTING: capabilities (test/filters/caps.exp)"
13./caps.exp 13./caps.exp
14 14
15rm -f seccomp-test-file
16if [ "$(uname -m)" = "x86_64" ]; then
17 echo "TESTING: fseccomp (test/filters/fseccomp.exp)"
18 ./fseccomp.exp
19else
20 echo "TESTING SKIP: fseccomp test implemented only for x86_64"
21fi
22rm -f seccomp-test-file
23
24
15if [ "$(uname -m)" = "x86_64" ]; then 25if [ "$(uname -m)" = "x86_64" ]; then
16 echo "TESTING: protocol (test/filters/protocol.exp)" 26 echo "TESTING: protocol (test/filters/protocol.exp)"
17 ./protocol.exp 27 ./protocol.exp
18else 28else
19 echo "TESTING SKIP: protocol, not running on x86_64" 29 echo "TESTING SKIP: protocol, running only on x86_64"
20fi 30fi
21 31
22echo "TESTING: seccomp bad empty (test/filters/seccomp-bad-empty.exp)" 32echo "TESTING: seccomp bad empty (test/filters/seccomp-bad-empty.exp)"
@@ -50,9 +60,6 @@ echo "TESTING: seccomp chmod profile - seccomp lists (test/filters/seccomp-chmod
50echo "TESTING: seccomp empty (test/filters/seccomp-empty.exp)" 60echo "TESTING: seccomp empty (test/filters/seccomp-empty.exp)"
51./seccomp-empty.exp 61./seccomp-empty.exp
52 62
53echo "TESTING: seccomp bad empty (test/filters/seccomp-bad-empty.exp)"
54./seccomp-bad-empty.exp
55
56if [ "$(uname -m)" = "x86_64" ]; then 63if [ "$(uname -m)" = "x86_64" ]; then
57 echo "TESTING: seccomp dual filter (test/filters/seccomp-dualfilter.exp)" 64 echo "TESTING: seccomp dual filter (test/filters/seccomp-dualfilter.exp)"
58 ./seccomp-dualfilter.exp 65 ./seccomp-dualfilter.exp
diff --git a/test/filters/fseccomp.exp b/test/filters/fseccomp.exp
new file mode 100755
index 000000000..8a9a8f9dc
--- /dev/null
+++ b/test/filters/fseccomp.exp
@@ -0,0 +1,138 @@
1#!/usr/bin/expect -f
2# This file is part of Firejail project
3# Copyright (C) 2014-2016 Firejail Authors
4# License GPL v2
5
6set timeout 10
7spawn $env(SHELL)
8match_max 100000
9
10after 100
11send -- "/usr/lib/firejail/fseccomp debug-syscalls\r"
12expect {
13 timeout {puts "TESTING ERROR 1\n";exit}
14 "1 - write"
15}
16
17after 100
18send -- "/usr/lib/firejail/fseccomp debug-errnos\r"
19expect {
20 timeout {puts "TESTING ERROR 2\n";exit}
21 "1 - EPERM"
22}
23
24after 100
25send -- "/usr/lib/firejail/fseccomp debug-protocols\r"
26expect {
27 timeout {puts "TESTING ERROR 3\n";exit}
28 "unix, inet, inet6, netlink, packet,"
29}
30
31after 100
32send -- "/usr/lib/firejail/fseccomp protocol build unix,inet seccomp-test-file\r"
33after 100
34send -- "/usr/lib/firejail/fseccomp print seccomp-test-file\r"
35expect {
36 timeout {puts "TESTING ERROR 4.1\n";exit}
37 "WHITELIST 41 socket"
38}
39
40after 100
41send -- "/usr/lib/firejail/fseccomp secondary 64 seccomp-test-file\r"
42after 100
43send -- "/usr/lib/firejail/fseccomp print seccomp-test-file\r"
44expect {
45 timeout {puts "TESTING ERROR 5.1\n";exit}
46 "BLACKLIST 165 mount"
47}
48expect {
49 timeout {puts "TESTING ERROR 5.2\n";exit}
50 "BLACKLIST 166 umount2"
51}
52expect {
53 timeout {puts "TESTING ERROR 5.3\n";exit}
54 "RETURN_ALLOW"
55}
56
57after 100
58send -- "/usr/lib/firejail/fseccomp default seccomp-test-file\r"
59after 100
60send -- "/usr/lib/firejail/fseccomp print seccomp-test-file\r"
61expect {
62 timeout {puts "TESTING ERROR 6.1\n";exit}
63 "BLACKLIST 165 mount"
64}
65expect {
66 timeout {puts "TESTING ERROR 6.2\n";exit}
67 "BLACKLIST 166 umount2"
68}
69expect {
70 timeout {puts "TESTING ERROR 6.3\n";exit}
71 "RETURN_ALLOW"
72}
73
74after 100
75send -- "/usr/lib/firejail/fseccomp drop seccomp-test-file chmod,chown\r"
76after 100
77send -- "/usr/lib/firejail/fseccomp print seccomp-test-file\r"
78expect {
79 timeout {puts "TESTING ERROR 7.1\n";exit}
80 "BLACKLIST 165 mount" {puts "TESTING ERROR 7.2\n";exit}
81 "BLACKLIST 166 umount2" {puts "TESTING ERROR 7.3\n";exit}
82 "BLACKLIST 90 chmod"
83}
84expect {
85 timeout {puts "TESTING ERROR 7.4\n";exit}
86 "BLACKLIST 92 chown"
87}
88expect {
89 timeout {puts "TESTING ERROR 7.5\n";exit}
90 "RETURN_ALLOW"
91}
92
93after 100
94send -- "/usr/lib/firejail/fseccomp default drop seccomp-test-file chmod,chown\r"
95after 100
96send -- "/usr/lib/firejail/fseccomp print seccomp-test-file\r"
97expect {
98 timeout {puts "TESTING ERROR 8.1\n";exit}
99 "BLACKLIST 165 mount"
100}
101expect {
102 timeout {puts "TESTING ERROR 8.2\n";exit}
103 "BLACKLIST 166 umount2"
104}
105expect {
106 timeout {puts "TESTING ERROR 8.3\n";exit}
107 "BLACKLIST 90 chmod"
108}
109expect {
110 timeout {puts "TESTING ERROR 8.4\n";exit}
111 "BLACKLIST 92 chown"
112}
113expect {
114 timeout {puts "TESTING ERROR 8.5\n";exit}
115 "RETURN_ALLOW"
116}
117after 100
118send -- "/usr/lib/firejail/fseccomp keep seccomp-test-file chmod,chown\r"
119after 100
120send -- "/usr/lib/firejail/fseccomp print seccomp-test-file\r"
121expect {
122 timeout {puts "TESTING ERROR 9.1\n";exit}
123 "WHITELIST 90 chmod"
124}
125expect {
126 timeout {puts "TESTING ERROR 9.2\n";exit}
127 "WHITELIST 92 chown"
128}
129expect {
130 timeout {puts "TESTING ERROR 9.3\n";exit}
131 "KILL_PROCESS"
132}
133
134
135
136after 100
137puts "\nall done\n"
138
diff --git a/test/filters/noroot.exp b/test/filters/noroot.exp
index 2a7cb7975..b011f2bf9 100755
--- a/test/filters/noroot.exp
+++ b/test/filters/noroot.exp
@@ -46,20 +46,20 @@ expect {
46} 46}
47send -- "sudo -s\r" 47send -- "sudo -s\r"
48expect { 48expect {
49 timeout {puts "TESTING ERROR 8\n";exit} 49 timeout {puts "TESTING ERROR 7\n";exit}
50 "effective uid is not 0, is sudo installed setuid root?" { puts "OK\n";} 50 "effective uid is not 0, is sudo installed setuid root?" { puts "OK\n";}
51 "sudo must be owned by uid 0 and have the setuid bit set" { puts "OK\n";} 51 "sudo must be owned by uid 0 and have the setuid bit set" { puts "OK\n";}
52 "Bad system call" { puts "OK\n";} 52 "Bad system call" { puts "OK\n";}
53} 53}
54send -- "cat /proc/self/uid_map | wc -l\r" 54send -- "cat /proc/self/uid_map | wc -l\r"
55expect { 55expect {
56 timeout {puts "TESTING ERROR 7\n";exit} 56 timeout {puts "TESTING ERROR 8\n";exit}
57 "1" 57 "1"
58} 58}
59send -- "cat /proc/self/gid_map | wc -l\r" 59send -- "cat /proc/self/gid_map | wc -l\r"
60expect { 60expect {
61 timeout {puts "TESTING ERROR 8\n";exit} 61 timeout {puts "TESTING ERROR 9\n";exit}
62 "3" 62 "5"
63} 63}
64 64
65puts "\n" 65puts "\n"
@@ -70,59 +70,59 @@ sleep 2
70 70
71send -- "firejail --name=test --noroot --noprofile\r" 71send -- "firejail --name=test --noroot --noprofile\r"
72expect { 72expect {
73 timeout {puts "TESTING ERROR 9\n";exit} 73 timeout {puts "TESTING ERROR 10\n";exit}
74 "Child process initialized" 74 "Child process initialized"
75} 75}
76sleep 1 76sleep 1
77 77
78send -- "cat /proc/self/status\r" 78send -- "cat /proc/self/status\r"
79expect { 79expect {
80 timeout {puts "TESTING ERROR 10\n";exit} 80 timeout {puts "TESTING ERROR 11\n";exit}
81 "CapBnd:" 81 "CapBnd:"
82} 82}
83expect { 83expect {
84 timeout {puts "TESTING ERROR 11\n";exit} 84 timeout {puts "TESTING ERROR 12\n";exit}
85 "ffffffff" 85 "ffffffff"
86} 86}
87expect { 87expect {
88 timeout {puts "TESTING ERROR 12\n";exit} 88 timeout {puts "TESTING ERROR 13\n";exit}
89 "Seccomp:" 89 "Seccomp:"
90} 90}
91expect { 91expect {
92 timeout {puts "TESTING ERROR 13\n";exit} 92 timeout {puts "TESTING ERROR 14\n";exit}
93 "0" 93 "0"
94} 94}
95expect { 95expect {
96 timeout {puts "TESTING ERROR 14\n";exit} 96 timeout {puts "TESTING ERROR 15\n";exit}
97 "Cpus_allowed:" 97 "Cpus_allowed:"
98} 98}
99puts "\n" 99puts "\n"
100 100
101send -- "whoami\r" 101send -- "whoami\r"
102expect { 102expect {
103 timeout {puts "TESTING ERROR 15\n";exit} 103 timeout {puts "TESTING ERROR 16\n";exit}
104 $env(USER) 104 $env(USER)
105} 105}
106send -- "sudo -s\r" 106send -- "sudo -s\r"
107expect { 107expect {
108 timeout {puts "TESTING ERROR 16\n";exit} 108 timeout {puts "TESTING ERROR 17\n";exit}
109 "effective uid is not 0, is sudo installed setuid root?" { puts "OK\n";} 109 "effective uid is not 0, is sudo installed setuid root?" { puts "OK\n";}
110 "sudo must be owned by uid 0 and have the setuid bit set" { puts "OK\n";} 110 "sudo must be owned by uid 0 and have the setuid bit set" { puts "OK\n";}
111} 111}
112send -- "ping 0\r" 112send -- "ping 0\r"
113expect { 113expect {
114 timeout {puts "TESTING ERROR 17\n";exit} 114 timeout {puts "TESTING ERROR 18\n";exit}
115 "Operation not permitted" 115 "Operation not permitted"
116} 116}
117send -- "cat /proc/self/uid_map | wc -l\r" 117send -- "cat /proc/self/uid_map | wc -l\r"
118expect { 118expect {
119 timeout {puts "TESTING ERROR 18\n";exit} 119 timeout {puts "TESTING ERROR 19\n";exit}
120 "1" 120 "1"
121} 121}
122send -- "cat /proc/self/gid_map | wc -l\r" 122send -- "cat /proc/self/gid_map | wc -l\r"
123expect { 123expect {
124 timeout {puts "TESTING ERROR 19\n";exit} 124 timeout {puts "TESTING ERROR 20\n";exit}
125 "3" 125 "5"
126} 126}
127 127
128 128
@@ -130,31 +130,31 @@ expect {
130spawn $env(SHELL) 130spawn $env(SHELL)
131send -- "firejail --debug --join=test\r" 131send -- "firejail --debug --join=test\r"
132expect { 132expect {
133 timeout {puts "TESTING ERROR 20\n";exit} 133 timeout {puts "TESTING ERROR 21\n";exit}
134 "User namespace detected" 134 "User namespace detected"
135} 135}
136expect { 136expect {
137 timeout {puts "TESTING ERROR 21\n";exit} 137 timeout {puts "TESTING ERROR 22\n";exit}
138 "Joining user namespace" 138 "Joining user namespace"
139} 139}
140sleep 1 140sleep 1
141 141
142send -- "sudo -s\r" 142send -- "sudo -s\r"
143expect { 143expect {
144 timeout {puts "TESTING ERROR 22\n";exit} 144 timeout {puts "TESTING ERROR 23\n";exit}
145 "effective uid is not 0, is sudo installed setuid root?" { puts "OK\n";} 145 "effective uid is not 0, is sudo installed setuid root?" { puts "OK\n";}
146 "sudo must be owned by uid 0 and have the setuid bit set" { puts "OK\n";} 146 "sudo must be owned by uid 0 and have the setuid bit set" { puts "OK\n";}
147 "Permission denied" { puts "OK\n";} 147 "Permission denied" { puts "OK\n";}
148} 148}
149send -- "cat /proc/self/uid_map | wc -l\r" 149send -- "cat /proc/self/uid_map | wc -l\r"
150expect { 150expect {
151 timeout {puts "TESTING ERROR 23\n";exit} 151 timeout {puts "TESTING ERROR 24\n";exit}
152 "1" 152 "1"
153} 153}
154send -- "cat /proc/self/gid_map | wc -l\r" 154send -- "cat /proc/self/gid_map | wc -l\r"
155expect { 155expect {
156 timeout {puts "TESTING ERROR 24\n";exit} 156 timeout {puts "TESTING ERROR 25\n";exit}
157 "3" 157 "5"
158} 158}
159after 100 159after 100
160puts "\nall done\n" 160puts "\nall done\n"
diff --git a/test/fs/fs.sh b/test/fs/fs.sh
index d45ef48bd..3139b8eae 100755
--- a/test/fs/fs.sh
+++ b/test/fs/fs.sh
@@ -6,6 +6,9 @@
6export MALLOC_CHECK_=3 6export MALLOC_CHECK_=3
7export MALLOC_PERTURB_=$(($RANDOM % 255 + 1)) 7export MALLOC_PERTURB_=$(($RANDOM % 255 + 1))
8 8
9echo "TESTING: /sys/fs access (test/fs/sys_fs.exp)"
10./sys_fs.exp
11
9echo "TESTING: kmsg access (test/fs/kmsg.exp)" 12echo "TESTING: kmsg access (test/fs/kmsg.exp)"
10./kmsg.exp 13./kmsg.exp
11 14
diff --git a/test/fs/sys_fs.exp b/test/fs/sys_fs.exp
new file mode 100755
index 000000000..f512776d9
--- /dev/null
+++ b/test/fs/sys_fs.exp
@@ -0,0 +1,44 @@
1#!/usr/bin/expect -f
2# This file is part of Firejail project
3# Copyright (C) 2014-2016 Firejail Authors
4# License GPL v2
5
6set timeout 10
7spawn $env(SHELL)
8match_max 100000
9
10send -- "firejail\r"
11expect {
12 timeout {puts "TESTING ERROR 1\n";exit}
13 "Child process initialized"
14}
15sleep 1
16
17send -- "ls /sys/fs\r"
18expect {
19 timeout {puts "TESTING ERROR 2\n";exit}
20 "Permission denied"
21}
22after 100
23
24send -- "exit\r"
25sleep 1
26
27send -- "firejail --noblacklist=/sys/fs\r"
28expect {
29 timeout {puts "TESTING ERROR 1\n";exit}
30 "Child process initialized"
31}
32sleep 1
33
34send -- "ls /sys/fs\r"
35expect {
36 timeout {puts "TESTING ERROR 2\n";exit}
37 "cgroup"
38}
39after 100
40send -- "exit\r"
41after 100
42
43puts "\nall done\n"
44