diff options
author | vis <vis@mailbox.org> | 2016-11-03 15:06:57 +0100 |
---|---|---|
committer | vis <vis@mailbox.org> | 2016-11-03 15:06:57 +0100 |
commit | 2aafd9bd3a96b578bf423eb8faba0efe965c52d5 (patch) | |
tree | 6ab4d26a6daad1e3972a86dbdcbe67030d710883 | |
parent | Improvements for Zathura profile (diff) | |
parent | removed warning if --quiet is enabled (diff) | |
download | firejail-2aafd9bd3a96b578bf423eb8faba0efe965c52d5.tar.gz firejail-2aafd9bd3a96b578bf423eb8faba0efe965c52d5.tar.zst firejail-2aafd9bd3a96b578bf423eb8faba0efe965c52d5.zip |
Merge remote-tracking branch 'upstream/master'
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 | |||
18 | src/ftee/ftee | 18 | src/ftee/ftee |
19 | src/tags | 19 | src/tags |
20 | src/faudit/faudit | 20 | src/faudit/faudit |
21 | src/fnet/fnet | ||
22 | src/fseccomp/fseccomp | ||
21 | uids.h | 23 | uids.h |
diff --git a/Makefile.in b/Makefile.in index 3f08c5952..86acc206c 100644 --- a/Makefile.in +++ b/Makefile.in | |||
@@ -1,6 +1,6 @@ | |||
1 | all: apps man | 1 | all: apps man |
2 | MYLIBS = src/lib | 2 | MYLIBS = src/lib |
3 | APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/libconnect | 3 | APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/libconnect src/fnet src/fseccomp |
4 | MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 | 4 | MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 |
5 | 5 | ||
6 | prefix=@prefix@ | 6 | prefix=@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 | ||
129 | uninstall: | 133 | uninstall: |
@@ -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 | ||
143 | DISTFILES = "src etc platform configure configure.ac Makefile.in install.sh mkman.sh mketc.sh mkdeb.sh mkuid.sh COPYING README RELNOTES" | 147 | DISTFILES = "src etc platform configure configure.ac Makefile.in install.sh mkman.sh mketc.sh mkdeb.sh mkuid.sh COPYING README RELNOTES" |
144 | DISTFILES_TEST = "test/apps test/apps-x11 test/environment test/profiles test/utils test/compile test/filters test/network test/fs test/sysutils" | 148 | DISTFILES_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 | ||
146 | dist: | 150 | dist: |
147 | mv config.status config.status.old | 151 | mv config.status config.status.old |
@@ -195,6 +199,9 @@ test-apps: | |||
195 | test-apps-x11: | 199 | test-apps-x11: |
196 | cd test/apps-x11; ./apps-x11.sh | grep TESTING | 200 | cd test/apps-x11; ./apps-x11.sh | grep TESTING |
197 | 201 | ||
202 | test-apps-x11-xorg: | ||
203 | cd test/apps-x11-xorg; ./apps-x11-xorg.sh | grep TESTING | ||
204 | |||
198 | test-sysutils: | 205 | test-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: | |||
213 | test-fs: | 220 | test-fs: |
214 | cd test/fs; ./fs.sh | grep TESTING | 221 | cd test/fs; ./fs.sh | grep TESTING |
215 | 222 | ||
216 | test: test-profiles test-fs test-utils test-environment test-apps test-apps-x11 test-filters | 223 | test: 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" |
@@ -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 |
49 | Fred-Barclay (https://github.com/Fred-Barclay) | 49 | Fred-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 | ||
83 | Impyy (https://github.com/Impyy) | ||
84 | - added mumble profile | ||
85 | valoq (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 | ||
91 | Vadim A. Misbakh-Soloviov (https://github.com/msva) | ||
92 | - profile fixes | ||
93 | Rafael Cavalcanti (https://github.com/rccavalcanti) | ||
94 | - chromium profile fixes for Arch Linux | ||
95 | Deelvesh Bunjun (https://github.com/DeelveshBunjun) | ||
96 | - added xpdf profile | ||
97 | vismir2 (https://github.com/vismir2) | ||
98 | - claws-mail, mutt, git, emacs, vim profiles | ||
99 | Dara Adib (https://github.com/daradib) | ||
100 | - ssh profile fix | ||
101 | - evince profile fix | ||
80 | vismir2 (https://github.com/vismir2) | 102 | vismir2 (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 |
83 | graywolf (https://github.com/graywolf) | 105 | graywolf (https://github.com/graywolf) |
84 | - spelling fix | 106 | - spelling fix |
85 | Dara Adib (https://github.com/daradib) | ||
86 | - ssh profile fix | ||
87 | Tomasz Jan Góralczyk (https://github.com/tjg) | 107 | Tomasz Jan Góralczyk (https://github.com/tjg) |
88 | - fixed Steam profile | 108 | - fixed Steam profile |
89 | pwnage-pineapple (https://github.com/pwnage-pineapple) | 109 | pwnage-pineapple (https://github.com/pwnage-pineapple) |
@@ -40,75 +40,17 @@ FAQ: https://firejail.wordpress.com/support/frequently-asked-questions/ | |||
40 | If you keep your Firejail profiles in a public repository, please give us a link: | 40 | If 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 | 46 | Use 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 | |
109 | x11 xpra, x11 xephyr, x11 none, x11 xorg, allusers, join-or-start | 55 | xiphos, Tor Browser Bundle, display (imagemagik), Wire, mumble |
110 | |||
111 | ## New profiles | ||
112 | |||
113 | qpdfview, mupdf, Luminance HDR, Synfig Studio, Gimp, Inkscape, feh, ranger, zathura, 7z, keepass, keepassx | ||
114 | 56 | ||
@@ -1,9 +1,19 @@ | |||
1 | firejail (0.9.43) baseline; urgency=low | 1 | firejail (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 | |||
10 | firejail (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 | ||
23 | firejail (0.9.42) baseline; urgency=low | 38 | firejail (0.9.42) baseline; urgency=low |
24 | * security: --whitelist deleted files, submitted by Vasya Novikov | 39 | * security: --whitelist deleted files, submitted by Vasya Novikov |
@@ -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. |
581 | PACKAGE_NAME='firejail' | 581 | PACKAGE_NAME='firejail' |
582 | PACKAGE_TARNAME='firejail' | 582 | PACKAGE_TARNAME='firejail' |
583 | PACKAGE_VERSION='0.9.43' | 583 | PACKAGE_VERSION='0.9.45' |
584 | PACKAGE_STRING='firejail 0.9.43' | 584 | PACKAGE_STRING='firejail 0.9.45' |
585 | PACKAGE_BUGREPORT='netblue30@yahoo.com' | 585 | PACKAGE_BUGREPORT='netblue30@yahoo.com' |
586 | PACKAGE_URL='http://firejail.wordpress.com' | 586 | PACKAGE_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 | ||
1264 | Usage: $0 [OPTION]... [VAR=VALUE]... | 1264 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1265 | 1265 | ||
@@ -1320,7 +1320,7 @@ fi | |||
1320 | 1320 | ||
1321 | if test -n "$ac_init_help"; then | 1321 | if 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 | |||
1424 | test -n "$ac_init_help" && exit $ac_status | 1424 | test -n "$ac_init_help" && exit $ac_status |
1425 | if $ac_init_version; then | 1425 | if $ac_init_version; then |
1426 | cat <<\_ACEOF | 1426 | cat <<\_ACEOF |
1427 | firejail configure 0.9.43 | 1427 | firejail configure 0.9.45 |
1428 | generated by GNU Autoconf 2.69 | 1428 | generated by GNU Autoconf 2.69 |
1429 | 1429 | ||
1430 | Copyright (C) 2012 Free Software Foundation, Inc. | 1430 | Copyright (C) 2012 Free Software Foundation, Inc. |
@@ -1726,7 +1726,7 @@ cat >config.log <<_ACEOF | |||
1726 | This file contains any messages produced by compilers while | 1726 | This file contains any messages produced by compilers while |
1727 | running configure, to aid debugging if configure makes a mistake. | 1727 | running configure, to aid debugging if configure makes a mistake. |
1728 | 1728 | ||
1729 | It was created by firejail $as_me 0.9.43, which was | 1729 | It was created by firejail $as_me 0.9.45, which was |
1730 | generated by GNU Autoconf 2.69. Invocation command line was | 1730 | generated 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" |
3760 | fi | 3760 | fi |
3761 | 3761 | ||
3762 | ac_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" | 3762 | ac_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 | ||
3764 | cat >confcache <<\_ACEOF | 3764 | cat >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. |
4305 | ac_log=" | 4305 | ac_log=" |
4306 | This file was extended by firejail $as_me 0.9.43, which was | 4306 | This file was extended by firejail $as_me 0.9.45, which was |
4307 | generated by GNU Autoconf 2.69. Invocation command line was | 4307 | generated 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 | |||
4357 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 | 4357 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
4358 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" | 4358 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
4359 | ac_cs_version="\\ | 4359 | ac_cs_version="\\ |
4360 | firejail config.status 0.9.43 | 4360 | firejail config.status 0.9.45 |
4361 | configured by $0, generated by GNU Autoconf 2.69, | 4361 | configured 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 @@ | |||
1 | AC_PREREQ([2.68]) | 1 | AC_PREREQ([2.68]) |
2 | AC_INIT(firejail, 0.9.43, netblue30@yahoo.com, , http://firejail.wordpress.com) | 2 | AC_INIT(firejail, 0.9.45, netblue30@yahoo.com, , http://firejail.wordpress.com) |
3 | AC_CONFIG_SRCDIR([src/firejail/main.c]) | 3 | AC_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" |
149 | fi | 149 | fi |
150 | 150 | ||
151 | AC_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) | 151 | AC_OUTPUT(Makefile src/lib/Makefile src/fnet/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile \ |
152 | src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile src/fseccomp/Makefile) | ||
152 | 153 | ||
153 | echo | 154 | echo |
154 | echo "Configuration options:" | 155 | echo "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 | |||
3 | noblacklist ~/.config/Wire | ||
4 | |||
5 | include /etc/firejail/disable-common.inc | ||
6 | include /etc/firejail/disable-programs.inc | ||
7 | include /etc/firejail/disable-devel.inc | ||
8 | include /etc/firejail/disable-passwdmgr.inc | ||
9 | |||
10 | caps.drop all | ||
11 | netfilter | ||
12 | nonewprivs | ||
13 | nogroups | ||
14 | noroot | ||
15 | protocol unix,inet,inet6,netlink | ||
16 | seccomp | ||
17 | shell none | ||
18 | |||
19 | private-tmp | ||
20 | private-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 | ||
9 | caps.drop all | 9 | caps.drop all |
10 | netfilter | 10 | netfilter |
11 | nonewprivs | ||
12 | nogroups | 11 | nogroups |
12 | nonewprivs | ||
13 | noroot | 13 | noroot |
14 | nosound | 14 | nosound |
15 | protocol unix,inet,inet6,netlink | 15 | protocol 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 | ||
9 | caps.drop all | 9 | caps.drop all |
10 | netfilter | 10 | netfilter |
11 | nonewprivs | ||
12 | nogroups | 11 | nogroups |
12 | nonewprivs | ||
13 | noroot | 13 | noroot |
14 | nosound | 14 | nosound |
15 | protocol unix,inet,inet6,netlink | 15 | protocol 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 | |||
7 | include /etc/firejail/disable-passwdmgr.inc | 7 | include /etc/firejail/disable-passwdmgr.inc |
8 | 8 | ||
9 | caps.drop all | 9 | caps.drop all |
10 | nonewprivs | ||
11 | nogroups | 10 | nogroups |
11 | nonewprivs | ||
12 | noroot | 12 | noroot |
13 | nosound | 13 | nosound |
14 | protocol unix | 14 | protocol 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 | ||
9 | caps.drop all | 9 | caps.drop all |
10 | netfilter | 10 | netfilter |
11 | nonewprivs | ||
12 | nogroups | 11 | nogroups |
12 | nonewprivs | ||
13 | noroot | 13 | noroot |
14 | protocol unix | 14 | protocol unix |
15 | seccomp | 15 | seccomp |
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 | ||
12 | caps.drop all | 12 | caps.drop all |
13 | netfilter | 13 | netfilter |
14 | nonewprivs | ||
15 | nogroups | 14 | nogroups |
15 | nonewprivs | ||
16 | noroot | 16 | noroot |
17 | nosound | 17 | nosound |
18 | protocol unix,inet,inet6 | 18 | protocol 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 |
2 | noblacklist /usr/bin/python2* | 2 | noblacklist /usr/bin/python2* |
3 | noblacklist /usr/lib/python3* | 3 | noblacklist /usr/lib/python3* |
4 | noblacklist ${HOME}/.config/cherrytree | ||
4 | include /etc/firejail/disable-common.inc | 5 | include /etc/firejail/disable-common.inc |
5 | include /etc/firejail/disable-programs.inc | 6 | include /etc/firejail/disable-programs.inc |
6 | include /etc/firejail/disable-devel.inc | 7 | include /etc/firejail/disable-devel.inc |
@@ -8,20 +9,10 @@ include /etc/firejail/disable-passwdmgr.inc | |||
8 | 9 | ||
9 | caps.drop all | 10 | caps.drop all |
10 | netfilter | 11 | netfilter |
12 | nogroups | ||
11 | nonewprivs | 13 | nonewprivs |
12 | noroot | 14 | noroot |
13 | nosound | 15 | nosound |
14 | seccomp | 16 | seccomp |
15 | protocol unix,inet,inet6,netlink | 17 | protocol unix,inet,inet6,netlink |
16 | tracelog | 18 | tracelog |
17 | |||
18 | include /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 | |||
25 | whitelist ~/.lastpass | 25 | whitelist ~/.lastpass |
26 | whitelist ~/.config/lastpass | 26 | whitelist ~/.config/lastpass |
27 | 27 | ||
28 | # specific to Arch | ||
29 | whitelist ~/.config/chromium-flags.conf | ||
30 | |||
28 | include /etc/firejail/whitelist-common.inc | 31 | include /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 |
2 | blacklist-nolog ${HOME}/.history | 2 | blacklist-nolog ${HOME}/.history |
3 | blacklist-nolog ${HOME}/.*_history | 3 | blacklist-nolog ${HOME}/.*_history |
4 | blacklist-nolog ${HOME}/.bash_history | ||
4 | blacklist ${HOME}/.local/share/systemd | 5 | blacklist ${HOME}/.local/share/systemd |
5 | blacklist-nolog ${HOME}/.adobe | 6 | blacklist-nolog ${HOME}/.adobe |
6 | blacklist-nolog ${HOME}/.macromedia | 7 | blacklist-nolog ${HOME}/.macromedia |
@@ -23,6 +24,7 @@ blacklist ${HOME}/.config/openbox/autostart | |||
23 | blacklist ${HOME}/.config/openbox/environment | 24 | blacklist ${HOME}/.config/openbox/environment |
24 | blacklist ${HOME}/.gnomerc | 25 | blacklist ${HOME}/.gnomerc |
25 | blacklist /etc/X11/Xsession.d/ | 26 | blacklist /etc/X11/Xsession.d/ |
27 | blacklist ${HOME}/.xpra | ||
26 | 28 | ||
27 | # VirtualBox | 29 | # VirtualBox |
28 | blacklist ${HOME}/.VirtualBox | 30 | blacklist ${HOME}/.VirtualBox |
@@ -96,9 +98,6 @@ read-only ${HOME}/.emacs.d | |||
96 | read-only ${HOME}/.nano | 98 | read-only ${HOME}/.nano |
97 | read-only ${HOME}/.tmux.conf | 99 | read-only ${HOME}/.tmux.conf |
98 | read-only ${HOME}/.iscreenrc | 100 | read-only ${HOME}/.iscreenrc |
99 | read-only ${HOME}/.muttrc | ||
100 | read-only ${HOME}/.mutt/muttrc | ||
101 | read-only ${HOME}/.msmtprc | ||
102 | read-only ${HOME}/.reportbugrc | 101 | read-only ${HOME}/.reportbugrc |
103 | read-only ${HOME}/.xmonad | 102 | read-only ${HOME}/.xmonad |
104 | read-only ${HOME}/.xscreensaver | 103 | read-only ${HOME}/.xscreensaver |
@@ -137,6 +136,11 @@ blacklist /etc/gshadow+ | |||
137 | blacklist /etc/ssh | 136 | blacklist /etc/ssh |
138 | blacklist /var/backup | 137 | blacklist /var/backup |
139 | 138 | ||
139 | # system directories | ||
140 | blacklist /sbin | ||
141 | blacklist /usr/sbin | ||
142 | blacklist /usr/local/sbin | ||
143 | |||
140 | # system management | 144 | # system management |
141 | blacklist ${PATH}/umount | 145 | blacklist ${PATH}/umount |
142 | blacklist ${PATH}/mount | 146 | blacklist ${PATH}/mount |
@@ -149,11 +153,22 @@ blacklist ${PATH}/xev | |||
149 | blacklist ${PATH}/strace | 153 | blacklist ${PATH}/strace |
150 | blacklist ${PATH}/nc | 154 | blacklist ${PATH}/nc |
151 | blacklist ${PATH}/ncat | 155 | blacklist ${PATH}/ncat |
152 | 156 | blacklist ${PATH}/gpasswd | |
153 | # system directories | 157 | blacklist ${PATH}/newgidmap |
154 | blacklist /sbin | 158 | blacklist ${PATH}/newgrp |
155 | blacklist /usr/sbin | 159 | blacklist ${PATH}/newuidmap |
156 | blacklist /usr/local/sbin | 160 | blacklist ${PATH}/pkexec |
161 | blacklist ${PATH}/sg | ||
162 | blacklist ${PATH}/rsh | ||
163 | blacklist ${PATH}/rlogin | ||
164 | blacklist ${PATH}/rcp | ||
165 | blacklist ${PATH}/crontab | ||
166 | blacklist ${PATH}/ksu | ||
167 | blacklist ${PATH}/chsh | ||
168 | blacklist ${PATH}/chfn | ||
169 | blacklist ${PATH}/chage | ||
170 | blacklist ${PATH}/expiry | ||
171 | blacklist ${PATH}/unix_chkpwd | ||
157 | 172 | ||
158 | # prevent lxterminal connecting to an existing lxterminal session | 173 | # prevent lxterminal connecting to an existing lxterminal session |
159 | blacklist /tmp/.lxterminal-socket* | 174 | blacklist /tmp/.lxterminal-socket* |
@@ -172,3 +187,7 @@ blacklist ${PATH}/roxterm-config | |||
172 | blacklist ${PATH}/terminix | 187 | blacklist ${PATH}/terminix |
173 | blacklist ${PATH}/urxvtc | 188 | blacklist ${PATH}/urxvtc |
174 | blacklist ${PATH}/urxvtcd | 189 | blacklist ${PATH}/urxvtcd |
190 | |||
191 | # kernel files | ||
192 | blacklist /vmlinuz* | ||
193 | blacklist /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 |
21 | blacklist /usr/bin/clang* | 21 | blacklist /usr/bin/clang* |
22 | blacklist /usr/bin/llvm* | 22 | blacklist /usr/bin/llvm* |
23 | blacklist /usb/bin/lldb* | 23 | blacklist /usr/bin/lldb* |
24 | blacklist /usr/lib/llvm* | 24 | blacklist /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 | |||
7 | blacklist ${HOME}/.Mathematica | 7 | blacklist ${HOME}/.Mathematica |
8 | blacklist ${HOME}/.Wolfram Research | 8 | blacklist ${HOME}/.Wolfram Research |
9 | blacklist ${HOME}/.stellarium | 9 | blacklist ${HOME}/.stellarium |
10 | blacklist ${HOME}/.sword | ||
11 | blacklist ${HOME}/.xiphos | ||
10 | blacklist ${HOME}/.config/Atom | 12 | blacklist ${HOME}/.config/Atom |
11 | blacklist ${HOME}/.config/gthumb | 13 | blacklist ${HOME}/.config/gthumb |
12 | blacklist ${HOME}/.config/mupen64plus | 14 | blacklist ${HOME}/.config/mupen64plus |
@@ -33,6 +35,13 @@ blacklist ${HOME}/.synfig | |||
33 | blacklist ${HOME}/.inkscape | 35 | blacklist ${HOME}/.inkscape |
34 | blacklist ${HOME}/.gimp* | 36 | blacklist ${HOME}/.gimp* |
35 | blacklist ${HOME}/.config/zathura | 37 | blacklist ${HOME}/.config/zathura |
38 | blacklist ${HOME}/.config/cherrytree | ||
39 | blacklist ${HOME}/.xpdfrc | ||
40 | blacklist ${HOME}/.openshot | ||
41 | blacklist ${HOME}/.openshot_qt | ||
42 | blacklist ${HOME}/.flowblade | ||
43 | blacklist ${HOME}/.config/flowblade | ||
44 | blacklist ${HOME}/.config/eog | ||
36 | 45 | ||
37 | 46 | ||
38 | # Media players | 47 | # Media players |
@@ -70,8 +79,12 @@ blacklist ${HOME}/.8pecxstudios | |||
70 | blacklist ${HOME}/.config/brave | 79 | blacklist ${HOME}/.config/brave |
71 | blacklist ${HOME}/.config/inox | 80 | blacklist ${HOME}/.config/inox |
72 | blacklist ${HOME}/.muttrc | 81 | blacklist ${HOME}/.muttrc |
82 | blacklist ${HOME}/.mutt | ||
73 | blacklist ${HOME}/.mutt/muttrc | 83 | blacklist ${HOME}/.mutt/muttrc |
74 | blacklist ${HOME}/.msmtprc | 84 | blacklist ${HOME}/.msmtprc |
85 | blacklist ${HOME}/.config/evolution | ||
86 | blacklist ${HOME}/.local/share/evolution | ||
87 | blacklist ${HOME}/.cache/evolution | ||
75 | 88 | ||
76 | # Instant Messaging | 89 | # Instant Messaging |
77 | blacklist ${HOME}/.config/hexchat | 90 | blacklist ${HOME}/.config/hexchat |
@@ -93,6 +106,7 @@ blacklist ${HOME}/.config/Slack | |||
93 | blacklist ${HOME}/.cache/gajim | 106 | blacklist ${HOME}/.cache/gajim |
94 | blacklist ${HOME}/.local/share/gajim | 107 | blacklist ${HOME}/.local/share/gajim |
95 | blacklist ${HOME}/.config/gajim | 108 | blacklist ${HOME}/.config/gajim |
109 | blacklist ${HOME}/.config/Wire | ||
96 | 110 | ||
97 | # Games | 111 | # Games |
98 | blacklist ${HOME}/.hedgewars | 112 | blacklist ${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 | ||
2 | include /etc/firejail/disable-common.inc | ||
3 | include /etc/firejail/disable-programs.inc | ||
4 | include /etc/firejail/disable-devel.inc | ||
5 | include /etc/firejail/disable-passwdmgr.inc | ||
6 | |||
7 | caps.drop all | ||
8 | seccomp | ||
9 | protocol unix | ||
10 | netfilter | ||
11 | net none | ||
12 | nonewprivs | ||
13 | noroot | ||
14 | nogroups | ||
15 | nosound | ||
16 | shell none | ||
17 | x11 xorg | ||
18 | |||
19 | private-bin display | ||
20 | private-tmp | ||
21 | private-dev | ||
22 | private-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 | |||
3 | noblacklist ~/.config/eog | ||
4 | |||
5 | include /etc/firejail/disable-common.inc | ||
6 | include /etc/firejail/disable-programs.inc | ||
7 | include /etc/firejail/disable-devel.inc | ||
8 | include /etc/firejail/disable-passwdmgr.inc | ||
9 | |||
10 | caps.drop all | ||
11 | netfilter | ||
12 | nogroups | ||
13 | nonewprivs | ||
14 | noroot | ||
15 | protocol unix | ||
16 | seccomp | ||
17 | shell none | ||
18 | |||
19 | private-bin eog | ||
20 | private-dev | ||
21 | private-etc fonts | ||
22 | private-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 | |||
15 | tracelog | 15 | tracelog |
16 | 16 | ||
17 | private-bin evince,evince-previewer,evince-thumbnailer | 17 | private-bin evince,evince-previewer,evince-thumbnailer |
18 | whitelist /tmp/.X11-unix | ||
19 | private-dev | 18 | private-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 | |||
3 | noblacklist ~/.config/evolution | ||
4 | noblacklist ~/.local/share/evolution | ||
5 | noblacklist ~/.cache/evolution | ||
6 | noblacklist ~/.pki | ||
7 | noblacklist ~/.pki/nssdb | ||
8 | noblacklist ~/.gnupg | ||
9 | |||
10 | include /etc/firejail/disable-common.inc | ||
11 | include /etc/firejail/disable-programs.inc | ||
12 | include /etc/firejail/disable-devel.inc | ||
13 | include /etc/firejail/disable-passwdmgr.inc | ||
14 | |||
15 | caps.drop all | ||
16 | netfilter | ||
17 | nogroups | ||
18 | nonewprivs | ||
19 | noroot | ||
20 | protocol unix,inet,inet6 | ||
21 | seccomp | ||
22 | shell none | ||
23 | |||
24 | private-dev | ||
25 | private-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 | |||
5 | include /etc/firejail/disable-passwdmgr.inc | 5 | include /etc/firejail/disable-passwdmgr.inc |
6 | 6 | ||
7 | caps.drop all | 7 | caps.drop all |
8 | seccomp | ||
9 | protocol unix | ||
10 | netfilter | 8 | netfilter |
11 | net none | 9 | net none |
10 | nogroups | ||
12 | nonewprivs | 11 | nonewprivs |
13 | noroot | 12 | noroot |
14 | nogroups | ||
15 | nosound | 13 | nosound |
14 | protocol unix | ||
15 | seccomp | ||
16 | shell none | 16 | shell none |
17 | 17 | ||
18 | private-bin feh | 18 | private-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 |
2 | quiet | ||
3 | ignore noroot | 2 | ignore noroot |
4 | include /etc/firejail/default.profile | 3 | include /etc/firejail/default.profile |
5 | 4 | ||
6 | tracelog | 5 | blacklist /tmp/.X11-unix |
6 | |||
7 | hostname file | ||
7 | net none | 8 | net none |
9 | no3d | ||
10 | nosound | ||
11 | quiet | ||
8 | shell none | 12 | shell none |
13 | tracelog | ||
14 | |||
15 | private-dev | ||
9 | private-bin file | 16 | private-bin file |
10 | private-etc magic.mgc,magic,localtime | 17 | private-etc magic.mgc,magic,localtime |
11 | hostname file | ||
12 | private-dev | ||
13 | nosound | ||
14 | no3d | ||
15 | blacklist /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 | |||
13 | nosound | 13 | nosound |
14 | protocol unix,inet,inet6 | 14 | protocol unix,inet,inet6 |
15 | seccomp | 15 | seccomp |
16 | |||
17 | shell none | 16 | shell none |
17 | |||
18 | private-bin filezilla,uname,sh,python,lsb_release,fzputtygen,fzsftp | 18 | private-bin filezilla,uname,sh,python,lsb_release,fzputtygen,fzsftp |
19 | whitelist /tmp/.X11-unix | ||
20 | private-dev | 19 | private-dev |
21 | nosound | ||
22 | 20 | ||
21 | whitelist /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 | ||
2 | noblacklist ${HOME}/.flowblade | ||
3 | noblacklist ${HOME}/.config/flowblade | ||
4 | include /etc/firejail/disable-common.inc | ||
5 | include /etc/firejail/disable-programs.inc | ||
6 | include /etc/firejail/disable-passwdmgr.inc | ||
7 | |||
8 | caps.drop all | ||
9 | netfilter | ||
10 | nonewprivs | ||
11 | noroot | ||
12 | protocol unix,inet,inet6,netlink | ||
13 | seccomp | ||
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 | |||
6 | include /etc/firejail/disable-devel.inc | 6 | include /etc/firejail/disable-devel.inc |
7 | 7 | ||
8 | caps.drop all | 8 | caps.drop all |
9 | seccomp | ||
10 | protocol unix,inet,inet6,netlink | ||
11 | netfilter | 9 | netfilter |
12 | #tracelog | ||
13 | nonewprivs | 10 | nonewprivs |
14 | noroot | 11 | noroot |
12 | protocol unix,inet,inet6,netlink | ||
13 | seccomp | ||
14 | #tracelog | ||
15 | 15 | ||
16 | whitelist ${DOWNLOADS} | 16 | whitelist ${DOWNLOADS} |
17 | mkdir ~/.config/Franz | 17 | mkdir ~/.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 | ||
23 | caps.drop all | 23 | caps.drop all |
24 | netfilter | 24 | netfilter |
25 | nonewprivs | ||
26 | nogroups | 25 | nogroups |
26 | nonewprivs | ||
27 | noroot | 27 | noroot |
28 | protocol unix,inet,inet6 | 28 | protocol unix,inet,inet6 |
29 | seccomp | 29 | seccomp |
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 | ||
7 | caps.drop all | 7 | caps.drop all |
8 | netfilter | 8 | netfilter |
9 | nogroups | ||
9 | nonewprivs | 10 | nonewprivs |
10 | noroot | 11 | noroot |
12 | nosound | ||
11 | protocol unix | 13 | protocol unix |
12 | seccomp | 14 | seccomp |
13 | private-dev | 15 | |
14 | private-tmp | ||
15 | noexec ${HOME} | 16 | noexec ${HOME} |
16 | noexec /tmp | 17 | noexec /tmp |
17 | nogroups | 18 | |
18 | nosound | 19 | private-dev |
20 | private-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 | |||
12 | include /etc/firejail/disable-programs.inc | 12 | include /etc/firejail/disable-programs.inc |
13 | include /etc/firejail/disable-passwdmgr.inc | 13 | include /etc/firejail/disable-passwdmgr.inc |
14 | 14 | ||
15 | quiet | ||
16 | 15 | ||
17 | caps.drop all | 16 | caps.drop all |
18 | netfilter | 17 | netfilter |
18 | nogroups | ||
19 | nonewprivs | 19 | nonewprivs |
20 | noroot | 20 | noroot |
21 | nogroups | ||
22 | nosound | 21 | nosound |
23 | protocol unix,inet,inet6 | 22 | protocol unix,inet,inet6 |
23 | quiet | ||
24 | seccomp | 24 | seccomp |
25 | shell none | 25 | shell 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 | |||
6 | include /etc/firejail/disable-programs.inc | 6 | include /etc/firejail/disable-programs.inc |
7 | 7 | ||
8 | # Whitelist | 8 | # Whitelist |
9 | mkdir ~/.config/Gpredict | ||
10 | whitelist ~/.config/Gpredict | 9 | whitelist ~/.config/Gpredict |
11 | 10 | ||
12 | caps.drop all | 11 | caps.drop all |
13 | netfilter | 12 | netfilter |
14 | nonewprivs | ||
15 | nogroups | 13 | nogroups |
14 | nonewprivs | ||
16 | noroot | 15 | noroot |
17 | nosound | 16 | nosound |
18 | protocol unix,inet,inet6 | 17 | protocol unix,inet,inet6 |
@@ -21,5 +20,6 @@ shell none | |||
21 | tracelog | 20 | tracelog |
22 | 21 | ||
23 | private-bin gpredict | 22 | private-bin gpredict |
23 | private-etc fonts,resolv.conf | ||
24 | private-dev | 24 | private-dev |
25 | private-tmp | 25 | private-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 | |||
7 | include /etc/firejail/disable-passwdmgr.inc | 7 | include /etc/firejail/disable-passwdmgr.inc |
8 | 8 | ||
9 | caps.drop all | 9 | caps.drop all |
10 | nogroups | ||
10 | nonewprivs | 11 | nonewprivs |
11 | noroot | 12 | noroot |
12 | nogroups | ||
13 | private-dev | ||
14 | protocol unix | 13 | protocol unix |
15 | seccomp | 14 | seccomp |
16 | nosound | 15 | nosound |
17 | 16 | ||
17 | private-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 |
2 | quiet | ||
3 | ignore noroot | 2 | ignore noroot |
4 | include /etc/firejail/default.profile | 3 | include /etc/firejail/default.profile |
5 | tracelog | 4 | |
6 | net none | ||
7 | shell none | ||
8 | blacklist /tmp/.X11-unix | 5 | blacklist /tmp/.X11-unix |
9 | private-dev | 6 | |
10 | nosound | 7 | net none |
11 | no3d | 8 | no3d |
9 | nosound | ||
10 | quiet | ||
11 | shell none | ||
12 | tracelog | ||
12 | 13 | ||
14 | private-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 | ||
7 | caps.drop all | 7 | caps.drop all |
8 | netfilter | 8 | netfilter |
9 | nogroups | ||
9 | nonewprivs | 10 | nonewprivs |
10 | noroot | 11 | noroot |
12 | nosound | ||
11 | protocol unix | 13 | protocol unix |
12 | seccomp | 14 | seccomp |
13 | private-dev | 15 | |
14 | private-tmp | ||
15 | noexec ${HOME} | 16 | noexec ${HOME} |
16 | noexec /tmp | 17 | noexec /tmp |
17 | nogroups | 18 | |
18 | nosound | 19 | private-dev |
20 | private-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 | |||
6 | include /etc/firejail/disable-programs.inc | 6 | include /etc/firejail/disable-programs.inc |
7 | 7 | ||
8 | caps.drop all | 8 | caps.drop all |
9 | nonewprivs | ||
10 | nogroups | 9 | nogroups |
10 | nonewprivs | ||
11 | noroot | 11 | noroot |
12 | protocol unix,inet,inet6 | 12 | protocol unix,inet,inet6 |
13 | seccomp | 13 | seccomp |
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 | |||
13 | nonewprivs | 13 | nonewprivs |
14 | noroot | 14 | noroot |
15 | nosound | 15 | nosound |
16 | protocol unix | 16 | protocol unix,inet,inet6 |
17 | seccomp | 17 | seccomp |
18 | netfilter | 18 | netfilter |
19 | shell none | 19 | shell 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 | ||
9 | caps.drop all | 9 | caps.drop all |
10 | netfilter | 10 | netfilter |
11 | nonewprivs | ||
12 | nogroups | 11 | nogroups |
12 | nonewprivs | ||
13 | noroot | 13 | noroot |
14 | protocol unix,inet,inet6,netlink | 14 | protocol unix,inet,inet6,netlink |
15 | seccomp | 15 | seccomp |
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 @@ | |||
2 | quiet | 2 | quiet |
3 | ignore noroot | 3 | ignore noroot |
4 | include /etc/firejail/default.profile | 4 | include /etc/firejail/default.profile |
5 | tracelog | 5 | |
6 | net none | 6 | net none |
7 | nosound | ||
7 | shell none | 8 | shell none |
9 | tracelog | ||
10 | |||
8 | private-dev | 11 | private-dev |
9 | nosound | ||
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 |
2 | noblacklist ~/.config/libreoffice | 2 | noblacklist ~/.config/libreoffice |
3 | noblacklist /usr/local/sbin | ||
3 | include /etc/firejail/disable-common.inc | 4 | include /etc/firejail/disable-common.inc |
4 | include /etc/firejail/disable-programs.inc | 5 | include /etc/firejail/disable-programs.inc |
5 | include /etc/firejail/disable-devel.inc | 6 | include /etc/firejail/disable-devel.inc |
@@ -10,9 +11,9 @@ netfilter | |||
10 | nogroups | 11 | nogroups |
11 | nonewprivs | 12 | nonewprivs |
12 | noroot | 13 | noroot |
13 | protocol unix,inet,inet6,netlink | 14 | protocol unix,inet,inet6 |
14 | seccomp | 15 | seccomp |
15 | tracelog | 16 | tracelog |
16 | 17 | ||
17 | private-dev | 18 | private-dev |
18 | whitelist /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 | |||
5 | include /etc/firejail/disable-passwdmgr.inc | 5 | include /etc/firejail/disable-passwdmgr.inc |
6 | 6 | ||
7 | caps.drop all | 7 | caps.drop all |
8 | ipc-namespace | ||
8 | netfilter | 9 | netfilter |
9 | protocol unix | 10 | nogroups |
10 | nonewprivs | 11 | nonewprivs |
11 | noroot | 12 | noroot |
13 | nosound | ||
14 | protocol unix | ||
12 | seccomp | 15 | seccomp |
13 | shell none | 16 | shell none |
14 | tracelog | 17 | tracelog |
15 | private-tmp | 18 | |
16 | private-dev | ||
17 | noexec ${HOME} | 19 | noexec ${HOME} |
18 | noexec /tmp | 20 | noexec /tmp |
19 | nogroups | 21 | |
20 | nosound | 22 | private-tmp |
21 | ipc-namespace | 23 | private-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 | ||
2 | noblacklist ${HOME}/.config/Mumble | ||
3 | noblacklist ${HOME}/.local/share/data/Mumble | ||
4 | include /etc/firejail/disable-common.inc | ||
5 | include /etc/firejail/disable-programs.inc | ||
6 | include /etc/firejail/disable-devel.inc | ||
7 | include /etc/firejail/disable-passwdmgr.inc | ||
8 | |||
9 | mkdir ${HOME}/.config/Mumble | ||
10 | mkdir ${HOME}/.local/share/data/Mumble | ||
11 | whitelist ${HOME}/.config/Mumble | ||
12 | whitelist ${HOME}/.local/share/data/Mumble | ||
13 | include /etc/firejail/whitelist-common.inc | ||
14 | |||
15 | caps.drop all | ||
16 | netfilter | ||
17 | nonewprivs | ||
18 | nogroups | ||
19 | noroot | ||
20 | protocol unix,inet,inet6 | ||
21 | seccomp | ||
22 | shell none | ||
23 | tracelog | ||
24 | |||
25 | private-bin mumble | ||
26 | private-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 | ||
3 | noblacklist ~/.muttrc | 3 | noblacklist ~/.muttrc |
4 | noblacklist ~/.mutt | 4 | noblacklist ~/.mutt |
5 | noblacklist ~/.mutt/muttrc | ||
5 | noblacklist ~/.mailcap | 6 | noblacklist ~/.mailcap |
6 | noblacklist ~/.gnupg | 7 | noblacklist ~/.gnupg |
7 | noblacklist ~/.mail | 8 | noblacklist ~/.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 | |||
9 | include /etc/firejail/disable-passwdmgr.inc | 9 | include /etc/firejail/disable-passwdmgr.inc |
10 | 10 | ||
11 | caps.drop all | 11 | caps.drop all |
12 | nonewprivs | ||
13 | nogroups | 12 | nogroups |
13 | nonewprivs | ||
14 | noroot | 14 | noroot |
15 | private-dev | ||
16 | protocol unix | 15 | protocol unix |
17 | seccomp | 16 | seccomp |
18 | nosound | 17 | nosound |
19 | 18 | ||
19 | private-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 | ||
2 | noblacklist ${HOME}/.openshot | ||
3 | noblacklist ${HOME}/.openshot_qt | ||
4 | include /etc/firejail/disable-common.inc | ||
5 | include /etc/firejail/disable-programs.inc | ||
6 | include /etc/firejail/disable-passwdmgr.inc | ||
7 | |||
8 | caps.drop all | ||
9 | netfilter | ||
10 | nonewprivs | ||
11 | noroot | ||
12 | protocol unix,inet,inet6,netlink | ||
13 | seccomp | ||
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 | ||
9 | caps.drop all | 9 | caps.drop all |
10 | netfilter | 10 | netfilter |
11 | nonewprivs | ||
12 | nogroups | 11 | nogroups |
12 | nonewprivs | ||
13 | noroot | 13 | noroot |
14 | protocol unix,inet,inet6 | 14 | protocol unix,inet,inet6 |
15 | seccomp | 15 | seccomp |
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 | |||
8 | include /etc/firejail/disable-passwdmgr.inc | 8 | include /etc/firejail/disable-passwdmgr.inc |
9 | 9 | ||
10 | caps.drop all | 10 | caps.drop all |
11 | nonewprivs | ||
12 | nogroups | 11 | nogroups |
12 | nonewprivs | ||
13 | noroot | 13 | noroot |
14 | nosound | 14 | nosound |
15 | protocol unix | 15 | protocol unix |
@@ -20,4 +20,3 @@ tracelog | |||
20 | private-bin pix | 20 | private-bin pix |
21 | whitelist /tmp/.X11-unix | 21 | whitelist /tmp/.X11-unix |
22 | private-dev | 22 | private-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+ | |||
14 | mkdir ~/.cache/psi+ | 14 | mkdir ~/.cache/psi+ |
15 | whitelist ~/.cache/psi+ | 15 | whitelist ~/.cache/psi+ |
16 | 16 | ||
17 | include /etc/firejail/whitelist-common.inc | ||
18 | |||
19 | caps.drop all | 17 | caps.drop all |
20 | netfilter | 18 | netfilter |
21 | noroot | 19 | noroot |
22 | protocol unix,inet,inet6 | 20 | protocol unix,inet,inet6 |
23 | seccomp | 21 | seccomp |
22 | |||
23 | include /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 |
18 | whitelist /tmp/.X11-unix | ||
19 | private-dev | 18 | private-dev |
20 | nosound | 19 | |
20 | whitelist /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 | |||
18 | tracelog | 18 | tracelog |
19 | 19 | ||
20 | private-bin qpdfview | 20 | private-bin qpdfview |
21 | private-tmp | ||
22 | private-dev | 21 | private-dev |
22 | private-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 | ||
12 | caps.drop all | 12 | caps.drop all |
13 | netfilter | 13 | netfilter |
14 | nonewprivs | ||
15 | nogroups | 14 | nogroups |
15 | nonewprivs | ||
16 | noroot | 16 | noroot |
17 | protocol unix,inet,inet6 | 17 | protocol unix,inet,inet6 |
18 | seccomp | 18 | seccomp |
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 | ||
15 | caps.drop all | 15 | caps.drop all |
16 | netfilter | 16 | netfilter |
17 | nonewprivs | ||
18 | nogroups | 17 | nogroups |
18 | nonewprivs | ||
19 | noroot | 19 | noroot |
20 | private-bin quiterss | ||
21 | private-dev | ||
22 | nosound | 20 | nosound |
23 | #private-etc X11,ssl | ||
24 | protocol unix,inet,inet6 | 21 | protocol unix,inet,inet6 |
25 | seccomp | 22 | seccomp |
26 | shell none | 23 | shell none |
27 | tracelog | 24 | tracelog |
28 | 25 | ||
26 | private-bin quiterss | ||
27 | private-dev | ||
28 | #private-etc X11,ssl | ||
29 | |||
29 | include /etc/firejail/whitelist-common.inc | 30 | include /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 | |||
12 | caps.drop all | 12 | caps.drop all |
13 | netfilter | 13 | netfilter |
14 | net none | 14 | net none |
15 | nogroups | ||
15 | nonewprivs | 16 | nonewprivs |
16 | noroot | 17 | noroot |
17 | nogroups | ||
18 | protocol unix | 18 | protocol unix |
19 | seccomp | 19 | seccomp |
20 | nosound | 20 | nosound |
21 | 21 | ||
22 | private-tmp | 22 | private-tmp |
23 | private-dev | 23 | private-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 | |||
5 | include /etc/firejail/disable-passwdmgr.inc | 5 | include /etc/firejail/disable-passwdmgr.inc |
6 | 6 | ||
7 | caps.drop all | 7 | caps.drop all |
8 | nogroups | ||
9 | netfilter | 8 | netfilter |
9 | nogroups | ||
10 | nonewprivs | 10 | nonewprivs |
11 | noroot | 11 | noroot |
12 | protocol unix,inet,inet6 | 12 | protocol 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 | |||
16 | private-bin rtorrent | 16 | private-bin rtorrent |
17 | whitelist /tmp/.X11-unix | 17 | whitelist /tmp/.X11-unix |
18 | private-dev | 18 | private-dev |
19 | nosound | ||
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 | |||
6 | include /etc/firejail/disable-programs.inc | 6 | include /etc/firejail/disable-programs.inc |
7 | include /etc/firejail/disable-passwdmgr.inc | 7 | include /etc/firejail/disable-passwdmgr.inc |
8 | 8 | ||
9 | private | ||
10 | private-dev | ||
11 | nosound | ||
12 | no3d | ||
13 | private-tmp | ||
14 | blacklist /tmp/.X11-unix | 9 | blacklist /tmp/.X11-unix |
10 | |||
11 | no3d | ||
12 | nosound | ||
15 | seccomp | 13 | seccomp |
16 | 14 | ||
15 | private | ||
16 | private-dev | ||
17 | private-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 | ||
1 | noblacklist ${HOME}/.config/Slack | 2 | noblacklist ${HOME}/.config/Slack |
2 | noblacklist ${HOME}/Downloads | 3 | noblacklist ${HOME}/Downloads |
3 | 4 | ||
@@ -6,25 +7,25 @@ include /etc/firejail/disable-programs.inc | |||
6 | include /etc/firejail/disable-devel.inc | 7 | include /etc/firejail/disable-devel.inc |
7 | include /etc/firejail/disable-passwdmgr.inc | 8 | include /etc/firejail/disable-passwdmgr.inc |
8 | 9 | ||
9 | mkdir ${HOME}/.config | ||
10 | mkdir ${HOME}/.config/Slack | ||
11 | whitelist ${HOME}/.config/Slack | ||
12 | whitelist ${HOME}/Downloads | ||
13 | |||
14 | protocol unix,inet,inet6,netlink | ||
15 | private-dev | ||
16 | private-tmp | ||
17 | private-etc fonts,resolv.conf,ld.so.conf,ld.so.cache,localtime | ||
18 | name slack | ||
19 | blacklist /var | 10 | blacklist /var |
20 | 11 | ||
21 | include /etc/firejail/whitelist-common.inc | ||
22 | |||
23 | caps.drop all | 12 | caps.drop all |
24 | seccomp | 13 | name slack |
25 | netfilter | 14 | netfilter |
26 | nonewprivs | ||
27 | nogroups | 15 | nogroups |
16 | nonewprivs | ||
28 | noroot | 17 | noroot |
18 | protocol unix,inet,inet6,netlink | ||
19 | seccomp | ||
29 | shell none | 20 | shell none |
21 | |||
30 | private-bin slack | 22 | private-bin slack |
23 | private-dev | ||
24 | private-etc fonts,resolv.conf,ld.so.conf,ld.so.cache,localtime | ||
25 | private-tmp | ||
26 | |||
27 | mkdir ${HOME}/.config | ||
28 | mkdir ${HOME}/.config/Slack | ||
29 | whitelist ${HOME}/.config/Slack | ||
30 | whitelist ${HOME}/Downloads | ||
31 | include /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 | |||
7 | include /etc/firejail/disable-devel.inc | 7 | include /etc/firejail/disable-devel.inc |
8 | include /etc/firejail/disable-passwdmgr.inc | 8 | include /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 | ||
13 | mkdir ${HOME}/.config/spotify | 11 | mkdir ${HOME}/.config/spotify |
14 | whitelist ${HOME}/.config/spotify | 12 | whitelist ${HOME}/.config/spotify |
15 | mkdir ${HOME}/.local/share/spotify | 13 | mkdir ${HOME}/.local/share/spotify |
16 | whitelist ${HOME}/.local/share/spotify | 14 | whitelist ${HOME}/.local/share/spotify |
17 | mkdir ${HOME}/.cache/spotify | 15 | mkdir ${HOME}/.cache/spotify |
18 | whitelist ${HOME}/.cache/spotify | 16 | whitelist ${HOME}/.cache/spotify |
19 | include /etc/firejail/whitelist-common.inc | ||
20 | 17 | ||
21 | caps.drop all | 18 | caps.drop all |
22 | netfilter | 19 | netfilter |
@@ -27,5 +24,20 @@ protocol unix,inet,inet6,netlink | |||
27 | seccomp | 24 | seccomp |
28 | shell none | 25 | shell none |
29 | 26 | ||
30 | #private-bin spotify | 27 | private-bin spotify |
28 | private-etc fonts,machine-id,pulse,resolv.conf | ||
31 | private-dev | 29 | private-dev |
30 | private-tmp | ||
31 | |||
32 | blacklist ${HOME}/.Xauthority | ||
33 | blacklist ${HOME}/.bashrc | ||
34 | blacklist /boot | ||
35 | blacklist /lost+found | ||
36 | blacklist /media | ||
37 | blacklist /mnt | ||
38 | blacklist /opt | ||
39 | blacklist /root | ||
40 | blacklist /sbin | ||
41 | blacklist /srv | ||
42 | blacklist /sys | ||
43 | blacklist /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 | ||
2 | include /etc/firejail/disable-common.inc | ||
3 | include /etc/firejail/disable-devel.inc | ||
4 | include /etc/firejail/disable-passwdmgr.inc | ||
5 | include /etc/firejail/disable-programs.inc | ||
6 | |||
7 | caps.drop all | ||
8 | netfilter | ||
9 | nogroups | ||
10 | nonewprivs | ||
11 | noroot | ||
12 | protocol unix,inet,inet6 | ||
13 | seccomp | ||
14 | shell none | ||
15 | tracelog | ||
16 | |||
17 | private-bin bash,grep,sed,tail,env,gpg,id,readlink,dirname,test,mkdir,ln,sed,cp,rm,getconf | ||
18 | private-etc fonts | ||
19 | private-dev | ||
20 | private-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 |
2 | quiet | ||
3 | ignore noroot | 2 | ignore noroot |
4 | include /etc/firejail/default.profile | 3 | include /etc/firejail/default.profile |
5 | tracelog | 4 | |
6 | net none | 5 | net none |
7 | shell none | ||
8 | private-dev | ||
9 | nosound | 6 | nosound |
7 | quiet | ||
8 | shell none | ||
9 | tracelog | ||
10 | 10 | ||
11 | private-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 | |||
11 | noroot | 11 | noroot |
12 | protocol unix | 12 | protocol unix |
13 | seccomp | 13 | seccomp |
14 | private-dev | 14 | |
15 | private-tmp | ||
16 | noexec ${HOME} | 15 | noexec ${HOME} |
17 | noexec /tmp | 16 | noexec /tmp |
17 | |||
18 | private-dev | ||
19 | private-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 |
2 | quiet | ||
3 | ignore noroot | 2 | ignore noroot |
4 | include /etc/firejail/default.profile | 3 | include /etc/firejail/default.profile |
5 | 4 | ||
6 | tracelog | 5 | blacklist /tmp/.X11-unix |
6 | |||
7 | hostname tar | ||
7 | net none | 8 | net none |
9 | no3d | ||
10 | nosound | ||
11 | quiet | ||
8 | shell none | 12 | shell none |
13 | tracelog | ||
9 | 14 | ||
10 | # support compressed archives | 15 | # support compressed archives |
11 | private-bin sh,tar,gtar,compress,gzip,lzma,xz,bzip2,lbzip2,lzip,lzop | 16 | private-bin sh,tar,gtar,compress,gzip,lzma,xz,bzip2,lbzip2,lzip,lzop |
12 | private-dev | 17 | private-dev |
13 | nosound | ||
14 | no3d | ||
15 | private-etc passwd,group,localtime | 18 | private-etc passwd,group,localtime |
16 | hostname tar | ||
17 | blacklist /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 | |||
10 | noroot | 10 | noroot |
11 | protocol unix,inet,inet6 | 11 | protocol unix,inet,inet6 |
12 | seccomp | 12 | seccomp |
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 | |||
18 | tracelog | 18 | tracelog |
19 | 19 | ||
20 | private-bin transmission-gtk | 20 | private-bin transmission-gtk |
21 | whitelist /tmp/.X11-unix | ||
22 | private-dev | 21 | private-dev |
23 | 22 | ||
23 | whitelist /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 | |||
14 | nosound | 14 | nosound |
15 | protocol unix,inet,inet6 | 15 | protocol unix,inet,inet6 |
16 | seccomp | 16 | seccomp |
17 | shell none | ||
17 | tracelog | 18 | tracelog |
18 | 19 | ||
19 | shell none | ||
20 | private-bin transmission-qt | 20 | private-bin transmission-qt |
21 | whitelist /tmp/.X11-unix | ||
22 | private-dev | 21 | private-dev |
22 | |||
23 | whitelist /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 | |||
9 | netfilter | 9 | netfilter |
10 | nonewprivs | 10 | nonewprivs |
11 | noroot | 11 | noroot |
12 | nosound | ||
12 | protocol unix,inet,inet6 | 13 | protocol unix,inet,inet6 |
13 | seccomp | 14 | seccomp |
15 | shell none | ||
14 | 16 | ||
17 | private-bin uget-gtk | ||
18 | private-dev | ||
19 | |||
20 | whitelist /tmp/.X11-unix | ||
15 | whitelist ${DOWNLOADS} | 21 | whitelist ${DOWNLOADS} |
16 | mkdir ~/.config/uGet | 22 | mkdir ~/.config/uGet |
17 | whitelist ~/.config/uGet | 23 | whitelist ~/.config/uGet |
18 | include /etc/firejail/whitelist-common.inc | 24 | include /etc/firejail/whitelist-common.inc |
19 | |||
20 | shell none | ||
21 | private-bin uget-gtk | ||
22 | whitelist /tmp/.X11-unix | ||
23 | private-dev | ||
24 | nosound | ||
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 |
2 | quiet | ||
3 | ignore noroot | 2 | ignore noroot |
4 | include /etc/firejail/default.profile | 3 | include /etc/firejail/default.profile |
5 | 4 | ||
6 | tracelog | 5 | blacklist /tmp/.X11-unix |
6 | |||
7 | hostname unrar | ||
7 | net none | 8 | net none |
9 | no3d | ||
10 | nosound | ||
11 | quiet | ||
8 | shell none | 12 | shell none |
13 | tracelog | ||
14 | |||
9 | private-bin unrar | 15 | private-bin unrar |
10 | private-dev | 16 | private-dev |
11 | nosound | ||
12 | no3d | ||
13 | private-etc passwd,group,localtime | 17 | private-etc passwd,group,localtime |
14 | hostname unrar | ||
15 | private-tmp | 18 | private-tmp |
16 | blacklist /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 |
2 | quiet | ||
3 | ignore noroot | 2 | ignore noroot |
4 | include /etc/firejail/default.profile | 3 | include /etc/firejail/default.profile |
4 | blacklist /tmp/.X11-unix | ||
5 | 5 | ||
6 | tracelog | 6 | hostname unzip |
7 | net none | 7 | net none |
8 | no3d | ||
9 | nosound | ||
10 | quiet | ||
8 | shell none | 11 | shell none |
12 | tracelog | ||
13 | |||
9 | private-bin unzip | 14 | private-bin unzip |
10 | private-etc passwd,group,localtime | ||
11 | hostname unzip | ||
12 | private-dev | 15 | private-dev |
13 | nosound | 16 | private-etc passwd,group,localtime |
14 | no3d | ||
15 | blacklist /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 |
2 | quiet | ||
3 | ignore noroot | 2 | ignore noroot |
4 | include /etc/firejail/default.profile | 3 | include /etc/firejail/default.profile |
5 | 4 | ||
6 | tracelog | 5 | blacklist /etc |
6 | |||
7 | hostname uudeview | ||
7 | net none | 8 | net none |
9 | nosound | ||
10 | quiet | ||
8 | shell none | 11 | shell none |
12 | tracelog | ||
13 | |||
9 | private-bin uudeview | 14 | private-bin uudeview |
10 | private-dev | 15 | private-dev |
11 | private-etc nonexisting_fakefile_for_empty_etc | ||
12 | hostname uudeview | ||
13 | nosound | ||
14 | uudeview | ||
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 | |||
3 | noblacklist ~/.vim | 2 | noblacklist ~/.vim |
4 | noblacklist ~/.vimrc | 3 | noblacklist ~/.vimrc |
5 | noblacklist ~/.viminfo | 4 | noblacklist ~/.viminfo |
@@ -10,8 +9,8 @@ include /etc/firejail/disable-passwdmgr.inc | |||
10 | 9 | ||
11 | caps.drop all | 10 | caps.drop all |
12 | netfilter | 11 | netfilter |
12 | nogroups | ||
13 | nonewprivs | 13 | nonewprivs |
14 | noroot | 14 | noroot |
15 | nogroups | ||
16 | protocol unix,inet,inet6 | 15 | protocol unix,inet,inet6 |
17 | seccomp | 16 | seccomp |
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 | |||
3 | noblacklist ${HOME}/.VirtualBox | ||
4 | noblacklist ${HOME}/VirtualBox VMs | ||
5 | noblacklist ${HOME}/.config/VirtualBox | ||
6 | include /etc/firejail/disable-common.inc | ||
7 | include /etc/firejail/disable-programs.inc | ||
8 | include /etc/firejail/disable-passwdmgr.inc | ||
9 | |||
10 | caps.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 | |||
14 | protocol unix,inet,inet6 | 14 | protocol unix,inet,inet6 |
15 | seccomp | 15 | seccomp |
16 | shell none | 16 | shell none |
17 | tracelog | ||
18 | 17 | ||
19 | private-bin vlc,cvlc,nvlc,rvlc,qvlc,svlc | 18 | private-bin vlc,cvlc,nvlc,rvlc,qvlc,svlc |
20 | private-dev | 19 | private-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 | |||
14 | whitelist ~/.fontconfig | 14 | whitelist ~/.fontconfig |
15 | whitelist ~/.fonts.conf | 15 | whitelist ~/.fonts.conf |
16 | whitelist ~/.fonts.conf.d | 16 | whitelist ~/.fonts.conf.d |
17 | whitelist ~/.local/share/fonts | ||
17 | whitelist ~/.config/fontconfig | 18 | whitelist ~/.config/fontconfig |
18 | whitelist ~/.cache/fontconfig | 19 | whitelist ~/.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 | ||
2 | noblacklist ~/.sword | ||
3 | noblacklist ~/.xiphos | ||
4 | |||
5 | include /etc/firejail/disable-common.inc | ||
6 | include /etc/firejail/disable-devel.inc | ||
7 | include /etc/firejail/disable-passwdmgr.inc | ||
8 | include /etc/firejail/disable-programs.inc | ||
9 | |||
10 | blacklist ~/.bashrc | ||
11 | blacklist ~/.Xauthority | ||
12 | |||
13 | caps.drop all | ||
14 | netfilter | ||
15 | nogroups | ||
16 | nonewprivs | ||
17 | noroot | ||
18 | nosound | ||
19 | protocol unix,inet,inet6 | ||
20 | seccomp | ||
21 | shell none | ||
22 | tracelog | ||
23 | |||
24 | private-bin xiphos | ||
25 | private-etc fonts,resolv.conf,sword | ||
26 | private-dev | ||
27 | private-tmp | ||
28 | |||
29 | whitelist ${HOME}/.sword | ||
30 | whitelist ${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 | ################################ | ||
4 | noblacklist ${HOME}/.xpdfrc | ||
5 | include /etc/firejail/disable-common.inc | ||
6 | include /etc/firejail/disable-programs.inc | ||
7 | include /etc/firejail/disable-passwdmgr.inc | ||
8 | |||
9 | caps.drop all | ||
10 | net none | ||
11 | nonewprivs | ||
12 | noroot | ||
13 | protocol unix | ||
14 | shell none | ||
15 | seccomp | ||
16 | |||
17 | private-dev | ||
18 | private-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 | ||
10 | caps.drop all | 10 | caps.drop all |
11 | netfilter | 11 | netfilter |
12 | nonewprivs | ||
13 | nogroups | 12 | nogroups |
13 | nonewprivs | ||
14 | noroot | 14 | noroot |
15 | protocol unix,inet,inet6 | 15 | protocol unix,inet,inet6 |
16 | seccomp | 16 | seccomp |
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 |
2 | quiet | ||
3 | ignore noroot | 2 | ignore noroot |
4 | include /etc/firejail/default.profile | 3 | include /etc/firejail/default.profile |
5 | tracelog | 4 | |
6 | net none | ||
7 | shell none | ||
8 | blacklist /tmp/.X11-unix | 5 | blacklist /tmp/.X11-unix |
9 | private-dev | 6 | |
10 | nosound | 7 | net none |
11 | no3d | 8 | no3d |
9 | nosound | ||
10 | quiet | ||
11 | shell none | ||
12 | tracelog | ||
12 | 13 | ||
14 | private-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 | |||
7 | include /etc/firejail/disable-passwdmgr.inc | 7 | include /etc/firejail/disable-passwdmgr.inc |
8 | 8 | ||
9 | caps.drop all | 9 | caps.drop all |
10 | seccomp | ||
11 | protocol unix | ||
12 | netfilter | 10 | netfilter |
11 | nogroups | ||
13 | nonewprivs | 12 | nonewprivs |
14 | noroot | 13 | noroot |
15 | nogroups | ||
16 | nosound | 14 | nosound |
17 | shell none | 15 | shell none |
16 | seccomp | ||
17 | protocol unix | ||
18 | 18 | ||
19 | private-bin zathura | 19 | private-bin zathura |
20 | private-dev | 20 | private-dev |
@@ -1,4 +1,4 @@ | |||
1 | #!/bin/bash | 1 | #!/bin/sh |
2 | 2 | ||
3 | echo "extracting UID_MIN and GID_MIN" | 3 | echo "extracting UID_MIN and GID_MIN" |
4 | echo "#ifndef FIREJAIL_UIDS_H" > uids.h | 4 | echo "#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 | ||
2 | VERSION="0.9.44" | ||
3 | rm -fr ~/rpmbuild | ||
4 | rm -f firejail-$VERSION-1.x86_64.rpm | ||
5 | |||
6 | mkdir -p ~/rpmbuild/{RPMS,SRPMS,BUILD,SOURCES,SPECS,tmp} | ||
7 | cat <<EOF >~/.rpmmacros | ||
8 | %_topdir %(echo $HOME)/rpmbuild | ||
9 | %_tmppath %{_topdir}/tmp | ||
10 | EOF | ||
11 | |||
12 | cd ~/rpmbuild | ||
13 | echo "building directory tree" | ||
14 | |||
15 | mkdir -p firejail-$VERSION/usr/bin | ||
16 | install -m 755 /usr/bin/firejail firejail-$VERSION/usr/bin/. | ||
17 | install -m 755 /usr/bin/firemon firejail-$VERSION/usr/bin/. | ||
18 | install -m 755 /usr/bin/firecfg firejail-$VERSION/usr/bin/. | ||
19 | |||
20 | mkdir -p firejail-$VERSION/usr/lib/firejail | ||
21 | install -m 755 /usr/lib/firejail/faudit firejail-$VERSION/usr/lib/firejail/. | ||
22 | install -m 644 /usr/lib/firejail/firecfg.config firejail-$VERSION/usr/lib/firejail/. | ||
23 | install -m 755 /usr/lib/firejail/fshaper.sh firejail-$VERSION/usr/lib/firejail/. | ||
24 | install -m 755 /usr/lib/firejail/ftee firejail-$VERSION/usr/lib/firejail/. | ||
25 | install -m 644 /usr/lib/firejail/libtrace.so firejail-$VERSION/usr/lib/firejail/. | ||
26 | install -m 644 /usr/lib/firejail/libtracelog.so firejail-$VERSION/usr/lib/firejail/. | ||
27 | install -m 644 /usr/lib/firejail/libconnect.so firejail-$VERSION/usr/lib/firejail/. | ||
28 | |||
29 | mkdir -p firejail-$VERSION/usr/share/man/man1 | ||
30 | install -m 644 /usr/share/man/man1/firejail.1.gz firejail-$VERSION/usr/share/man/man1/. | ||
31 | install -m 644 /usr/share/man/man1/firemon.1.gz firejail-$VERSION/usr/share/man/man1/. | ||
32 | install -m 644 /usr/share/man/man1/firecfg.1.gz firejail-$VERSION/usr/share/man/man1/. | ||
33 | |||
34 | mkdir -p firejail-$VERSION/usr/share/man/man5 | ||
35 | install -m 644 /usr/share/man/man5/firejail-profile.5.gz firejail-$VERSION/usr/share/man/man5/. | ||
36 | install -m 644 /usr/share/man/man5/firejail-login.5.gz firejail-$VERSION/usr/share/man/man5/. | ||
37 | |||
38 | mkdir -p firejail-$VERSION/usr/share/doc/packages/firejail | ||
39 | install -m 644 /usr/share/doc/firejail/COPYING firejail-$VERSION/usr/share/doc/packages/firejail/. | ||
40 | install -m 644 /usr/share/doc/firejail/README firejail-$VERSION/usr/share/doc/packages/firejail/. | ||
41 | install -m 644 /usr/share/doc/firejail/RELNOTES firejail-$VERSION/usr/share/doc/packages/firejail/. | ||
42 | |||
43 | mkdir -p firejail-$VERSION/etc/firejail | ||
44 | install -m 644 /etc/firejail/0ad.profile firejail-$VERSION/etc/firejail/. | ||
45 | install -m 644 /etc/firejail/abrowser.profile firejail-$VERSION/etc/firejail/. | ||
46 | install -m 644 /etc/firejail/atom-beta.profile firejail-$VERSION/etc/firejail/. | ||
47 | install -m 644 /etc/firejail/atom.profile firejail-$VERSION/etc/firejail/. | ||
48 | install -m 644 /etc/firejail/atril.profile firejail-$VERSION/etc/firejail/. | ||
49 | install -m 644 /etc/firejail/audacious.profile firejail-$VERSION/etc/firejail/. | ||
50 | install -m 644 /etc/firejail/audacity.profile firejail-$VERSION/etc/firejail/. | ||
51 | install -m 644 /etc/firejail/aweather.profile firejail-$VERSION/etc/firejail/. | ||
52 | install -m 644 /etc/firejail/bitlbee.profile firejail-$VERSION/etc/firejail/. | ||
53 | install -m 644 /etc/firejail/brave.profile firejail-$VERSION/etc/firejail/. | ||
54 | install -m 644 /etc/firejail/cherrytree.profile firejail-$VERSION/etc/firejail/. | ||
55 | install -m 644 /etc/firejail/chromium-browser.profile firejail-$VERSION/etc/firejail/. | ||
56 | install -m 644 /etc/firejail/chromium.profile firejail-$VERSION/etc/firejail/. | ||
57 | install -m 644 /etc/firejail/clementine.profile firejail-$VERSION/etc/firejail/. | ||
58 | install -m 644 /etc/firejail/cmus.profile firejail-$VERSION/etc/firejail/. | ||
59 | install -m 644 /etc/firejail/conkeror.profile firejail-$VERSION/etc/firejail/. | ||
60 | install -m 644 /etc/firejail/corebird.profile firejail-$VERSION/etc/firejail/. | ||
61 | install -m 644 /etc/firejail/cpio.profile firejail-$VERSION/etc/firejail/. | ||
62 | install -m 644 /etc/firejail/cyberfox.profile firejail-$VERSION/etc/firejail/. | ||
63 | install -m 644 /etc/firejail/Cyberfox.profile firejail-$VERSION/etc/firejail/. | ||
64 | install -m 644 /etc/firejail/deadbeef.profile firejail-$VERSION/etc/firejail/. | ||
65 | install -m 644 /etc/firejail/default.profile firejail-$VERSION/etc/firejail/. | ||
66 | install -m 644 /etc/firejail/deluge.profile firejail-$VERSION/etc/firejail/. | ||
67 | install -m 644 /etc/firejail/dillo.profile firejail-$VERSION/etc/firejail/. | ||
68 | install -m 644 /etc/firejail/disable-common.inc firejail-$VERSION/etc/firejail/. | ||
69 | install -m 644 /etc/firejail/disable-devel.inc firejail-$VERSION/etc/firejail/. | ||
70 | install -m 644 /etc/firejail/disable-passwdmgr.inc firejail-$VERSION/etc/firejail/. | ||
71 | install -m 644 /etc/firejail/disable-programs.inc firejail-$VERSION/etc/firejail/. | ||
72 | install -m 644 /etc/firejail/dnscrypt-proxy.profile firejail-$VERSION/etc/firejail/. | ||
73 | install -m 644 /etc/firejail/dnsmasq.profile firejail-$VERSION/etc/firejail/. | ||
74 | install -m 644 /etc/firejail/dosbox.profile firejail-$VERSION/etc/firejail/. | ||
75 | install -m 644 /etc/firejail/dropbox.profile firejail-$VERSION/etc/firejail/. | ||
76 | install -m 644 /etc/firejail/empathy.profile firejail-$VERSION/etc/firejail/. | ||
77 | install -m 644 /etc/firejail/eom.profile firejail-$VERSION/etc/firejail/. | ||
78 | install -m 644 /etc/firejail/epiphany.profile firejail-$VERSION/etc/firejail/. | ||
79 | install -m 644 /etc/firejail/evince.profile firejail-$VERSION/etc/firejail/. | ||
80 | install -m 644 /etc/firejail/fbreader.profile firejail-$VERSION/etc/firejail/. | ||
81 | install -m 644 /etc/firejail/file.profile firejail-$VERSION/etc/firejail/. | ||
82 | install -m 644 /etc/firejail/filezilla.profile firejail-$VERSION/etc/firejail/. | ||
83 | install -m 644 /etc/firejail/firefox-esr.profile firejail-$VERSION/etc/firejail/. | ||
84 | install -m 644 /etc/firejail/firefox.profile firejail-$VERSION/etc/firejail/. | ||
85 | install -m 644 /etc/firejail/firejail.config firejail-$VERSION/etc/firejail/. | ||
86 | install -m 644 /etc/firejail/flashpeak-slimjet.profile firejail-$VERSION/etc/firejail/. | ||
87 | install -m 644 /etc/firejail/franz.profile firejail-$VERSION/etc/firejail/. | ||
88 | install -m 644 /etc/firejail/gajim.profile firejail-$VERSION/etc/firejail/. | ||
89 | install -m 644 /etc/firejail/gitter.profile firejail-$VERSION/etc/firejail/. | ||
90 | install -m 644 /etc/firejail/gnome-chess.profile firejail-$VERSION/etc/firejail/. | ||
91 | install -m 644 /etc/firejail/gnome-mplayer.profile firejail-$VERSION/etc/firejail/. | ||
92 | install -m 644 /etc/firejail/google-chrome-beta.profile firejail-$VERSION/etc/firejail/. | ||
93 | install -m 644 /etc/firejail/google-chrome.profile firejail-$VERSION/etc/firejail/. | ||
94 | install -m 644 /etc/firejail/google-chrome-stable.profile firejail-$VERSION/etc/firejail/. | ||
95 | install -m 644 /etc/firejail/google-chrome-unstable.profile firejail-$VERSION/etc/firejail/. | ||
96 | install -m 644 /etc/firejail/google-play-music-desktop-player.profile firejail-$VERSION/etc/firejail/. | ||
97 | install -m 644 /etc/firejail/gpredict.profile firejail-$VERSION/etc/firejail/. | ||
98 | install -m 644 /etc/firejail/gtar.profile firejail-$VERSION/etc/firejail/. | ||
99 | install -m 644 /etc/firejail/gthumb.profile firejail-$VERSION/etc/firejail/. | ||
100 | install -m 644 /etc/firejail/gwenview.profile firejail-$VERSION/etc/firejail/. | ||
101 | install -m 644 /etc/firejail/gzip.profile firejail-$VERSION/etc/firejail/. | ||
102 | install -m 644 /etc/firejail/hedgewars.profile firejail-$VERSION/etc/firejail/. | ||
103 | install -m 644 /etc/firejail/hexchat.profile firejail-$VERSION/etc/firejail/. | ||
104 | install -m 644 /etc/firejail/icecat.profile firejail-$VERSION/etc/firejail/. | ||
105 | install -m 644 /etc/firejail/icedove.profile firejail-$VERSION/etc/firejail/. | ||
106 | install -m 644 /etc/firejail/iceweasel.profile firejail-$VERSION/etc/firejail/. | ||
107 | install -m 644 /etc/firejail/inox.profile firejail-$VERSION/etc/firejail/. | ||
108 | install -m 644 /etc/firejail/jitsi.profile firejail-$VERSION/etc/firejail/. | ||
109 | install -m 644 /etc/firejail/kmail.profile firejail-$VERSION/etc/firejail/. | ||
110 | install -m 644 /etc/firejail/konversation.profile firejail-$VERSION/etc/firejail/. | ||
111 | install -m 644 /etc/firejail/less.profile firejail-$VERSION/etc/firejail/. | ||
112 | install -m 644 /etc/firejail/libreoffice.profile firejail-$VERSION/etc/firejail/. | ||
113 | install -m 644 /etc/firejail/localc.profile firejail-$VERSION/etc/firejail/. | ||
114 | install -m 644 /etc/firejail/lodraw.profile firejail-$VERSION/etc/firejail/. | ||
115 | install -m 644 /etc/firejail/loffice.profile firejail-$VERSION/etc/firejail/. | ||
116 | install -m 644 /etc/firejail/lofromtemplate.profile firejail-$VERSION/etc/firejail/. | ||
117 | install -m 644 /etc/firejail/login.users firejail-$VERSION/etc/firejail/. | ||
118 | install -m 644 /etc/firejail/loimpress.profile firejail-$VERSION/etc/firejail/. | ||
119 | install -m 644 /etc/firejail/lomath.profile firejail-$VERSION/etc/firejail/. | ||
120 | install -m 644 /etc/firejail/loweb.profile firejail-$VERSION/etc/firejail/. | ||
121 | install -m 644 /etc/firejail/lowriter.profile firejail-$VERSION/etc/firejail/. | ||
122 | install -m 644 /etc/firejail/lxterminal.profile firejail-$VERSION/etc/firejail/. | ||
123 | install -m 644 /etc/firejail/mathematica.profile firejail-$VERSION/etc/firejail/. | ||
124 | install -m 644 /etc/firejail/Mathematica.profile firejail-$VERSION/etc/firejail/. | ||
125 | install -m 644 /etc/firejail/mcabber.profile firejail-$VERSION/etc/firejail/. | ||
126 | install -m 644 /etc/firejail/midori.profile firejail-$VERSION/etc/firejail/. | ||
127 | install -m 644 /etc/firejail/mpv.profile firejail-$VERSION/etc/firejail/. | ||
128 | install -m 644 /etc/firejail/mupen64plus.profile firejail-$VERSION/etc/firejail/. | ||
129 | install -m 644 /etc/firejail/netsurf.profile firejail-$VERSION/etc/firejail/. | ||
130 | install -m 644 /etc/firejail/nolocal.net firejail-$VERSION/etc/firejail/. | ||
131 | install -m 644 /etc/firejail/okular.profile firejail-$VERSION/etc/firejail/. | ||
132 | install -m 644 /etc/firejail/openbox.profile firejail-$VERSION/etc/firejail/. | ||
133 | install -m 644 /etc/firejail/opera-beta.profile firejail-$VERSION/etc/firejail/. | ||
134 | install -m 644 /etc/firejail/opera.profile firejail-$VERSION/etc/firejail/. | ||
135 | install -m 644 /etc/firejail/palemoon.profile firejail-$VERSION/etc/firejail/. | ||
136 | install -m 644 /etc/firejail/parole.profile firejail-$VERSION/etc/firejail/. | ||
137 | install -m 644 /etc/firejail/pidgin.profile firejail-$VERSION/etc/firejail/. | ||
138 | install -m 644 /etc/firejail/pix.profile firejail-$VERSION/etc/firejail/. | ||
139 | install -m 644 /etc/firejail/polari.profile firejail-$VERSION/etc/firejail/. | ||
140 | install -m 644 /etc/firejail/psi-plus.profile firejail-$VERSION/etc/firejail/. | ||
141 | install -m 644 /etc/firejail/qbittorrent.profile firejail-$VERSION/etc/firejail/. | ||
142 | install -m 644 /etc/firejail/qtox.profile firejail-$VERSION/etc/firejail/. | ||
143 | install -m 644 /etc/firejail/quassel.profile firejail-$VERSION/etc/firejail/. | ||
144 | install -m 644 /etc/firejail/quiterss.profile firejail-$VERSION/etc/firejail/. | ||
145 | install -m 644 /etc/firejail/qutebrowser.profile firejail-$VERSION/etc/firejail/. | ||
146 | install -m 644 /etc/firejail/rhythmbox.profile firejail-$VERSION/etc/firejail/. | ||
147 | install -m 644 /etc/firejail/rtorrent.profile firejail-$VERSION/etc/firejail/. | ||
148 | install -m 644 /etc/firejail/seamonkey-bin.profile firejail-$VERSION/etc/firejail/. | ||
149 | install -m 644 /etc/firejail/seamonkey.profile firejail-$VERSION/etc/firejail/. | ||
150 | install -m 644 /etc/firejail/server.profile firejail-$VERSION/etc/firejail/. | ||
151 | install -m 644 /etc/firejail/skypeforlinux.profile firejail-$VERSION/etc/firejail/. | ||
152 | install -m 644 /etc/firejail/skype.profile firejail-$VERSION/etc/firejail/. | ||
153 | install -m 644 /etc/firejail/slack.profile firejail-$VERSION/etc/firejail/. | ||
154 | install -m 644 /etc/firejail/snap.profile firejail-$VERSION/etc/firejail/. | ||
155 | install -m 644 /etc/firejail/soffice.profile firejail-$VERSION/etc/firejail/. | ||
156 | install -m 644 /etc/firejail/spotify.profile firejail-$VERSION/etc/firejail/. | ||
157 | install -m 644 /etc/firejail/ssh.profile firejail-$VERSION/etc/firejail/. | ||
158 | install -m 644 /etc/firejail/steam.profile firejail-$VERSION/etc/firejail/. | ||
159 | install -m 644 /etc/firejail/stellarium.profile firejail-$VERSION/etc/firejail/. | ||
160 | install -m 644 /etc/firejail/strings.profile firejail-$VERSION/etc/firejail/. | ||
161 | install -m 644 /etc/firejail/tar.profile firejail-$VERSION/etc/firejail/. | ||
162 | install -m 644 /etc/firejail/telegram.profile firejail-$VERSION/etc/firejail/. | ||
163 | install -m 644 /etc/firejail/Telegram.profile firejail-$VERSION/etc/firejail/. | ||
164 | install -m 644 /etc/firejail/thunderbird.profile firejail-$VERSION/etc/firejail/. | ||
165 | install -m 644 /etc/firejail/totem.profile firejail-$VERSION/etc/firejail/. | ||
166 | install -m 644 /etc/firejail/transmission-gtk.profile firejail-$VERSION/etc/firejail/. | ||
167 | install -m 644 /etc/firejail/transmission-qt.profile firejail-$VERSION/etc/firejail/. | ||
168 | install -m 644 /etc/firejail/uget-gtk.profile firejail-$VERSION/etc/firejail/. | ||
169 | install -m 644 /etc/firejail/unbound.profile firejail-$VERSION/etc/firejail/. | ||
170 | install -m 644 /etc/firejail/unrar.profile firejail-$VERSION/etc/firejail/. | ||
171 | install -m 644 /etc/firejail/unzip.profile firejail-$VERSION/etc/firejail/. | ||
172 | install -m 644 /etc/firejail/uudeview.profile firejail-$VERSION/etc/firejail/. | ||
173 | install -m 644 /etc/firejail/vivaldi-beta.profile firejail-$VERSION/etc/firejail/. | ||
174 | install -m 644 /etc/firejail/vivaldi.profile firejail-$VERSION/etc/firejail/. | ||
175 | install -m 644 /etc/firejail/vlc.profile firejail-$VERSION/etc/firejail/. | ||
176 | install -m 644 /etc/firejail/warzone2100.profile firejail-$VERSION/etc/firejail/. | ||
177 | install -m 644 /etc/firejail/webserver.net firejail-$VERSION/etc/firejail/. | ||
178 | install -m 644 /etc/firejail/weechat-curses.profile firejail-$VERSION/etc/firejail/. | ||
179 | install -m 644 /etc/firejail/weechat.profile firejail-$VERSION/etc/firejail/. | ||
180 | install -m 644 /etc/firejail/wesnoth.profile firejail-$VERSION/etc/firejail/. | ||
181 | install -m 644 /etc/firejail/whitelist-common.inc firejail-$VERSION/etc/firejail/. | ||
182 | install -m 644 /etc/firejail/wine.profile firejail-$VERSION/etc/firejail/. | ||
183 | install -m 644 /etc/firejail/xchat.profile firejail-$VERSION/etc/firejail/. | ||
184 | install -m 644 /etc/firejail/xplayer.profile firejail-$VERSION/etc/firejail/. | ||
185 | install -m 644 /etc/firejail/xreader.profile firejail-$VERSION/etc/firejail/. | ||
186 | install -m 644 /etc/firejail/xviewer.profile firejail-$VERSION/etc/firejail/. | ||
187 | install -m 644 /etc/firejail/xzdec.profile firejail-$VERSION/etc/firejail/. | ||
188 | install -m 644 /etc/firejail/xz.profile firejail-$VERSION/etc/firejail/. | ||
189 | install -m 644 /etc/firejail/zathura.profile firejail-$VERSION/etc/firejail/. | ||
190 | install -m 644 /etc/firejail/7z.profile firejail-$VERSION/etc/firejail/. | ||
191 | install -m 644 /etc/firejail/keepass.profile firejail-$VERSION/etc/firejail/. | ||
192 | install -m 644 /etc/firejail/keepassx.profile firejail-$VERSION/etc/firejail/. | ||
193 | install -m 644 /etc/firejail/claws-mail.profile firejail-$VERSION/etc/firejail/. | ||
194 | install -m 644 /etc/firejail/mutt.profile firejail-$VERSION/etc/firejail/. | ||
195 | install -m 644 /etc/firejail/git.profile firejail-$VERSION/etc/firejail/. | ||
196 | install -m 644 /etc/firejail/emacs.profile firejail-$VERSION/etc/firejail/. | ||
197 | install -m 644 /etc/firejail/vim.profile firejail-$VERSION/etc/firejail/. | ||
198 | install -m 644 /etc/firejail/xpdf.profile firejail-$VERSION/etc/firejail/. | ||
199 | install -m 644 /etc/firejail/virtualbox.profile firejail-$VERSION/etc/firejail/. | ||
200 | install -m 644 /etc/firejail/openshot.profile firejail-$VERSION/etc/firejail/. | ||
201 | install -m 644 /etc/firejail/flowblade.profile firejail-$VERSION/etc/firejail/. | ||
202 | install -m 644 /etc/firejail/eog.profile firejail-$VERSION/etc/firejail/. | ||
203 | install -m 644 /etc/firejail/evolution.profile firejail-$VERSION/etc/firejail/. | ||
204 | install -m 644 /etc/firejail/feh.profile firejail-$VERSION/etc/firejail/. | ||
205 | install -m 644 /etc/firejail/gimp.profile firejail-$VERSION/etc/firejail/. | ||
206 | install -m 644 /etc/firejail/inkscape.profile firejail-$VERSION/etc/firejail/. | ||
207 | install -m 644 /etc/firejail/luminance-hdr.profile firejail-$VERSION/etc/firejail/. | ||
208 | install -m 644 /etc/firejail/mupdf.profile firejail-$VERSION/etc/firejail/. | ||
209 | install -m 644 /etc/firejail/qpdfview.profile firejail-$VERSION/etc/firejail/. | ||
210 | install -m 644 /etc/firejail/ranger.profile firejail-$VERSION/etc/firejail/. | ||
211 | install -m 644 /etc/firejail/synfigstudio.profile firejail-$VERSION/etc/firejail/. | ||
212 | |||
213 | |||
214 | mkdir -p firejail-$VERSION/usr/share/bash-completion/completions | ||
215 | install -m 644 /usr/share/bash-completion/completions/firejail firejail-$VERSION/usr/share/bash-completion/completions/. | ||
216 | install -m 644 /usr/share/bash-completion/completions/firemon firejail-$VERSION/usr/share/bash-completion/completions/. | ||
217 | install -m 644 /usr/share/bash-completion/completions/firecfg firejail-$VERSION/usr/share/bash-completion/completions/. | ||
218 | |||
219 | echo "building tar.gz archive" | ||
220 | tar -czvf firejail-$VERSION.tar.gz firejail-$VERSION | ||
221 | |||
222 | cp firejail-$VERSION.tar.gz SOURCES/. | ||
223 | |||
224 | echo "building config spec" | ||
225 | cat <<EOF > SPECS/firejail.spec | ||
226 | %define __spec_install_post %{nil} | ||
227 | %define debug_package %{nil} | ||
228 | %define __os_install_post %{_dbpath}/brp-compress | ||
229 | |||
230 | Summary: Linux namepaces sandbox program | ||
231 | Name: firejail | ||
232 | Version: $VERSION | ||
233 | Release: 1 | ||
234 | License: GPL+ | ||
235 | Group: Development/Tools | ||
236 | SOURCE0 : %{name}-%{version}.tar.gz | ||
237 | URL: http://firejail.wordpress.com | ||
238 | |||
239 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root | ||
240 | |||
241 | %description | ||
242 | Firejail is a SUID sandbox program that reduces the risk of security | ||
243 | breaches by restricting the running environment of untrusted applications | ||
244 | using Linux namespaces. It includes a sandbox profile for Mozilla Firefox. | ||
245 | |||
246 | %prep | ||
247 | %setup -q | ||
248 | |||
249 | %build | ||
250 | |||
251 | %install | ||
252 | rm -rf %{buildroot} | ||
253 | mkdir -p %{buildroot} | ||
254 | |||
255 | cp -a * %{buildroot} | ||
256 | |||
257 | |||
258 | %clean | ||
259 | rm -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 | ||
458 | chmod 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 | |||
534 | EOF | ||
535 | |||
536 | echo "building rpm" | ||
537 | rpmbuild -ba SPECS/firejail.spec | ||
538 | rpm -qpl RPMS/x86_64/firejail-$VERSION-1.x86_64.rpm | ||
539 | cd .. | ||
540 | rm -f firejail-$VERSION-1.x86_64.rpm | ||
541 | cp 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 | |||
42 | opera | 42 | opera |
43 | palemoon | 43 | palemoon |
44 | qutebrowser | 44 | qutebrowser |
45 | start-tor-browser | ||
45 | seamonkey | 46 | seamonkey |
46 | seamonkey-bin | 47 | seamonkey-bin |
47 | thunderbird | 48 | thunderbird |
48 | vivaldi-beta | 49 | vivaldi-beta |
49 | vivaldi | 50 | vivaldi |
51 | evolution | ||
50 | 52 | ||
51 | # chat/messaging | 53 | # chat/messaging |
52 | bitlbee | 54 | bitlbee |
@@ -76,6 +78,7 @@ unbound | |||
76 | mupen64plus | 78 | mupen64plus |
77 | wine | 79 | wine |
78 | dosbox | 80 | dosbox |
81 | virtualbox | ||
79 | 82 | ||
80 | # games | 83 | # games |
81 | 0ad | 84 | 0ad |
@@ -134,8 +137,12 @@ Mathematica | |||
134 | mathematica | 137 | mathematica |
135 | okular | 138 | okular |
136 | pix | 139 | pix |
140 | xpdf | ||
137 | xreader | 141 | xreader |
138 | zathura | 142 | zathura |
143 | openshot | ||
144 | flowblade | ||
145 | eog | ||
139 | 146 | ||
140 | # other | 147 | # other |
141 | ssh | 148 | ssh |
@@ -144,6 +151,7 @@ atom | |||
144 | ranger | 151 | ranger |
145 | keepass | 152 | keepass |
146 | keepassx | 153 | keepassx |
154 | xiphos | ||
147 | 155 | ||
148 | # weather/climate | 156 | # weather/climate |
149 | aweather | 157 | aweather |
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) | |||
30 | CFLAGS += -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 | 30 | CFLAGS += -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 |
31 | LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread | 31 | LDFLAGS += -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 | ||
36 | firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o | 36 | firejail: $(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 | ||
39 | clean:; rm -f *.o firejail firejail.1 firejail.1.gz | 39 | clean:; 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) { | |||
121 | void appimage_clear(void) { | 144 | void 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 | /* | ||
21 | Compile with: | ||
22 | gcc elfsize.c -o elfsize | ||
23 | Example: | ||
24 | ls -l 126584 | ||
25 | Calculation using the values also reported by readelf -h: | ||
26 | Start of section headers e_shoff 124728 | ||
27 | Size of section headers e_shentsize 64 | ||
28 | Number of section headers e_shnum 29 | ||
29 | e_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 | |||
41 | typedef Elf32_Nhdr Elf_Nhdr; | ||
42 | |||
43 | static 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 | |||
53 | static 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 | |||
60 | static 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 | |||
67 | static 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 | ||
75 | static 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 | ||
92 | static 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 | ||
110 | long unsigned int appimage2_size(const char *fname) { | ||
111 | /* TODO, FIXME: This assumes that the section header table (SHT) is | ||
112 | the last part of the ELF. This is usually the case but | ||
113 | it could also be that the last section is the last part | ||
114 | of 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 | |||
155 | getout: | ||
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 |
44 | int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr) { | 45 | int 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) | ||
290 | void 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 | |||
209 | void 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 | ||
177 | typedef struct config_t { | 187 | typedef struct config_t { |
@@ -358,21 +368,19 @@ void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask, int mtu); | |||
358 | void net_if_ip6(const char *ifname, const char *addr6); | 368 | void net_if_ip6(const char *ifname, const char *addr6); |
359 | int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6], int *mtu); | 369 | int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6], int *mtu); |
360 | int net_add_route(uint32_t dest, uint32_t mask, uint32_t gw); | 370 | int net_add_route(uint32_t dest, uint32_t mask, uint32_t gw); |
361 | void net_ifprint(void); | ||
362 | void net_bridge_add_interface(const char *bridge, const char *dev); | ||
363 | uint32_t network_get_defaultgw(void); | 371 | uint32_t network_get_defaultgw(void); |
364 | int net_config_mac(const char *ifname, const unsigned char mac[6]); | 372 | int net_config_mac(const char *ifname, const unsigned char mac[6]); |
365 | int net_get_mac(const char *ifname, unsigned char mac[6]); | 373 | int net_get_mac(const char *ifname, unsigned char mac[6]); |
374 | void net_config_interface(const char *dev, uint32_t ip, uint32_t mask, int mtu); | ||
375 | |||
376 | // preproc.c | ||
377 | void preproc_build_firejail_dir(void); | ||
378 | void preproc_mount_mnt_dir(void); | ||
379 | void preproc_build_cp_command(void); | ||
380 | void preproc_delete_cp_command(void) ; | ||
381 | void preproc_remount_mnt_dir(void); | ||
366 | 382 | ||
367 | // fs.c | 383 | // fs.c |
368 | // build /run/firejail directory | ||
369 | void fs_build_firejail_dir(void); | ||
370 | // build /run/firejail/mnt directory | ||
371 | void fs_build_mnt_dir(void); | ||
372 | // grab a copy of cp command | ||
373 | void fs_build_cp_command(void); | ||
374 | // delete the temporary cp command | ||
375 | void 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 |
377 | void fs_blacklist(void); | 385 | void 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 |
390 | void fs_chroot(const char *rootdir); | 398 | void fs_chroot(const char *rootdir); |
391 | int fs_check_chroot_dir(const char *rootdir); | 399 | int fs_check_chroot_dir(const char *rootdir); |
392 | void 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); | |||
426 | int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr); | 433 | int 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 |
428 | uint32_t arp_assign(const char *dev, Bridge *br); | 435 | uint32_t arp_assign(const char *dev, Bridge *br); |
429 | // scan interface (--scan option) | ||
430 | void arp_scan(const char *dev, uint32_t srcaddr, uint32_t srcmask); | ||
431 | |||
432 | // veth.c | ||
433 | int net_create_veth(const char *dev, const char *nsdev, unsigned pid); | ||
434 | int net_create_macvlan(const char *dev, const char *parent, unsigned pid); | ||
435 | int net_move_interface(const char *dev, unsigned pid); | ||
436 | 436 | ||
437 | // util.c | 437 | // util.c |
438 | void drop_privs(int nogroups); | 438 | void drop_privs(int nogroups); |
@@ -457,10 +457,11 @@ char *expand_home(const char *path, const char* homedir); | |||
457 | const char *gnu_basename(const char *path); | 457 | const char *gnu_basename(const char *path); |
458 | uid_t pid_get_uid(pid_t pid); | 458 | uid_t pid_get_uid(pid_t pid); |
459 | void invalid_filename(const char *fname); | 459 | void invalid_filename(const char *fname); |
460 | uid_t get_tty_gid(void); | 460 | uid_t get_group_id(const char *group); |
461 | uid_t get_audio_gid(void); | ||
462 | int remove_directory(const char *path); | 461 | int remove_directory(const char *path); |
463 | void flush_stdin(void); | 462 | void flush_stdin(void); |
463 | void create_empty_dir_as_root(const char *dir, mode_t mode); | ||
464 | void create_empty_file_as_root(const char *dir, mode_t mode); | ||
464 | 465 | ||
465 | // fs_var.c | 466 | // fs_var.c |
466 | void fs_var_log(void); // mounting /var/log | 467 | void 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 |
499 | int seccomp_load(const char *fname); | ||
500 | void seccomp_filter_32(void); | ||
501 | void seccomp_filter_64(void); | ||
498 | int seccomp_filter_drop(int enforce_seccomp); | 502 | int seccomp_filter_drop(int enforce_seccomp); |
499 | int seccomp_filter_keep(void); | 503 | int seccomp_filter_keep(void); |
500 | void seccomp_set(void); | 504 | int seccomp_filter_errno(void); |
501 | void seccomp_print_filter_name(const char *name); | 505 | void seccomp_print_filter_name(const char *name); |
502 | void seccomp_print_filter(pid_t pid); | 506 | void seccomp_print_filter(pid_t pid); |
503 | int seccomp_filter_errno(void); | ||
504 | 507 | ||
505 | // caps.c | 508 | // caps.c |
506 | int caps_default_filter(void); | 509 | int caps_default_filter(void); |
@@ -517,8 +520,6 @@ void caps_print_filter_name(const char *name); | |||
517 | const char *syscall_find_nr(int nr); | 520 | const char *syscall_find_nr(int nr); |
518 | // return -1 if error, 0 if no error | 521 | // return -1 if error, 0 if no error |
519 | int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg), int arg); | 522 | int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg), int arg); |
520 | // print all available syscallsseccomp | ||
521 | void syscall_print(void); | ||
522 | 523 | ||
523 | // fs_trace.c | 524 | // fs_trace.c |
524 | void fs_trace_preload(void); | 525 | void fs_trace_preload(void); |
@@ -597,13 +598,10 @@ void fs_check_bin_list(void); | |||
597 | void fs_private_bin_list(void); | 598 | void fs_private_bin_list(void); |
598 | 599 | ||
599 | // protocol.c | 600 | // protocol.c |
600 | void protocol_list(); | ||
601 | void protocol_print_filter_name(const char *name); | ||
602 | void protocol_print_filter(pid_t pid); | ||
603 | void protocol_store(const char *prlist); | ||
604 | void protocol_filter(void); | ||
605 | void protocol_filter_save(void); | 601 | void protocol_filter_save(void); |
606 | void protocol_filter_load(const char *fname); | 602 | void protocol_filter_load(const char *fname); |
603 | void protocol_print_filter_name(const char *name); | ||
604 | void protocol_print_filter(pid_t pid); | ||
607 | 605 | ||
608 | // restrict_users.c | 606 | // restrict_users.c |
609 | void restrict_users(void); | 607 | void restrict_users(void); |
@@ -672,14 +670,33 @@ extern char *xephyr_extra_params; | |||
672 | extern char *netfilter_default; | 670 | extern char *netfilter_default; |
673 | int checkcfg(int val); | 671 | int checkcfg(int val); |
674 | void print_compiletime_support(void); | 672 | void print_compiletime_support(void); |
673 | void x11_xorg(void); | ||
675 | 674 | ||
676 | // appimage.c | 675 | // appimage.c |
677 | void appimage_set(const char *appimage_path); | 676 | void appimage_set(const char *appimage_path); |
678 | void appimage_clear(void); | 677 | void appimage_clear(void); |
679 | const char *appimage_getdir(void); | 678 | const char *appimage_getdir(void); |
680 | 679 | ||
680 | // appimage_size.c | ||
681 | long unsigned int appimage2_size(const char *fname); | ||
682 | |||
681 | // cmdline.c | 683 | // cmdline.c |
682 | void build_cmdline(char **command_line, char **window_title, int argc, char **argv, int index); | 684 | void 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 | ||
698 | int 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 | ||
30 | static void fs_rdwr(const char *dir); | 30 | static void fs_rdwr(const char *dir); |
31 | 31 | ||
32 | static 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 | |||
45 | static 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 | ||
58 | static 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 | ||
73 | void 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 | ||
113 | static int tmpfs_mounted = 0; | ||
114 | #ifdef HAVE_CHROOT | ||
115 | static void fs_build_remount_mnt_dir(void) { | ||
116 | tmpfs_mounted = 0; | ||
117 | fs_build_mnt_dir(); | ||
118 | } | ||
119 | #endif | ||
120 | |||
121 | void 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 | ||
143 | void 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 | ||
172 | void 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 | ||
1248 | void 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 | ||
247 | void fs_dev_shm(void) { | 246 | void 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 | ||
286 | static void disable_file_or_dir(const char *fname) { | 286 | static 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 | ||
105 | static int store_xauthority(void) { | 105 | static 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 | ||
132 | static int store_asoundrc(void) { | 130 | static 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 | ||
28 | void fs_hostname(const char *hostname) { | 28 | void 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 | ||
46 | void fs_trace(void) { | 46 | void 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 | |||
24 | static 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 | |||
39 | static 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 | |||
50 | void 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 | |||
63 | void 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 | |||
76 | void 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 | |||
89 | void 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 | |||
54 | int arg_private = 0; // mount private /home and /tmp directoryu | 54 | int arg_private = 0; // mount private /home and /tmp directoryu |
55 | int arg_private_template = 0; // mount private /home using a template | 55 | int arg_private_template = 0; // mount private /home using a template |
56 | int arg_debug = 0; // print debug messages | 56 | int arg_debug = 0; // print debug messages |
57 | int arg_debug_check_filename; // print debug messages for filename checking | 57 | int arg_debug_check_filename = 0; // print debug messages for filename checking |
58 | int arg_debug_blacklists; // print debug messages for blacklists | 58 | int arg_debug_blacklists = 0; // print debug messages for blacklists |
59 | int arg_debug_whitelists; // print debug messages for whitelists | 59 | int arg_debug_whitelists = 0; // print debug messages for whitelists |
60 | int arg_nonetwork = 0; // --net=none | 60 | int arg_nonetwork = 0; // --net=none |
61 | int arg_command = 0; // -c | 61 | int arg_command = 0; // -c |
62 | int arg_overlay = 0; // overlay option | 62 | int 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 | ||
32 | void 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 | |||
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 | ||
96 | int net_get_mtu(const char *ifname) { | 32 | int 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 | ||
248 | void 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 | |||
283 | struct 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 |
290 | void net_if_ip6(const char *ifname, const char *addr6) { | 136 | void 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 | ||
352 | void 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 |
398 | int net_add_route(uint32_t ip, uint32_t mask, uint32_t gw) { | 148 | int 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 | ||
435 | void 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 |
482 | uint32_t network_get_defaultgw(void) { | 186 | uint32_t network_get_defaultgw(void) { |
@@ -510,20 +214,15 @@ uint32_t network_get_defaultgw(void) { | |||
510 | } | 214 | } |
511 | 215 | ||
512 | int net_config_mac(const char *ifname, const unsigned char mac[6]) { | 216 | int 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 | |||
249 | void 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 | ||
292 | void network_main(pid_t child) { | 291 | void 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 | |||
24 | static int tmpfs_mounted = 0; | ||
25 | |||
26 | // build /run/firejail directory | ||
27 | void 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 | ||
68 | void 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 | ||
110 | void 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 | ||
139 | void 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 | |||
54 | static char *protocol[] = { | ||
55 | "unix", | ||
56 | "inet", | ||
57 | "inet6", | ||
58 | "netlink", | ||
59 | "packet", | ||
60 | NULL | ||
61 | }; | ||
62 | |||
63 | static 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 | ||
73 | struct sock_filter whitelist[] = { | ||
74 | WHITELIST(AF_UNIX) | ||
75 | }; | ||
76 | unsigned whitelist_len = sizeof(whitelist) / sizeof(struct sock_filter); | ||
77 | |||
78 | |||
79 | |||
80 | static 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 | |||
91 | static 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 | ||
103 | void 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 | ||
121 | void 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 | |||
153 | errout: | ||
154 | fprintf(stderr, "Error: invalid protocol list\n"); | ||
155 | exit(1); | ||
156 | } | ||
157 | |||
158 | // install protocol filter | ||
159 | void 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 | ||
185 | printf("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 | } | ||
196 | printf("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 | ||
216 | printf("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 | ||
241 | printf("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 | ||
268 | void protocol_filter_save(void) { | 25 | void 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 |
23 | char *restricted_user = NULL; | 24 | char *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 | ||
287 | void start_audit(void) { | 259 | void 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) { | ||
477 | assert(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) { | ||
483 | assert(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) { | ||
489 | assert(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) { | ||
495 | assert(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 | |||
29 | static 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 | |||
102 | static struct sock_fprog prog = { | ||
103 | .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])), | ||
104 | .filter = filter, | ||
105 | }; | ||
106 | |||
107 | typedef struct sbox_config { | ||
108 | char *name; | ||
109 | char *path; | ||
110 | unsigned filters; | ||
111 | } SboxConfig; | ||
112 | |||
113 | |||
114 | int 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 | ||
26 | static struct sock_filter *sfilter = NULL; | ||
27 | static int sfilter_alloc_size = 0; | ||
28 | static int sfilter_index = 0; | ||
29 | |||
30 | // debug filter | ||
31 | void 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 | ||
88 | static 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 | |||
124 | static 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 | |||
143 | static 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 | |||
170 | static 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 | |||
197 | static 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 | |||
223 | static 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 | |||
249 | static 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 | 25 | int seccomp_load(const char *fname) { |
277 | static 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 | ||
298 | static 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 |
339 | void seccomp_filter_32(void) { | 71 | void 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 |
412 | void seccomp_filter_64(void) { | 88 | void 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 |
487 | int seccomp_filter_drop(int enforce_seccomp) { | 106 | int 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 |
736 | int seccomp_filter_keep(void) { | 199 | int 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 |
779 | int seccomp_filter_errno(void) { | 220 | int 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, | 246 | printf("*** --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 | |||
821 | void 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 | ||
840 | void seccomp_print_filter_name(const char *name) { | 251 | void 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 |
175 | int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) { | 175 | int 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 | ||
652 | uid_t get_tty_gid(void) { | 658 | uid_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 | |||
663 | uid_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 | ||
699 | void 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 | |||
716 | void 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 @@ | |||
1 | all: fnet | ||
2 | |||
3 | prefix=@prefix@ | ||
4 | exec_prefix=@exec_prefix@ | ||
5 | libdir=@libdir@ | ||
6 | sysconfdir=@sysconfdir@ | ||
7 | |||
8 | VERSION=@PACKAGE_VERSION@ | ||
9 | NAME=@PACKAGE_NAME@ | ||
10 | HAVE_SECCOMP_H=@HAVE_SECCOMP_H@ | ||
11 | HAVE_SECCOMP=@HAVE_SECCOMP@ | ||
12 | HAVE_CHROOT=@HAVE_CHROOT@ | ||
13 | HAVE_BIND=@HAVE_BIND@ | ||
14 | HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@ | ||
15 | HAVE_NETWORK=@HAVE_NETWORK@ | ||
16 | HAVE_USERNS=@HAVE_USERNS@ | ||
17 | HAVE_X11=@HAVE_X11@ | ||
18 | HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@ | ||
19 | HAVE_WHITELIST=@HAVE_WHITELIST@ | ||
20 | HAVE_GLOBALCFG=@HAVE_GLOBALCFG@ | ||
21 | HAVE_APPARMOR=@HAVE_APPARMOR@ | ||
22 | HAVE_OVERLAYFS=@HAVE_OVERLAYFS@ | ||
23 | HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@ | ||
24 | EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@ | ||
25 | |||
26 | H_FILE_LIST = $(sort $(wildcard *.[h])) | ||
27 | C_FILE_LIST = $(sort $(wildcard *.c)) | ||
28 | OBJS = $(C_FILE_LIST:.c=.o) | ||
29 | BINOBJS = $(foreach file, $(OBJS), $file) | ||
30 | CFLAGS += -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 | ||
31 | LDFLAGS += -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 | |||
36 | fnet: $(OBJS) ../lib/libnetlink.o ../lib/common.o | ||
37 | $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/libnetlink.o $(LIBS) $(EXTRA_LDFLAGS) | ||
38 | |||
39 | clean:; rm -f *.o fnet | ||
40 | |||
41 | distclean: 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 | |||
31 | typedef 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) | ||
45 | void 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 | ||
30 | int net_create_veth(const char *dev, const char *nsdev, unsigned pid); | ||
31 | int net_create_macvlan(const char *dev, const char *parent, unsigned pid); | ||
32 | int net_move_interface(const char *dev, unsigned pid); | ||
33 | |||
34 | // interface.c | ||
35 | void net_bridge_add_interface(const char *bridge, const char *dev); | ||
36 | void net_if_up(const char *ifname); | ||
37 | int net_get_mtu(const char *ifname); | ||
38 | void net_set_mtu(const char *ifname, int mtu); | ||
39 | void net_ifprint(int scan); | ||
40 | int net_get_mac(const char *ifname, unsigned char mac[6]); | ||
41 | void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask, int mtu); | ||
42 | int net_if_mac(const char *ifname, const unsigned char mac[6]); | ||
43 | void net_if_ip6(const char *ifname, const char *addr6); | ||
44 | |||
45 | |||
46 | // arp.c | ||
47 | void 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 | ||
33 | void 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 | ||
79 | void 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 | |||
138 | int 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 | |||
162 | void 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 | ||
184 | void 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 | |||
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 | |||
248 | int 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 | ||
269 | void 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 | |||
311 | int 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 | ||
331 | struct ifreq6 { | ||
332 | struct in6_addr ifr6_addr; | ||
333 | uint32_t ifr6_prefixlen; | ||
334 | unsigned int ifr6_ifindex; | ||
335 | }; | ||
336 | void 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 | |||
22 | static 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 | |||
35 | int main(int argc, char **argv) { | ||
36 | #if 0 | ||
37 | { | ||
38 | //system("cat /proc/self/status"); | ||
39 | int i; | ||
40 | for (i = 0; i < argc; i++) | ||
41 | printf("*%s* ", argv[i]); | ||
42 | printf("\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) { | |||
120 | int net_create_macvlan(const char *dev, const char *parent, unsigned pid) { | 118 | int 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 |
185 | int net_move_interface(const char *dev, unsigned pid) { | 181 | int 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 @@ | |||
1 | all: fseccomp | ||
2 | |||
3 | prefix=@prefix@ | ||
4 | exec_prefix=@exec_prefix@ | ||
5 | libdir=@libdir@ | ||
6 | sysconfdir=@sysconfdir@ | ||
7 | |||
8 | VERSION=@PACKAGE_VERSION@ | ||
9 | NAME=@PACKAGE_NAME@ | ||
10 | HAVE_SECCOMP_H=@HAVE_SECCOMP_H@ | ||
11 | HAVE_SECCOMP=@HAVE_SECCOMP@ | ||
12 | HAVE_CHROOT=@HAVE_CHROOT@ | ||
13 | HAVE_BIND=@HAVE_BIND@ | ||
14 | HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@ | ||
15 | HAVE_NETWORK=@HAVE_NETWORK@ | ||
16 | HAVE_USERNS=@HAVE_USERNS@ | ||
17 | HAVE_X11=@HAVE_X11@ | ||
18 | HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@ | ||
19 | HAVE_WHITELIST=@HAVE_WHITELIST@ | ||
20 | HAVE_GLOBALCFG=@HAVE_GLOBALCFG@ | ||
21 | HAVE_APPARMOR=@HAVE_APPARMOR@ | ||
22 | HAVE_OVERLAYFS=@HAVE_OVERLAYFS@ | ||
23 | HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@ | ||
24 | EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@ | ||
25 | |||
26 | H_FILE_LIST = $(sort $(wildcard *.[h])) | ||
27 | C_FILE_LIST = $(sort $(wildcard *.c)) | ||
28 | OBJS = $(C_FILE_LIST:.c=.o) | ||
29 | BINOBJS = $(foreach file, $(OBJS), $file) | ||
30 | CFLAGS += -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 | ||
31 | LDFLAGS += -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 | |||
36 | fseccomp: $(OBJS) ../lib/libnetlink.o ../lib/common.o | ||
37 | $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) | ||
38 | |||
39 | clean:; rm -f *.o fseccomp | ||
40 | |||
41 | distclean: 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 | |||
25 | typedef struct { | ||
26 | char *name; | ||
27 | int nr; | ||
28 | } ErrnoEntry; | ||
29 | |||
30 | static 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 | |||
173 | int 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 | |||
184 | char *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 | |||
197 | void 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 | ||
29 | void syscall_print(void); | ||
30 | int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int arg), int fd, int arg); | ||
31 | int syscall_find_name(const char *name); | ||
32 | char *syscall_find_nr(int nr); | ||
33 | |||
34 | // errno.c | ||
35 | void errno_print(void); | ||
36 | int errno_find_name(const char *name); | ||
37 | char *errno_find_nr(int nr); | ||
38 | |||
39 | // protocol.c | ||
40 | void protocol_print(void); | ||
41 | void protocol_build_filter(const char *prlist, const char *fname); | ||
42 | |||
43 | // seccomp_secondary.c | ||
44 | void seccomp_secondary_64(const char *fname); | ||
45 | void seccomp_secondary_32(const char *fname); | ||
46 | |||
47 | // seccomp_file.c | ||
48 | void filter_init(int fd); | ||
49 | void filter_add_whitelist(int fd, int syscall, int arg); | ||
50 | void filter_add_blacklist(int fd, int syscall, int arg); | ||
51 | void filter_add_errno(int fd, int syscall, int arg); | ||
52 | void filter_end_blacklist(int fd); | ||
53 | void filter_end_whitelist(int fd); | ||
54 | |||
55 | // seccomp.c | ||
56 | // default list | ||
57 | void seccomp_default(const char *fname, int allow_debuggers); | ||
58 | // drop list | ||
59 | void seccomp_drop(const char *fname, char *list, int allow_debuggers); | ||
60 | // default+drop list | ||
61 | void seccomp_default_drop(const char *fname, char *list, int allow_debuggers); | ||
62 | // whitelisted filter | ||
63 | void seccomp_keep(const char *fname, char *list); | ||
64 | |||
65 | // seccomp_print | ||
66 | void 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 | |||
22 | static 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 | |||
40 | int main(int argc, char **argv) { | ||
41 | #if 0 | ||
42 | { | ||
43 | system("cat /proc/self/status"); | ||
44 | int i; | ||
45 | for (i = 0; i < argc; i++) | ||
46 | printf("*%s* ", argv[i]); | ||
47 | printf("\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 | |||
54 | static char *protocol[] = { | ||
55 | "unix", | ||
56 | "inet", | ||
57 | "inet6", | ||
58 | "netlink", | ||
59 | "packet", | ||
60 | NULL | ||
61 | }; | ||
62 | |||
63 | static 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 | ||
73 | struct sock_filter whitelist[] = { | ||
74 | WHITELIST(AF_UNIX) | ||
75 | }; | ||
76 | unsigned whitelist_len = sizeof(whitelist) / sizeof(struct sock_filter); | ||
77 | |||
78 | static 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 | |||
90 | void 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 | ||
105 | void 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 | ||
129 | printf("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 | } | ||
140 | printf("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 | ||
163 | printf("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 | ||
188 | printf("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 | |||
24 | static 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 | ||
198 | void 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 | ||
218 | void 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 | ||
242 | void 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 | |||
265 | void 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 | |||
24 | static 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 | |||
39 | void 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 | |||
70 | void 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 | |||
79 | void 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 | |||
88 | void 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 | |||
95 | void filter_end_blacklist(int fd) { | ||
96 | struct sock_filter filter[] = { | ||
97 | RETURN_ALLOW | ||
98 | }; | ||
99 | write_to_file(fd, filter, sizeof(filter)); | ||
100 | } | ||
101 | |||
102 | void 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 | |||
24 | static struct sock_filter *filter = NULL; | ||
25 | static int filter_cnt = 0; | ||
26 | |||
27 | static 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 | ||
61 | void 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 | |||
24 | void 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 | ||
105 | void 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 | ||
25 | typedef struct { | 23 | typedef 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 | ||
40 | const char *syscall_find_nr(int nr) { | 38 | // return -1 if error, or syscall number |
39 | int 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 | |||
50 | char *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 | 61 | void syscall_print(void) { |
52 | static 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 |
64 | int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg), int arg) { | 71 | int 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 | |||
105 | void 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); | |||
113 | int name2pid(const char *name, pid_t *pid); | 113 | int name2pid(const char *name, pid_t *pid); |
114 | char *pid_proc_comm(const pid_t pid); | 114 | char *pid_proc_comm(const pid_t pid); |
115 | char *pid_proc_cmdline(const pid_t pid); | 115 | char *pid_proc_cmdline(const pid_t pid); |
116 | int pid_proc_cmdline_x11(const pid_t pid); | 116 | int 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 |
204 | int pid_proc_cmdline_x11(const pid_t pid) { | 204 | int 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 | ||
16 | Wildcard patterns are accepted in the user name field: | ||
17 | |||
18 | user*: --private | ||
19 | |||
16 | .SH RESTRICTED SHELL | 20 | .SH RESTRICTED SHELL |
17 | To configure a restricted shell, replace /bin/bash with /usr/bin/firejail in | 21 | To 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. | |||
218 | Whitelist directory or file. A temporary file system is mounted on the top directory, and the | 218 | Whitelist directory or file. A temporary file system is mounted on the top directory, and the |
219 | whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent, | 219 | whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent, |
220 | everything else is discarded when the sandbox is closed. The top directory could be | 220 | everything else is discarded when the sandbox is closed. The top directory could be |
221 | user home, /dev, /media, /mnt, /opt, /var, and /tmp. | 221 | user 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 | |||
1622 | Whitelist directory or file. A temporary file system is mounted on the top directory, and the | 1622 | Whitelist directory or file. A temporary file system is mounted on the top directory, and the |
1623 | whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent, | 1623 | whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent, |
1624 | everything else is discarded when the sandbox is closed. The top directory could be | 1624 | everything else is discarded when the sandbox is closed. The top directory could be |
1625 | user home, /dev, /media, /mnt, /opt, /var, and /tmp. | 1625 | user 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 | |||
6 | export MALLOC_CHECK_=3 | ||
7 | export MALLOC_PERTURB_=$(($RANDOM % 255 + 1)) | ||
8 | |||
9 | which firefox | ||
10 | if [ "$?" -eq 0 ]; | ||
11 | then | ||
12 | echo "TESTING: firefox x11 xorg" | ||
13 | ./firefox.exp | ||
14 | else | ||
15 | echo "TESTING SKIP: firefox not found" | ||
16 | fi | ||
17 | |||
18 | which transmission-gtk | ||
19 | if [ "$?" -eq 0 ]; | ||
20 | then | ||
21 | echo "TESTING: transmission-gtk x11 xorg" | ||
22 | ./transmission-gtk.exp | ||
23 | else | ||
24 | echo "TESTING SKIP: transmission-gtk not found" | ||
25 | fi | ||
26 | |||
27 | which icedove | ||
28 | if [ "$?" -eq 0 ]; | ||
29 | then | ||
30 | echo "TESTING: icedove x11 xorg" | ||
31 | ./icedove.exp | ||
32 | else | ||
33 | echo "TESTING SKIP: icedove not found" | ||
34 | fi | ||
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 | |||
6 | set timeout 10 | ||
7 | spawn $env(SHELL) | ||
8 | match_max 100000 | ||
9 | |||
10 | send -- "firejail --name=test --x11=xorg firefox -no-remote www.gentoo.org\r" | ||
11 | sleep 10 | ||
12 | |||
13 | spawn $env(SHELL) | ||
14 | send -- "firejail --list\r" | ||
15 | expect { | ||
16 | timeout {puts "TESTING ERROR 3\n";exit} | ||
17 | ":firejail" | ||
18 | } | ||
19 | expect { | ||
20 | timeout {puts "TESTING ERROR 3.1\n";exit} | ||
21 | "firefox" {puts "firefox detected\n";} | ||
22 | "iceweasel" {puts "iceweasel detected\n";} | ||
23 | } | ||
24 | expect { | ||
25 | timeout {puts "TESTING ERROR 3.2\n";exit} | ||
26 | "no-remote" | ||
27 | } | ||
28 | sleep 1 | ||
29 | # grsecurity exit | ||
30 | send -- "file /proc/sys/kernel/grsecurity\r" | ||
31 | expect { | ||
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 | } | ||
36 | send -- "firejail --name=blablabla\r" | ||
37 | expect { | ||
38 | timeout {puts "TESTING ERROR 4\n";exit} | ||
39 | "Child process initialized" | ||
40 | } | ||
41 | sleep 2 | ||
42 | |||
43 | spawn $env(SHELL) | ||
44 | send -- "firemon --seccomp\r" | ||
45 | expect { | ||
46 | timeout {puts "TESTING ERROR 5\n";exit} | ||
47 | " firefox" {puts "firefox detected\n";} | ||
48 | " iceweasel" {puts "iceweasel detected\n";} | ||
49 | } | ||
50 | expect { | ||
51 | timeout {puts "TESTING ERROR 5.0\n";exit} | ||
52 | "no-remote" | ||
53 | } | ||
54 | expect { | ||
55 | timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit} | ||
56 | "Seccomp: 2" | ||
57 | } | ||
58 | expect { | ||
59 | timeout {puts "TESTING ERROR 5.1\n";exit} | ||
60 | "name=blablabla" | ||
61 | } | ||
62 | sleep 1 | ||
63 | send -- "firemon --caps\r" | ||
64 | expect { | ||
65 | timeout {puts "TESTING ERROR 6\n";exit} | ||
66 | " firefox" {puts "firefox detected\n";} | ||
67 | " iceweasel" {puts "iceweasel detected\n";} | ||
68 | } | ||
69 | expect { | ||
70 | timeout {puts "TESTING ERROR 6.0\n";exit} | ||
71 | "no-remote" | ||
72 | } | ||
73 | expect { | ||
74 | timeout {puts "TESTING ERROR 6.1\n";exit} | ||
75 | "CapBnd:" | ||
76 | } | ||
77 | expect { | ||
78 | timeout {puts "TESTING ERROR 6.2\n";exit} | ||
79 | "0000000000000000" | ||
80 | } | ||
81 | expect { | ||
82 | timeout {puts "TESTING ERROR 6.3\n";exit} | ||
83 | "name=blablabla" | ||
84 | } | ||
85 | sleep 1 | ||
86 | send -- "firejail --shutdown=test\r" | ||
87 | sleep 3 | ||
88 | |||
89 | puts "\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 | |||
6 | set timeout 10 | ||
7 | spawn $env(SHELL) | ||
8 | match_max 100000 | ||
9 | |||
10 | send -- "firejail --name=test --x11=xorg icedove\r" | ||
11 | sleep 10 | ||
12 | |||
13 | spawn $env(SHELL) | ||
14 | send -- "firejail --list\r" | ||
15 | expect { | ||
16 | timeout {puts "TESTING ERROR 3\n";exit} | ||
17 | ":firejail" | ||
18 | } | ||
19 | expect { | ||
20 | timeout {puts "TESTING ERROR 3.1\n";exit} | ||
21 | "icedove" | ||
22 | } | ||
23 | sleep 1 | ||
24 | |||
25 | # grsecurity exit | ||
26 | send -- "file /proc/sys/kernel/grsecurity\r" | ||
27 | expect { | ||
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 | |||
33 | send -- "firejail --name=blablabla\r" | ||
34 | expect { | ||
35 | timeout {puts "TESTING ERROR 4\n";exit} | ||
36 | "Child process initialized" | ||
37 | } | ||
38 | sleep 2 | ||
39 | |||
40 | spawn $env(SHELL) | ||
41 | send -- "firemon --seccomp\r" | ||
42 | expect { | ||
43 | timeout {puts "TESTING ERROR 5\n";exit} | ||
44 | ":firejail" | ||
45 | } | ||
46 | expect { | ||
47 | timeout {puts "TESTING ERROR 5.0\n";exit} | ||
48 | "icedove" | ||
49 | } | ||
50 | expect { | ||
51 | timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit} | ||
52 | "Seccomp: 2" | ||
53 | } | ||
54 | expect { | ||
55 | timeout {puts "TESTING ERROR 5.1\n";exit} | ||
56 | "name=blablabla" | ||
57 | } | ||
58 | sleep 2 | ||
59 | send -- "firemon --caps\r" | ||
60 | expect { | ||
61 | timeout {puts "TESTING ERROR 6\n";exit} | ||
62 | ":firejail" | ||
63 | } | ||
64 | expect { | ||
65 | timeout {puts "TESTING ERROR 6.0\n";exit} | ||
66 | "icedove" | ||
67 | } | ||
68 | expect { | ||
69 | timeout {puts "TESTING ERROR 6.1\n";exit} | ||
70 | "CapBnd" | ||
71 | } | ||
72 | expect { | ||
73 | timeout {puts "TESTING ERROR 6.2\n";exit} | ||
74 | "0000000000000000" | ||
75 | } | ||
76 | expect { | ||
77 | timeout {puts "TESTING ERROR 6.3\n";exit} | ||
78 | "name=blablabla" | ||
79 | } | ||
80 | sleep 1 | ||
81 | send -- "firejail --shutdown=test\r" | ||
82 | sleep 3 | ||
83 | |||
84 | puts "\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 | |||
6 | set timeout 10 | ||
7 | spawn $env(SHELL) | ||
8 | match_max 100000 | ||
9 | |||
10 | send -- "firejail --name=test --x11=xorg transmission-gtk\r" | ||
11 | sleep 10 | ||
12 | |||
13 | spawn $env(SHELL) | ||
14 | send -- "firejail --list\r" | ||
15 | expect { | ||
16 | timeout {puts "TESTING ERROR 3\n";exit} | ||
17 | ":firejail" | ||
18 | } | ||
19 | expect { | ||
20 | timeout {puts "TESTING ERROR 3.1\n";exit} | ||
21 | "transmission-gtk" | ||
22 | } | ||
23 | sleep 1 | ||
24 | |||
25 | # grsecurity exit | ||
26 | send -- "file /proc/sys/kernel/grsecurity\r" | ||
27 | expect { | ||
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 | |||
33 | send -- "firejail --name=blablabla\r" | ||
34 | expect { | ||
35 | timeout {puts "TESTING ERROR 4\n";exit} | ||
36 | "Child process initialized" | ||
37 | } | ||
38 | sleep 2 | ||
39 | |||
40 | spawn $env(SHELL) | ||
41 | send -- "firemon --seccomp\r" | ||
42 | expect { | ||
43 | timeout {puts "TESTING ERROR 5\n";exit} | ||
44 | ":firejail" | ||
45 | } | ||
46 | expect { | ||
47 | timeout {puts "TESTING ERROR 5.0\n";exit} | ||
48 | "transmission-gtk" | ||
49 | } | ||
50 | expect { | ||
51 | timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit} | ||
52 | "Seccomp: 2" | ||
53 | } | ||
54 | expect { | ||
55 | timeout {puts "TESTING ERROR 5.1\n";exit} | ||
56 | "name=blablabla" | ||
57 | } | ||
58 | sleep 1 | ||
59 | send -- "firemon --caps\r" | ||
60 | expect { | ||
61 | timeout {puts "TESTING ERROR 6\n";exit} | ||
62 | ":firejail" | ||
63 | } | ||
64 | expect { | ||
65 | timeout {puts "TESTING ERROR 6.0\n";exit} | ||
66 | "transmission-gtk" | ||
67 | } | ||
68 | expect { | ||
69 | timeout {puts "TESTING ERROR 6.1\n";exit} | ||
70 | "CapBnd" | ||
71 | } | ||
72 | expect { | ||
73 | timeout {puts "TESTING ERROR 6.2\n";exit} | ||
74 | "0000000000000000" | ||
75 | } | ||
76 | expect { | ||
77 | timeout {puts "TESTING ERROR 6.3\n";exit} | ||
78 | "name=blablabla" | ||
79 | } | ||
80 | sleep 1 | ||
81 | send -- "firejail --shutdown=test\r" | ||
82 | sleep 3 | ||
83 | |||
84 | puts "\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 | } |
13 | expect { | 13 | expect { |
14 | timeout {puts "TESTING ERROR 1\n";exit} | 14 | timeout {puts "TESTING ERROR 1\n";exit} |
15 | "exited with 0" | 15 | "ioctl" |
16 | } | ||
17 | expect { | ||
18 | timeout {puts "TESTING ERROR 2\n";exit} | ||
19 | "exit_group" | ||
16 | } | 20 | } |
17 | after 100 | 21 | after 100 |
18 | 22 | ||
19 | send -- "firejail --allow-debuggers --profile=/etc/firejail/firefox.profile strace ls\r" | 23 | send -- "firejail --allow-debuggers --profile=/etc/firejail/firefox.profile strace ls\r" |
20 | expect { | 24 | expect { |
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 | } |
24 | expect { | 28 | expect { |
25 | timeout {puts "TESTING ERROR 3\n";exit} | 29 | timeout {puts "TESTING ERROR 4\n";exit} |
26 | "exited with 0" | 30 | "ioctl" |
31 | } | ||
32 | expect { | ||
33 | timeout {puts "TESTING ERROR 5\n";exit} | ||
34 | "exit_group" | ||
27 | } | 35 | } |
28 | after 100 | 36 | after 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)" | |||
12 | echo "TESTING: capabilities (test/filters/caps.exp)" | 12 | echo "TESTING: capabilities (test/filters/caps.exp)" |
13 | ./caps.exp | 13 | ./caps.exp |
14 | 14 | ||
15 | rm -f seccomp-test-file | ||
16 | if [ "$(uname -m)" = "x86_64" ]; then | ||
17 | echo "TESTING: fseccomp (test/filters/fseccomp.exp)" | ||
18 | ./fseccomp.exp | ||
19 | else | ||
20 | echo "TESTING SKIP: fseccomp test implemented only for x86_64" | ||
21 | fi | ||
22 | rm -f seccomp-test-file | ||
23 | |||
24 | |||
15 | if [ "$(uname -m)" = "x86_64" ]; then | 25 | if [ "$(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 |
18 | else | 28 | else |
19 | echo "TESTING SKIP: protocol, not running on x86_64" | 29 | echo "TESTING SKIP: protocol, running only on x86_64" |
20 | fi | 30 | fi |
21 | 31 | ||
22 | echo "TESTING: seccomp bad empty (test/filters/seccomp-bad-empty.exp)" | 32 | echo "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 | |||
50 | echo "TESTING: seccomp empty (test/filters/seccomp-empty.exp)" | 60 | echo "TESTING: seccomp empty (test/filters/seccomp-empty.exp)" |
51 | ./seccomp-empty.exp | 61 | ./seccomp-empty.exp |
52 | 62 | ||
53 | echo "TESTING: seccomp bad empty (test/filters/seccomp-bad-empty.exp)" | ||
54 | ./seccomp-bad-empty.exp | ||
55 | |||
56 | if [ "$(uname -m)" = "x86_64" ]; then | 63 | if [ "$(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 | |||
6 | set timeout 10 | ||
7 | spawn $env(SHELL) | ||
8 | match_max 100000 | ||
9 | |||
10 | after 100 | ||
11 | send -- "/usr/lib/firejail/fseccomp debug-syscalls\r" | ||
12 | expect { | ||
13 | timeout {puts "TESTING ERROR 1\n";exit} | ||
14 | "1 - write" | ||
15 | } | ||
16 | |||
17 | after 100 | ||
18 | send -- "/usr/lib/firejail/fseccomp debug-errnos\r" | ||
19 | expect { | ||
20 | timeout {puts "TESTING ERROR 2\n";exit} | ||
21 | "1 - EPERM" | ||
22 | } | ||
23 | |||
24 | after 100 | ||
25 | send -- "/usr/lib/firejail/fseccomp debug-protocols\r" | ||
26 | expect { | ||
27 | timeout {puts "TESTING ERROR 3\n";exit} | ||
28 | "unix, inet, inet6, netlink, packet," | ||
29 | } | ||
30 | |||
31 | after 100 | ||
32 | send -- "/usr/lib/firejail/fseccomp protocol build unix,inet seccomp-test-file\r" | ||
33 | after 100 | ||
34 | send -- "/usr/lib/firejail/fseccomp print seccomp-test-file\r" | ||
35 | expect { | ||
36 | timeout {puts "TESTING ERROR 4.1\n";exit} | ||
37 | "WHITELIST 41 socket" | ||
38 | } | ||
39 | |||
40 | after 100 | ||
41 | send -- "/usr/lib/firejail/fseccomp secondary 64 seccomp-test-file\r" | ||
42 | after 100 | ||
43 | send -- "/usr/lib/firejail/fseccomp print seccomp-test-file\r" | ||
44 | expect { | ||
45 | timeout {puts "TESTING ERROR 5.1\n";exit} | ||
46 | "BLACKLIST 165 mount" | ||
47 | } | ||
48 | expect { | ||
49 | timeout {puts "TESTING ERROR 5.2\n";exit} | ||
50 | "BLACKLIST 166 umount2" | ||
51 | } | ||
52 | expect { | ||
53 | timeout {puts "TESTING ERROR 5.3\n";exit} | ||
54 | "RETURN_ALLOW" | ||
55 | } | ||
56 | |||
57 | after 100 | ||
58 | send -- "/usr/lib/firejail/fseccomp default seccomp-test-file\r" | ||
59 | after 100 | ||
60 | send -- "/usr/lib/firejail/fseccomp print seccomp-test-file\r" | ||
61 | expect { | ||
62 | timeout {puts "TESTING ERROR 6.1\n";exit} | ||
63 | "BLACKLIST 165 mount" | ||
64 | } | ||
65 | expect { | ||
66 | timeout {puts "TESTING ERROR 6.2\n";exit} | ||
67 | "BLACKLIST 166 umount2" | ||
68 | } | ||
69 | expect { | ||
70 | timeout {puts "TESTING ERROR 6.3\n";exit} | ||
71 | "RETURN_ALLOW" | ||
72 | } | ||
73 | |||
74 | after 100 | ||
75 | send -- "/usr/lib/firejail/fseccomp drop seccomp-test-file chmod,chown\r" | ||
76 | after 100 | ||
77 | send -- "/usr/lib/firejail/fseccomp print seccomp-test-file\r" | ||
78 | expect { | ||
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 | } | ||
84 | expect { | ||
85 | timeout {puts "TESTING ERROR 7.4\n";exit} | ||
86 | "BLACKLIST 92 chown" | ||
87 | } | ||
88 | expect { | ||
89 | timeout {puts "TESTING ERROR 7.5\n";exit} | ||
90 | "RETURN_ALLOW" | ||
91 | } | ||
92 | |||
93 | after 100 | ||
94 | send -- "/usr/lib/firejail/fseccomp default drop seccomp-test-file chmod,chown\r" | ||
95 | after 100 | ||
96 | send -- "/usr/lib/firejail/fseccomp print seccomp-test-file\r" | ||
97 | expect { | ||
98 | timeout {puts "TESTING ERROR 8.1\n";exit} | ||
99 | "BLACKLIST 165 mount" | ||
100 | } | ||
101 | expect { | ||
102 | timeout {puts "TESTING ERROR 8.2\n";exit} | ||
103 | "BLACKLIST 166 umount2" | ||
104 | } | ||
105 | expect { | ||
106 | timeout {puts "TESTING ERROR 8.3\n";exit} | ||
107 | "BLACKLIST 90 chmod" | ||
108 | } | ||
109 | expect { | ||
110 | timeout {puts "TESTING ERROR 8.4\n";exit} | ||
111 | "BLACKLIST 92 chown" | ||
112 | } | ||
113 | expect { | ||
114 | timeout {puts "TESTING ERROR 8.5\n";exit} | ||
115 | "RETURN_ALLOW" | ||
116 | } | ||
117 | after 100 | ||
118 | send -- "/usr/lib/firejail/fseccomp keep seccomp-test-file chmod,chown\r" | ||
119 | after 100 | ||
120 | send -- "/usr/lib/firejail/fseccomp print seccomp-test-file\r" | ||
121 | expect { | ||
122 | timeout {puts "TESTING ERROR 9.1\n";exit} | ||
123 | "WHITELIST 90 chmod" | ||
124 | } | ||
125 | expect { | ||
126 | timeout {puts "TESTING ERROR 9.2\n";exit} | ||
127 | "WHITELIST 92 chown" | ||
128 | } | ||
129 | expect { | ||
130 | timeout {puts "TESTING ERROR 9.3\n";exit} | ||
131 | "KILL_PROCESS" | ||
132 | } | ||
133 | |||
134 | |||
135 | |||
136 | after 100 | ||
137 | puts "\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 | } |
47 | send -- "sudo -s\r" | 47 | send -- "sudo -s\r" |
48 | expect { | 48 | expect { |
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 | } |
54 | send -- "cat /proc/self/uid_map | wc -l\r" | 54 | send -- "cat /proc/self/uid_map | wc -l\r" |
55 | expect { | 55 | expect { |
56 | timeout {puts "TESTING ERROR 7\n";exit} | 56 | timeout {puts "TESTING ERROR 8\n";exit} |
57 | "1" | 57 | "1" |
58 | } | 58 | } |
59 | send -- "cat /proc/self/gid_map | wc -l\r" | 59 | send -- "cat /proc/self/gid_map | wc -l\r" |
60 | expect { | 60 | expect { |
61 | timeout {puts "TESTING ERROR 8\n";exit} | 61 | timeout {puts "TESTING ERROR 9\n";exit} |
62 | "3" | 62 | "5" |
63 | } | 63 | } |
64 | 64 | ||
65 | puts "\n" | 65 | puts "\n" |
@@ -70,59 +70,59 @@ sleep 2 | |||
70 | 70 | ||
71 | send -- "firejail --name=test --noroot --noprofile\r" | 71 | send -- "firejail --name=test --noroot --noprofile\r" |
72 | expect { | 72 | expect { |
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 | } |
76 | sleep 1 | 76 | sleep 1 |
77 | 77 | ||
78 | send -- "cat /proc/self/status\r" | 78 | send -- "cat /proc/self/status\r" |
79 | expect { | 79 | expect { |
80 | timeout {puts "TESTING ERROR 10\n";exit} | 80 | timeout {puts "TESTING ERROR 11\n";exit} |
81 | "CapBnd:" | 81 | "CapBnd:" |
82 | } | 82 | } |
83 | expect { | 83 | expect { |
84 | timeout {puts "TESTING ERROR 11\n";exit} | 84 | timeout {puts "TESTING ERROR 12\n";exit} |
85 | "ffffffff" | 85 | "ffffffff" |
86 | } | 86 | } |
87 | expect { | 87 | expect { |
88 | timeout {puts "TESTING ERROR 12\n";exit} | 88 | timeout {puts "TESTING ERROR 13\n";exit} |
89 | "Seccomp:" | 89 | "Seccomp:" |
90 | } | 90 | } |
91 | expect { | 91 | expect { |
92 | timeout {puts "TESTING ERROR 13\n";exit} | 92 | timeout {puts "TESTING ERROR 14\n";exit} |
93 | "0" | 93 | "0" |
94 | } | 94 | } |
95 | expect { | 95 | expect { |
96 | timeout {puts "TESTING ERROR 14\n";exit} | 96 | timeout {puts "TESTING ERROR 15\n";exit} |
97 | "Cpus_allowed:" | 97 | "Cpus_allowed:" |
98 | } | 98 | } |
99 | puts "\n" | 99 | puts "\n" |
100 | 100 | ||
101 | send -- "whoami\r" | 101 | send -- "whoami\r" |
102 | expect { | 102 | expect { |
103 | timeout {puts "TESTING ERROR 15\n";exit} | 103 | timeout {puts "TESTING ERROR 16\n";exit} |
104 | $env(USER) | 104 | $env(USER) |
105 | } | 105 | } |
106 | send -- "sudo -s\r" | 106 | send -- "sudo -s\r" |
107 | expect { | 107 | expect { |
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 | } |
112 | send -- "ping 0\r" | 112 | send -- "ping 0\r" |
113 | expect { | 113 | expect { |
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 | } |
117 | send -- "cat /proc/self/uid_map | wc -l\r" | 117 | send -- "cat /proc/self/uid_map | wc -l\r" |
118 | expect { | 118 | expect { |
119 | timeout {puts "TESTING ERROR 18\n";exit} | 119 | timeout {puts "TESTING ERROR 19\n";exit} |
120 | "1" | 120 | "1" |
121 | } | 121 | } |
122 | send -- "cat /proc/self/gid_map | wc -l\r" | 122 | send -- "cat /proc/self/gid_map | wc -l\r" |
123 | expect { | 123 | expect { |
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 { | |||
130 | spawn $env(SHELL) | 130 | spawn $env(SHELL) |
131 | send -- "firejail --debug --join=test\r" | 131 | send -- "firejail --debug --join=test\r" |
132 | expect { | 132 | expect { |
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 | } |
136 | expect { | 136 | expect { |
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 | } |
140 | sleep 1 | 140 | sleep 1 |
141 | 141 | ||
142 | send -- "sudo -s\r" | 142 | send -- "sudo -s\r" |
143 | expect { | 143 | expect { |
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 | } |
149 | send -- "cat /proc/self/uid_map | wc -l\r" | 149 | send -- "cat /proc/self/uid_map | wc -l\r" |
150 | expect { | 150 | expect { |
151 | timeout {puts "TESTING ERROR 23\n";exit} | 151 | timeout {puts "TESTING ERROR 24\n";exit} |
152 | "1" | 152 | "1" |
153 | } | 153 | } |
154 | send -- "cat /proc/self/gid_map | wc -l\r" | 154 | send -- "cat /proc/self/gid_map | wc -l\r" |
155 | expect { | 155 | expect { |
156 | timeout {puts "TESTING ERROR 24\n";exit} | 156 | timeout {puts "TESTING ERROR 25\n";exit} |
157 | "3" | 157 | "5" |
158 | } | 158 | } |
159 | after 100 | 159 | after 100 |
160 | puts "\nall done\n" | 160 | puts "\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 @@ | |||
6 | export MALLOC_CHECK_=3 | 6 | export MALLOC_CHECK_=3 |
7 | export MALLOC_PERTURB_=$(($RANDOM % 255 + 1)) | 7 | export MALLOC_PERTURB_=$(($RANDOM % 255 + 1)) |
8 | 8 | ||
9 | echo "TESTING: /sys/fs access (test/fs/sys_fs.exp)" | ||
10 | ./sys_fs.exp | ||
11 | |||
9 | echo "TESTING: kmsg access (test/fs/kmsg.exp)" | 12 | echo "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 | |||
6 | set timeout 10 | ||
7 | spawn $env(SHELL) | ||
8 | match_max 100000 | ||
9 | |||
10 | send -- "firejail\r" | ||
11 | expect { | ||
12 | timeout {puts "TESTING ERROR 1\n";exit} | ||
13 | "Child process initialized" | ||
14 | } | ||
15 | sleep 1 | ||
16 | |||
17 | send -- "ls /sys/fs\r" | ||
18 | expect { | ||
19 | timeout {puts "TESTING ERROR 2\n";exit} | ||
20 | "Permission denied" | ||
21 | } | ||
22 | after 100 | ||
23 | |||
24 | send -- "exit\r" | ||
25 | sleep 1 | ||
26 | |||
27 | send -- "firejail --noblacklist=/sys/fs\r" | ||
28 | expect { | ||
29 | timeout {puts "TESTING ERROR 1\n";exit} | ||
30 | "Child process initialized" | ||
31 | } | ||
32 | sleep 1 | ||
33 | |||
34 | send -- "ls /sys/fs\r" | ||
35 | expect { | ||
36 | timeout {puts "TESTING ERROR 2\n";exit} | ||
37 | "cgroup" | ||
38 | } | ||
39 | after 100 | ||
40 | send -- "exit\r" | ||
41 | after 100 | ||
42 | |||
43 | puts "\nall done\n" | ||
44 | |||