diff options
-rw-r--r-- | README | 12 | ||||
-rw-r--r-- | README.md | 26 | ||||
-rw-r--r-- | RELNOTES | 15 | ||||
-rw-r--r-- | etc/Cryptocat.profile | 2 | ||||
-rw-r--r-- | etc/disable-common.inc | 24 | ||||
-rw-r--r-- | etc/disable-programs.inc | 9 | ||||
-rw-r--r-- | etc/gnome-mplayer.profile | 2 | ||||
-rw-r--r-- | etc/login.users | 6 | ||||
-rw-r--r-- | etc/start-tor-browser.profile | 2 | ||||
-rw-r--r-- | etc/uudeview.profile | 2 | ||||
-rw-r--r-- | etc/uzbl-browser.profile | 29 | ||||
-rw-r--r-- | etc/vlc.profile | 2 | ||||
-rw-r--r-- | etc/xmms.profile | 18 | ||||
-rw-r--r-- | platform/debian/conffiles | 2 | ||||
-rw-r--r-- | src/bash_completion/firejail.bash_completion | 4 | ||||
-rw-r--r-- | src/firejail/firejail.h | 12 | ||||
-rw-r--r-- | src/firejail/fs.c | 21 | ||||
-rw-r--r-- | src/firejail/fs_etc.c | 4 | ||||
-rw-r--r-- | src/firejail/fs_hostname.c | 51 | ||||
-rw-r--r-- | src/firejail/main.c | 19 | ||||
-rw-r--r-- | src/firejail/netns.c | 114 | ||||
-rw-r--r-- | src/firejail/profile.c | 14 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 62 | ||||
-rw-r--r-- | src/firejail/usage.c | 2 | ||||
-rw-r--r-- | src/firejail/util.c | 91 | ||||
-rw-r--r-- | src/man/firejail-profile.txt | 11 | ||||
-rw-r--r-- | src/man/firejail.txt | 30 |
27 files changed, 513 insertions, 73 deletions
@@ -83,6 +83,7 @@ Fred-Barclay (https://github.com/Fred-Barclay) | |||
83 | - added xed and pluma profiles | 83 | - added xed and pluma profiles |
84 | - added Cryptocat profile | 84 | - added Cryptocat profile |
85 | - added wireshark profile | 85 | - added wireshark profile |
86 | - uudeview profile fix | ||
86 | valoq (https://github.com/valoq) | 87 | valoq (https://github.com/valoq) |
87 | - lots of profile fixes | 88 | - lots of profile fixes |
88 | - added support for /srv in --whitelist feature | 89 | - added support for /srv in --whitelist feature |
@@ -97,6 +98,14 @@ valoq (https://github.com/valoq) | |||
97 | - added skanlite, ssh-agent, transmission-cli, tracker, transmission-show, w3m, xfburn, xpra profiles | 98 | - added skanlite, ssh-agent, transmission-cli, tracker, transmission-show, w3m, xfburn, xpra profiles |
98 | - added wget profile | 99 | - added wget profile |
99 | - disable gnupg and systemd directories under /run/user | 100 | - disable gnupg and systemd directories under /run/user |
101 | Igor Bukanov (https://github.com/ibukanov) | ||
102 | - found/fiixed privilege escalation in --hosts-file option | ||
103 | Cat (https://github.com/ecat3) | ||
104 | - prevent tmux connecting to an existing session | ||
105 | Zack Weinberg (https://github.com/zackw) | ||
106 | - sdded support for joining a persistent, named network namespace | ||
107 | GSI (https://github.com/GSI) | ||
108 | - added Uzbl browser profile | ||
100 | Mike Frysinger (vapier@gentoo.org) | 109 | Mike Frysinger (vapier@gentoo.org) |
101 | - Gentoo compile patch | 110 | - Gentoo compile patch |
102 | Jericho (https://github.com/attritionorg) | 111 | Jericho (https://github.com/attritionorg) |
@@ -113,6 +122,7 @@ thewisenerd (https://github.com/thewisenerd) | |||
113 | SYN-cook (https://github.com/SYN-cook) | 122 | SYN-cook (https://github.com/SYN-cook) |
114 | - keepass/keepassx browser fixes | 123 | - keepass/keepassx browser fixes |
115 | - disable-common.inc fixes | 124 | - disable-common.inc fixes |
125 | - blacklist GNOME keyring and Konqueror | ||
116 | thewisenerd (https://github.com/thewisenerd) | 126 | thewisenerd (https://github.com/thewisenerd) |
117 | - appimage: pass commandline arguments | 127 | - appimage: pass commandline arguments |
118 | KOLANICH (https://github.com/KOLANICH) | 128 | KOLANICH (https://github.com/KOLANICH) |
@@ -224,6 +234,8 @@ KellerFuchs (https://github.com/KellerFuchs) | |||
224 | - disable-common.inc additions | 234 | - disable-common.inc additions |
225 | - make mutt and msmtp's rc files read-only | 235 | - make mutt and msmtp's rc files read-only |
226 | - added support for .local profile files in /etc/firejail | 236 | - added support for .local profile files in /etc/firejail |
237 | - fixed Cryptocat profile | ||
238 | - make ~/.local read-only | ||
227 | ValdikSS (https://github.com/ValdikSS) | 239 | ValdikSS (https://github.com/ValdikSS) |
228 | - Psi+, Corebird, Konversation profiles | 240 | - Psi+, Corebird, Konversation profiles |
229 | - various profile fixes | 241 | - various profile fixes |
@@ -51,7 +51,9 @@ Use this issue to request new profiles: https://github.com/netblue30/firejail/is | |||
51 | ````` | 51 | ````` |
52 | 52 | ||
53 | ````` | 53 | ````` |
54 | ## AppImage type 2 support | 54 | ## AppImage |
55 | |||
56 | Added AppImage type 2 support, and support for passing command line arguments to appimages. | ||
55 | ````` | 57 | ````` |
56 | 58 | ||
57 | ````` | 59 | ````` |
@@ -75,9 +77,9 @@ Use this issue to request new profiles: https://github.com/netblue30/firejail/is | |||
75 | Example: | 77 | Example: |
76 | # firejail --private-srv=www /etc/init.d/apache2 start | 78 | # firejail --private-srv=www /etc/init.d/apache2 start |
77 | 79 | ||
78 | --machine-id | 80 | --machine-id |
79 | Preserve id number in /etc/machine-id file. By default a new | 81 | Spoof id number in /etc/machine-id file - a new random id is |
80 | random id is generated inside the sandbox. | 82 | generated inside the sandbox. |
81 | 83 | ||
82 | Example: | 84 | Example: |
83 | $ firejail --machine-id | 85 | $ firejail --machine-id |
@@ -89,7 +91,21 @@ Use this issue to request new profiles: https://github.com/netblue30/firejail/is | |||
89 | Example: | 91 | Example: |
90 | $ firejail --allow-private-blacklist --private=~/priv-dir | 92 | $ firejail --allow-private-blacklist --private=~/priv-dir |
91 | --blacklist=~/.mozilla | 93 | --blacklist=~/.mozilla |
94 | |||
95 | --hosts-file=file | ||
96 | Use file as /etc/hosts. | ||
97 | |||
98 | Example: | ||
99 | $ firejail --hosts-file=~/myhosts firefox | ||
92 | 100 | ||
101 | --writable-var-log | ||
102 | Use the real /var/log directory, not a clone. By default, a | ||
103 | tmpfs is mounted on top of /var/log directory, and a skeleton | ||
104 | filesystem is created based on the original /var/log. | ||
105 | |||
106 | Example: | ||
107 | $ sudo firejail --writable-var-log | ||
108 | |||
93 | ````` | 109 | ````` |
94 | ## New Profiles | 110 | ## New Profiles |
95 | xiphos, Tor Browser Bundle, display (imagemagik), Wire, mumble, zoom, Guayadeque, qemu, keypass2, | 111 | xiphos, Tor Browser Bundle, display (imagemagik), Wire, mumble, zoom, Guayadeque, qemu, keypass2, |
@@ -98,5 +114,5 @@ gjs, gnome-books, gnome-clocks, gnome-documents, gnome-maps, gnome-music, gnome- | |||
98 | goobox, gpa, gpg, gpg-agent, highlight, img2txt, k3b, kate, lynx, mediainfo, nautilus, odt2txt, pdftotext, | 114 | goobox, gpa, gpg, gpg-agent, highlight, img2txt, k3b, kate, lynx, mediainfo, nautilus, odt2txt, pdftotext, |
99 | simple-scan, skanlite, ssh-agent, tracker, transmission-cli, transmission-show, w3m, xfburn, xpra, wget, | 115 | simple-scan, skanlite, ssh-agent, tracker, transmission-cli, transmission-show, w3m, xfburn, xpra, wget, |
100 | xed, pluma, Cryptocat, Bless, Gnome 2048, Gnome Calculator, Gnome Contacts, JD-GUI, Lollypop, MultiMC5, | 116 | xed, pluma, Cryptocat, Bless, Gnome 2048, Gnome Calculator, Gnome Contacts, JD-GUI, Lollypop, MultiMC5, |
101 | PDFSam, Pithos, Xonotic, wireshark, keepassx2, QupZilla, FossaMail | 117 | PDFSam, Pithos, Xonotic, wireshark, keepassx2, QupZilla, FossaMail, Uzbl browser, xmms |
102 | 118 | ||
@@ -14,23 +14,26 @@ firejail (0.9.45) baseline; urgency=low | |||
14 | * security: split file copying in private option in a separate executable | 14 | * security: split file copying in private option in a separate executable |
15 | * security: root exploit found by Sebastian Krahmer (CVE-2017-5180) | 15 | * security: root exploit found by Sebastian Krahmer (CVE-2017-5180) |
16 | * feature: disable gnupg and systemd directories under /run/user | 16 | * feature: disable gnupg and systemd directories under /run/user |
17 | * feature: allow root user access to /dev/shm (--noblacklist=/dev/shm) | ||
18 | * feature: AppImage type 2 support | ||
19 | * feature: test coverage (gcov) support | 17 | * feature: test coverage (gcov) support |
18 | * feature: allow root user access to /dev/shm (--noblacklist=/dev/shm) | ||
20 | * feature: private /opt directory (--private-opt, profile support) | 19 | * feature: private /opt directory (--private-opt, profile support) |
21 | * feature: private /srv directory (--private-srv, profile support) | 20 | * feature: private /srv directory (--private-srv, profile support) |
22 | * feature: spoof machine-id | 21 | * feature: spoof machine-id (--machine-id, profile support) |
22 | * feature: allow blacklists under --private (--allow-private-blacklist, profile support) | ||
23 | * feature: user-defined /etc/hosts file (--hosts-file, profile support) | ||
24 | * feature: support for the real /var/log directory (--writable-var-log, profile support) | ||
23 | * feature: config support for firejail prompt in terminals | 25 | * feature: config support for firejail prompt in terminals |
26 | * feature: AppImage type 2 support | ||
24 | * feature: pass command line arguments to appimages | 27 | * feature: pass command line arguments to appimages |
25 | * feature: --allow-private-blacklist option | 28 | * feature: allow non-seccomp setup for OverlayFS sandboxes - more work to come |
26 | * feature: allow non-seccomp setup for OverlayFS sandboxes | ||
27 | * feature: added a number o Python scripts for handling sandboxes | 29 | * feature: added a number o Python scripts for handling sandboxes |
28 | * feature: allow local customization using .local files under /etc/firejail | 30 | * feature: allow local customization using .local files under /etc/firejail |
29 | * new profiles: xiphos, Tor Browser Bundle, display (imagemagik), Wire, | 31 | * new profiles: xiphos, Tor Browser Bundle, display (imagemagik), Wire, |
30 | * new profiles: mumble, zoom, Guayadeque, qemu, keypass2, xed, pluma, | 32 | * new profiles: mumble, zoom, Guayadeque, qemu, keypass2, xed, pluma, |
31 | * new profiles: Cryptocat, Bless, Gnome 2048, Gnome Calculator, | 33 | * new profiles: Cryptocat, Bless, Gnome 2048, Gnome Calculator, |
32 | * new profiles: Gnome Contacts, JD-GUI, Lollypop, MultiMC5, PDFSam, Pithos, | 34 | * new profiles: Gnome Contacts, JD-GUI, Lollypop, MultiMC5, PDFSam, Pithos, |
33 | * new profies: Xonotic, wireshark, keepassx2, QupZilla, FossaMail | 35 | * new profies: Xonotic, wireshark, keepassx2, QupZilla, FossaMail, |
36 | * new profiles: Uzbl browser | ||
34 | * bugfixes | 37 | * bugfixes |
35 | -- netblue30 <netblue30@yahoo.com> Sun, 23 Oct 2016 08:00:00 -0500 | 38 | -- netblue30 <netblue30@yahoo.com> Sun, 23 Oct 2016 08:00:00 -0500 |
36 | 39 | ||
diff --git a/etc/Cryptocat.profile b/etc/Cryptocat.profile index 3db34c03c..b61b88f68 100644 --- a/etc/Cryptocat.profile +++ b/etc/Cryptocat.profile | |||
@@ -1,4 +1,4 @@ | |||
1 | # Firejail profile for | 1 | # Firejail profile for Cryptocat |
2 | noblacklist ${HOME}/.config/Cryptocat | 2 | noblacklist ${HOME}/.config/Cryptocat |
3 | 3 | ||
4 | include /etc/firejail/disable-common.inc | 4 | include /etc/firejail/disable-common.inc |
diff --git a/etc/disable-common.inc b/etc/disable-common.inc index 5a281a91f..64a39296e 100644 --- a/etc/disable-common.inc +++ b/etc/disable-common.inc | |||
@@ -75,12 +75,9 @@ blacklist /etc/profile.d | |||
75 | blacklist /etc/rc.local | 75 | blacklist /etc/rc.local |
76 | blacklist /etc/anacrontab | 76 | blacklist /etc/anacrontab |
77 | 77 | ||
78 | # General startup files | 78 | # Startup files |
79 | read-only ${HOME}/.xinitrc | 79 | read-only ${HOME}/.xinitrc |
80 | read-only ${HOME}/.xserverrc | 80 | read-only ${HOME}/.xserverrc |
81 | read-only ${HOME}/.profile | ||
82 | |||
83 | # Shell startup files | ||
84 | read-only ${HOME}/.antigen | 81 | read-only ${HOME}/.antigen |
85 | read-only ${HOME}/.bash_login | 82 | read-only ${HOME}/.bash_login |
86 | read-only ${HOME}/.bashrc | 83 | read-only ${HOME}/.bashrc |
@@ -99,6 +96,12 @@ read-only ${HOME}/.tcshrc | |||
99 | read-only ${HOME}/.cshrc | 96 | read-only ${HOME}/.cshrc |
100 | read-only ${HOME}/.csh_files | 97 | read-only ${HOME}/.csh_files |
101 | read-only ${HOME}/.profile | 98 | read-only ${HOME}/.profile |
99 | read-only ${HOME}/.forward | ||
100 | read-only ${HOME}/.login | ||
101 | read-only ${HOME}/.logout | ||
102 | read-only ${HOME}/.pgpkey | ||
103 | read-only ${HOME}/.plan | ||
104 | read-only ${HOME}/.project | ||
102 | 105 | ||
103 | # Initialization files that allow arbitrary command execution | 106 | # Initialization files that allow arbitrary command execution |
104 | read-only ${HOME}/.caffrc | 107 | read-only ${HOME}/.caffrc |
@@ -124,8 +127,16 @@ read-only ${HOME}/.reportbugrc | |||
124 | read-only ${HOME}/.xmonad | 127 | read-only ${HOME}/.xmonad |
125 | read-only ${HOME}/.xscreensaver | 128 | read-only ${HOME}/.xscreensaver |
126 | 129 | ||
127 | # The user ~/bin directory can override commands such as ls | 130 | # Make directories commonly found in $PATH read-only |
128 | read-only ${HOME}/bin | 131 | read-only ${HOME}/bin |
132 | read-only ${HOME}/.gem | ||
133 | read-only ${HOME}/.luarocks | ||
134 | read-only ${HOME}/.npm-packages | ||
135 | |||
136 | # Make the contents of ~/.local read-only, | ||
137 | # except the commonly-used ~/.local/share | ||
138 | read-only ${HOME}/.local | ||
139 | read-write ${HOME}/.local/share | ||
129 | 140 | ||
130 | # top secret | 141 | # top secret |
131 | blacklist ${HOME}/.ecryptfs | 142 | blacklist ${HOME}/.ecryptfs |
@@ -133,6 +144,7 @@ blacklist ${HOME}/.Private | |||
133 | blacklist ${HOME}/.ssh | 144 | blacklist ${HOME}/.ssh |
134 | blacklist ${HOME}/.cert | 145 | blacklist ${HOME}/.cert |
135 | blacklist ${HOME}/.gnome2/keyrings | 146 | blacklist ${HOME}/.gnome2/keyrings |
147 | blacklist ${HOME}/.local/share/keyrings | ||
136 | blacklist ${HOME}/.kde4/share/apps/kwallet | 148 | blacklist ${HOME}/.kde4/share/apps/kwallet |
137 | blacklist ${HOME}/.kde/share/apps/kwallet | 149 | blacklist ${HOME}/.kde/share/apps/kwallet |
138 | blacklist ${HOME}/.local/share/kwalletd | 150 | blacklist ${HOME}/.local/share/kwalletd |
@@ -202,6 +214,8 @@ blacklist /usr/lib64/virtualbox | |||
202 | 214 | ||
203 | # prevent lxterminal connecting to an existing lxterminal session | 215 | # prevent lxterminal connecting to an existing lxterminal session |
204 | blacklist /tmp/.lxterminal-socket* | 216 | blacklist /tmp/.lxterminal-socket* |
217 | # prevent tmux connecting to an existing session | ||
218 | blacklist /tmp/tmux-* | ||
205 | 219 | ||
206 | # disable terminals running as server resulting in sandbox escape | 220 | # disable terminals running as server resulting in sandbox escape |
207 | blacklist ${PATH}/gnome-terminal | 221 | blacklist ${PATH}/gnome-terminal |
diff --git a/etc/disable-programs.inc b/etc/disable-programs.inc index 96bf1464b..b307978da 100644 --- a/etc/disable-programs.inc +++ b/etc/disable-programs.inc | |||
@@ -177,8 +177,17 @@ blacklist ${HOME}/.icedove | |||
177 | blacklist ${HOME}/.inkscape | 177 | blacklist ${HOME}/.inkscape |
178 | blacklist ${HOME}/.jitsi | 178 | blacklist ${HOME}/.jitsi |
179 | blacklist ${HOME}/.kde/share/apps/gwenview | 179 | blacklist ${HOME}/.kde/share/apps/gwenview |
180 | blacklist ${HOME}/.kde/share/apps/kcookiejar | ||
181 | blacklist ${HOME}/.kde/share/apps/khtml | ||
182 | blacklist ${HOME}/.kde/share/apps/konqsidebartng | ||
183 | blacklist ${HOME}/.kde/share/apps/konqueror | ||
180 | blacklist ${HOME}/.kde/share/apps/okular | 184 | blacklist ${HOME}/.kde/share/apps/okular |
181 | blacklist ${HOME}/.kde/share/config/gwenviewrc | 185 | blacklist ${HOME}/.kde/share/config/gwenviewrc |
186 | blacklist ${HOME}/.kde/share/config/kcookiejarrc | ||
187 | blacklist ${HOME}/.kde/share/config/khtmlrc | ||
188 | blacklist ${HOME}/.kde/share/config/konq_history | ||
189 | blacklist ${HOME}/.kde/share/config/konqsidebartngrc | ||
190 | blacklist ${HOME}/.kde/share/config/konquerorrc | ||
182 | blacklist ${HOME}/.kde/share/config/okularpartrc | 191 | blacklist ${HOME}/.kde/share/config/okularpartrc |
183 | blacklist ${HOME}/.kde/share/config/okularrc | 192 | blacklist ${HOME}/.kde/share/config/okularrc |
184 | blacklist ${HOME}/.killingfloor | 193 | blacklist ${HOME}/.killingfloor |
diff --git a/etc/gnome-mplayer.profile b/etc/gnome-mplayer.profile index 488c7e0b8..25d2da085 100644 --- a/etc/gnome-mplayer.profile +++ b/etc/gnome-mplayer.profile | |||
@@ -12,6 +12,6 @@ protocol unix,inet,inet6 | |||
12 | seccomp | 12 | seccomp |
13 | shell none | 13 | shell none |
14 | 14 | ||
15 | private-bin gnome-mplayer,mplayer | 15 | # private-bin gnome-mplayer,mplayer |
16 | private-dev | 16 | private-dev |
17 | private-tmp | 17 | private-tmp |
diff --git a/etc/login.users b/etc/login.users index bc6ac4b09..81f12c6b1 100644 --- a/etc/login.users +++ b/etc/login.users | |||
@@ -9,6 +9,12 @@ | |||
9 | # | 9 | # |
10 | # netblue:--net=none --protocol=unix | 10 | # netblue:--net=none --protocol=unix |
11 | # | 11 | # |
12 | # Wildcard patterns are accepted in the user name field: | ||
13 | # | ||
14 | # user*: --private | ||
15 | # | ||
16 | # The example will do --private for user1, user2, and so on. | ||
17 | # | ||
12 | # The extra arguments are inserted into program command line if firejail | 18 | # The extra arguments are inserted into program command line if firejail |
13 | # was started as a login shell. | 19 | # was started as a login shell. |
14 | 20 | ||
diff --git a/etc/start-tor-browser.profile b/etc/start-tor-browser.profile index ee19cee25..16ef754f6 100644 --- a/etc/start-tor-browser.profile +++ b/etc/start-tor-browser.profile | |||
@@ -14,7 +14,7 @@ seccomp | |||
14 | shell none | 14 | shell none |
15 | tracelog | 15 | tracelog |
16 | 16 | ||
17 | private-bin bash,grep,sed,tail,env,gpg,id,readlink,dirname,test,mkdir,ln,sed,cp,rm,getconf | 17 | private-bin bash,grep,tail,env,gpg,id,readlink,dirname,test,mkdir,ln,sed,cp,rm,getconf |
18 | private-etc fonts | 18 | private-etc fonts |
19 | private-dev | 19 | private-dev |
20 | private-tmp | 20 | private-tmp |
diff --git a/etc/uudeview.profile b/etc/uudeview.profile index d5b750a13..d4b54067d 100644 --- a/etc/uudeview.profile +++ b/etc/uudeview.profile | |||
@@ -3,7 +3,6 @@ quiet | |||
3 | ignore noroot | 3 | ignore noroot |
4 | include /etc/firejail/default.profile | 4 | include /etc/firejail/default.profile |
5 | 5 | ||
6 | blacklist /etc | ||
7 | 6 | ||
8 | hostname uudeview | 7 | hostname uudeview |
9 | net none | 8 | net none |
@@ -13,3 +12,4 @@ tracelog | |||
13 | 12 | ||
14 | private-bin uudeview | 13 | private-bin uudeview |
15 | private-dev | 14 | private-dev |
15 | private-etc ld.so.preload | ||
diff --git a/etc/uzbl-browser.profile b/etc/uzbl-browser.profile new file mode 100644 index 000000000..8dc90982e --- /dev/null +++ b/etc/uzbl-browser.profile | |||
@@ -0,0 +1,29 @@ | |||
1 | # Firejail profile for uzbl-browser | ||
2 | |||
3 | noblacklist ~/.config/uzbl | ||
4 | noblacklist ~/.gnupg | ||
5 | include /etc/firejail/disable-common.inc | ||
6 | include /etc/firejail/disable-programs.inc | ||
7 | include /etc/firejail/disable-devel.inc | ||
8 | |||
9 | caps.drop all | ||
10 | netfilter | ||
11 | nonewprivs | ||
12 | noroot | ||
13 | protocol unix,inet,inet6 | ||
14 | seccomp | ||
15 | tracelog | ||
16 | |||
17 | mkdir ~/.config/uzbl | ||
18 | whitelist ~/.config/uzbl | ||
19 | mkdir ~/.local/share/uzbl | ||
20 | whitelist ~/.local/share/uzbl | ||
21 | |||
22 | whitelist ${DOWNLOADS} | ||
23 | |||
24 | mkdir ~/.gnupg | ||
25 | whitelist ~/.gnupg | ||
26 | mkdir ~/.password-store | ||
27 | whitelist ~/.password-store | ||
28 | |||
29 | include /etc/firejail/whitelist-common.inc | ||
diff --git a/etc/vlc.profile b/etc/vlc.profile index 2fd763f25..df9fcab03 100644 --- a/etc/vlc.profile +++ b/etc/vlc.profile | |||
@@ -8,7 +8,7 @@ include /etc/firejail/disable-passwdmgr.inc | |||
8 | 8 | ||
9 | caps.drop all | 9 | caps.drop all |
10 | netfilter | 10 | netfilter |
11 | nogroups | 11 | # nogroups |
12 | nonewprivs | 12 | nonewprivs |
13 | noroot | 13 | noroot |
14 | protocol unix,inet,inet6,netlink | 14 | protocol unix,inet,inet6,netlink |
diff --git a/etc/xmms.profile b/etc/xmms.profile new file mode 100644 index 000000000..0d57f2f90 --- /dev/null +++ b/etc/xmms.profile | |||
@@ -0,0 +1,18 @@ | |||
1 | # Firejail profile for XMMS | ||
2 | noblacklist ${HOME}/.xmms | ||
3 | |||
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 | caps.drop all | ||
10 | netfilter | ||
11 | nonewprivs | ||
12 | noroot | ||
13 | protocol unix,inet,inet6 | ||
14 | seccomp | ||
15 | shell none | ||
16 | |||
17 | private-bin xmms | ||
18 | private-dev | ||
diff --git a/platform/debian/conffiles b/platform/debian/conffiles index 56a5c8e7e..61e72583e 100644 --- a/platform/debian/conffiles +++ b/platform/debian/conffiles | |||
@@ -242,3 +242,5 @@ | |||
242 | /etc/firejail/qupzilla.profile | 242 | /etc/firejail/qupzilla.profile |
243 | /etc/firejail/FossaMail.profile | 243 | /etc/firejail/FossaMail.profile |
244 | /etc/firejail/fossamail.profile | 244 | /etc/firejail/fossamail.profile |
245 | /etc/firejail/uzbl-browser.profile | ||
246 | /etc/firejail/xmms.profile | ||
diff --git a/src/bash_completion/firejail.bash_completion b/src/bash_completion/firejail.bash_completion index d3dcd57d0..0f71c74dc 100644 --- a/src/bash_completion/firejail.bash_completion +++ b/src/bash_completion/firejail.bash_completion | |||
@@ -23,6 +23,10 @@ _firejail() | |||
23 | _filedir | 23 | _filedir |
24 | return 0 | 24 | return 0 |
25 | ;; | 25 | ;; |
26 | --hosts-file) | ||
27 | _filedir | ||
28 | return 0 | ||
29 | ;; | ||
26 | --chroot) | 30 | --chroot) |
27 | _filedir -d | 31 | _filedir -d |
28 | return 0 | 32 | return 0 |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 722d5c05e..7e5412630 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -213,6 +213,7 @@ typedef struct config_t { | |||
213 | // networking | 213 | // networking |
214 | char *name; // sandbox name | 214 | char *name; // sandbox name |
215 | char *hostname; // host name | 215 | char *hostname; // host name |
216 | char *hosts_file; // hosts file to be installed in the sandbox | ||
216 | uint32_t defaultgw; // default gateway | 217 | uint32_t defaultgw; // default gateway |
217 | Bridge bridge0; | 218 | Bridge bridge0; |
218 | Bridge bridge1; | 219 | Bridge bridge1; |
@@ -317,6 +318,7 @@ extern int arg_netfilter; // enable netfilter | |||
317 | extern int arg_netfilter6; // enable netfilter6 | 318 | extern int arg_netfilter6; // enable netfilter6 |
318 | extern char *arg_netfilter_file; // netfilter file | 319 | extern char *arg_netfilter_file; // netfilter file |
319 | extern char *arg_netfilter6_file; // netfilter file | 320 | extern char *arg_netfilter6_file; // netfilter file |
321 | extern char *arg_netns; // "ip netns"-created network namespace to use | ||
320 | extern int arg_doubledash; // double dash | 322 | extern int arg_doubledash; // double dash |
321 | extern int arg_shell_none; // run the program directly without a shell | 323 | extern int arg_shell_none; // run the program directly without a shell |
322 | extern int arg_private_dev; // private dev directory | 324 | extern int arg_private_dev; // private dev directory |
@@ -336,6 +338,7 @@ extern int arg_nice; // nice value configured | |||
336 | extern int arg_ipc; // enable ipc namespace | 338 | extern int arg_ipc; // enable ipc namespace |
337 | extern int arg_writable_etc; // writable etc | 339 | extern int arg_writable_etc; // writable etc |
338 | extern int arg_writable_var; // writable var | 340 | extern int arg_writable_var; // writable var |
341 | extern int arg_writable_var_log; // writable /var/log | ||
339 | extern int arg_appimage; // appimage | 342 | extern int arg_appimage; // appimage |
340 | extern int arg_audit; // audit | 343 | extern int arg_audit; // audit |
341 | extern char *arg_audit_prog; // audit | 344 | extern char *arg_audit_prog; // audit |
@@ -451,6 +454,7 @@ void logargs(int argc, char **argv) ; | |||
451 | void logerr(const char *msg); | 454 | void logerr(const char *msg); |
452 | int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); | 455 | int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); |
453 | void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); | 456 | void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); |
457 | void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); | ||
454 | void touch_file_as_user(const char *fname, uid_t uid, gid_t gid, mode_t mode); | 458 | void touch_file_as_user(const char *fname, uid_t uid, gid_t gid, mode_t mode); |
455 | int is_dir(const char *fname); | 459 | int is_dir(const char *fname); |
456 | int is_link(const char *fname); | 460 | int is_link(const char *fname); |
@@ -536,6 +540,9 @@ void fs_trace(void); | |||
536 | // fs_hostname.c | 540 | // fs_hostname.c |
537 | void fs_hostname(const char *hostname); | 541 | void fs_hostname(const char *hostname); |
538 | void fs_resolvconf(void); | 542 | void fs_resolvconf(void); |
543 | char *fs_check_hosts_fiile(const char *fname); | ||
544 | void fs_store_hosts_file(void); | ||
545 | void fs_mount_hosts_file(void); | ||
539 | 546 | ||
540 | // rlimit.c | 547 | // rlimit.c |
541 | void set_rlimits(void); | 548 | void set_rlimits(void); |
@@ -560,6 +567,11 @@ void check_netfilter_file(const char *fname); | |||
560 | void netfilter(const char *fname); | 567 | void netfilter(const char *fname); |
561 | void netfilter6(const char *fname); | 568 | void netfilter6(const char *fname); |
562 | 569 | ||
570 | // netns.c | ||
571 | void check_netns(const char *nsname); | ||
572 | void netns(const char *nsname); | ||
573 | void netns_mounts(const char *nsname); | ||
574 | |||
563 | // bandwidth.c | 575 | // bandwidth.c |
564 | void bandwidth_del_run_file(pid_t pid); | 576 | void bandwidth_del_run_file(pid_t pid); |
565 | void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, int up); | 577 | void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, int up); |
diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 0da4cc111..69b9d77bc 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "firejail.h" | 20 | #include "firejail.h" |
21 | #include <sys/mount.h> | 21 | #include <sys/mount.h> |
22 | #include <sys/stat.h> | 22 | #include <sys/stat.h> |
23 | #include <sys/wait.h> | ||
23 | #include <linux/limits.h> | 24 | #include <linux/limits.h> |
24 | #include <fnmatch.h> | 25 | #include <fnmatch.h> |
25 | #include <glob.h> | 26 | #include <glob.h> |
@@ -681,11 +682,13 @@ void fs_basic_fs(void) { | |||
681 | fs_rdonly("/usr"); | 682 | fs_rdonly("/usr"); |
682 | 683 | ||
683 | // update /var directory in order to support multiple sandboxes running on the same root directory | 684 | // update /var directory in order to support multiple sandboxes running on the same root directory |
684 | // if (!arg_private_dev) | ||
685 | // fs_dev_shm(); | ||
686 | fs_var_lock(); | 685 | fs_var_lock(); |
687 | fs_var_tmp(); | 686 | fs_var_tmp(); |
688 | fs_var_log(); | 687 | if (!arg_writable_var_log) |
688 | fs_var_log(); | ||
689 | else | ||
690 | fs_rdwr("/var/log"); | ||
691 | |||
689 | fs_var_lib(); | 692 | fs_var_lib(); |
690 | fs_var_cache(); | 693 | fs_var_cache(); |
691 | fs_var_utmp(); | 694 | fs_var_utmp(); |
@@ -995,7 +998,11 @@ void fs_overlayfs(void) { | |||
995 | // fs_dev_shm(); | 998 | // fs_dev_shm(); |
996 | fs_var_lock(); | 999 | fs_var_lock(); |
997 | fs_var_tmp(); | 1000 | fs_var_tmp(); |
998 | fs_var_log(); | 1001 | if (!arg_writable_var_log) |
1002 | fs_var_log(); | ||
1003 | else | ||
1004 | fs_rdwr("/var/log"); | ||
1005 | |||
999 | fs_var_lib(); | 1006 | fs_var_lib(); |
1000 | fs_var_cache(); | 1007 | fs_var_cache(); |
1001 | fs_var_utmp(); | 1008 | fs_var_utmp(); |
@@ -1225,7 +1232,11 @@ void fs_chroot(const char *rootdir) { | |||
1225 | // fs_dev_shm(); | 1232 | // fs_dev_shm(); |
1226 | fs_var_lock(); | 1233 | fs_var_lock(); |
1227 | fs_var_tmp(); | 1234 | fs_var_tmp(); |
1228 | fs_var_log(); | 1235 | if (!arg_writable_var_log) |
1236 | fs_var_log(); | ||
1237 | else | ||
1238 | fs_rdwr("/var/log"); | ||
1239 | |||
1229 | fs_var_lib(); | 1240 | fs_var_lib(); |
1230 | fs_var_cache(); | 1241 | fs_var_cache(); |
1231 | fs_var_utmp(); | 1242 | fs_var_utmp(); |
diff --git a/src/firejail/fs_etc.c b/src/firejail/fs_etc.c index 479383af2..f14e90deb 100644 --- a/src/firejail/fs_etc.c +++ b/src/firejail/fs_etc.c | |||
@@ -31,8 +31,8 @@ void fs_machineid(void) { | |||
31 | uint32_t u32[4]; | 31 | uint32_t u32[4]; |
32 | } mid; | 32 | } mid; |
33 | 33 | ||
34 | // if --machine-id flag is active, do nothing | 34 | // if --machine-id flag is inactive, do nothing |
35 | if (arg_machineid) | 35 | if (arg_machineid == 0) |
36 | return; | 36 | return; |
37 | 37 | ||
38 | // init random number generator | 38 | // init random number generator |
diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c index b2e1b4a99..3b586b276 100644 --- a/src/firejail/fs_hostname.c +++ b/src/firejail/fs_hostname.c | |||
@@ -42,7 +42,7 @@ void fs_hostname(const char *hostname) { | |||
42 | } | 42 | } |
43 | 43 | ||
44 | // create a new /etc/hosts | 44 | // create a new /etc/hosts |
45 | if (stat("/etc/hosts", &s) == 0) { | 45 | if (cfg.hosts_file == NULL && stat("/etc/hosts", &s) == 0) { |
46 | if (arg_debug) | 46 | if (arg_debug) |
47 | printf("Creating a new /etc/hosts file\n"); | 47 | printf("Creating a new /etc/hosts file\n"); |
48 | // copy /etc/host into our new file, and modify it on the fly | 48 | // copy /etc/host into our new file, and modify it on the fly |
@@ -79,9 +79,7 @@ void fs_hostname(const char *hostname) { | |||
79 | fclose(fp2); | 79 | fclose(fp2); |
80 | 80 | ||
81 | // bind-mount the file on top of /etc/hostname | 81 | // bind-mount the file on top of /etc/hostname |
82 | if (mount(RUN_HOSTS_FILE, "/etc/hosts", NULL, MS_BIND|MS_REC, NULL) < 0) | 82 | fs_mount_hosts_file(); |
83 | errExit("mount bind /etc/hosts"); | ||
84 | fs_logger("create /etc/hosts"); | ||
85 | } | 83 | } |
86 | return; | 84 | return; |
87 | 85 | ||
@@ -129,4 +127,49 @@ void fs_resolvconf(void) { | |||
129 | } | 127 | } |
130 | } | 128 | } |
131 | 129 | ||
130 | char *fs_check_hosts_fiile(const char *fname) { | ||
131 | assert(fname); | ||
132 | invalid_filename(fname); | ||
133 | char *rv = expand_home(fname, cfg.homedir); | ||
134 | |||
135 | // no a link | ||
136 | if (is_link(rv)) | ||
137 | goto errexit; | ||
132 | 138 | ||
139 | // the user has read access to the file | ||
140 | if (access(rv, R_OK)) | ||
141 | goto errexit; | ||
142 | |||
143 | return rv; | ||
144 | errexit: | ||
145 | fprintf(stderr, "Error: invalid file %s\n", fname); | ||
146 | exit(1); | ||
147 | } | ||
148 | |||
149 | void fs_store_hosts_file(void) { | ||
150 | copy_file_from_user_to_root(cfg.hosts_file, RUN_HOSTS_FILE, 0, 0, 0644); // root needed | ||
151 | } | ||
152 | |||
153 | void fs_mount_hosts_file(void) { | ||
154 | // check /etc/hosts file | ||
155 | struct stat s; | ||
156 | if (stat("/etc/hosts", &s) == -1) | ||
157 | goto errexit; | ||
158 | // not a link | ||
159 | if (is_link("/etc/hosts")) | ||
160 | goto errexit; | ||
161 | // owned by root | ||
162 | if (s.st_uid != 0) | ||
163 | goto errexit; | ||
164 | |||
165 | // bind-mount the file on top of /etc/hostname | ||
166 | if (mount(RUN_HOSTS_FILE, "/etc/hosts", NULL, MS_BIND|MS_REC, NULL) < 0) | ||
167 | errExit("mount bind /etc/hosts"); | ||
168 | fs_logger("create /etc/hosts"); | ||
169 | return; | ||
170 | |||
171 | errexit: | ||
172 | fprintf(stderr, "Error: invalid /etc/hosts file\n"); | ||
173 | exit(1); | ||
174 | } | ||
175 | |||
diff --git a/src/firejail/main.c b/src/firejail/main.c index 84bf5e8e6..7c6568903 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -85,6 +85,7 @@ int arg_netfilter; // enable netfilter | |||
85 | int arg_netfilter6; // enable netfilter6 | 85 | int arg_netfilter6; // enable netfilter6 |
86 | char *arg_netfilter_file = NULL; // netfilter file | 86 | char *arg_netfilter_file = NULL; // netfilter file |
87 | char *arg_netfilter6_file = NULL; // netfilter6 file | 87 | char *arg_netfilter6_file = NULL; // netfilter6 file |
88 | char *arg_netns = NULL; // "ip netns"-created network namespace to use | ||
88 | int arg_doubledash = 0; // double dash | 89 | int arg_doubledash = 0; // double dash |
89 | int arg_shell_none = 0; // run the program directly without a shell | 90 | int arg_shell_none = 0; // run the program directly without a shell |
90 | int arg_private_dev = 0; // private dev directory | 91 | int arg_private_dev = 0; // private dev directory |
@@ -113,7 +114,8 @@ int arg_x11_block = 0; // block X11 | |||
113 | int arg_x11_xorg = 0; // use X11 security extention | 114 | int arg_x11_xorg = 0; // use X11 security extention |
114 | int arg_allusers = 0; // all user home directories visible | 115 | int arg_allusers = 0; // all user home directories visible |
115 | int arg_machineid = 0; // preserve /etc/machine-id | 116 | int arg_machineid = 0; // preserve /etc/machine-id |
116 | int arg_allow_private_blacklist = 0; // blacklist things in private directories | 117 | int arg_allow_private_blacklist = 0; // blacklist things in private directories |
118 | int arg_writable_var_log; // writable /var/log | ||
117 | 119 | ||
118 | int login_shell = 0; | 120 | int login_shell = 0; |
119 | 121 | ||
@@ -1487,6 +1489,9 @@ int main(int argc, char **argv) { | |||
1487 | else if (strcmp(argv[i], "--writable-var") == 0) { | 1489 | else if (strcmp(argv[i], "--writable-var") == 0) { |
1488 | arg_writable_var = 1; | 1490 | arg_writable_var = 1; |
1489 | } | 1491 | } |
1492 | else if (strcmp(argv[i], "--writable-var-log") == 0) { | ||
1493 | arg_writable_var_log = 1; | ||
1494 | } | ||
1490 | else if (strcmp(argv[i], "--machine-id") == 0) { | 1495 | else if (strcmp(argv[i], "--machine-id") == 0) { |
1491 | arg_machineid = 1; | 1496 | arg_machineid = 1; |
1492 | } | 1497 | } |
@@ -1946,6 +1951,9 @@ int main(int argc, char **argv) { | |||
1946 | return 1; | 1951 | return 1; |
1947 | } | 1952 | } |
1948 | } | 1953 | } |
1954 | |||
1955 | else if (strncmp(argv[i], "--hosts-file=", 13) == 0) | ||
1956 | cfg.hosts_file = fs_check_hosts_fiile(argv[i] + 13); | ||
1949 | 1957 | ||
1950 | #ifdef HAVE_NETWORK | 1958 | #ifdef HAVE_NETWORK |
1951 | else if (strcmp(argv[i], "--netfilter") == 0) { | 1959 | else if (strcmp(argv[i], "--netfilter") == 0) { |
@@ -1999,6 +2007,15 @@ int main(int argc, char **argv) { | |||
1999 | else | 2007 | else |
2000 | exit_err_feature("networking"); | 2008 | exit_err_feature("networking"); |
2001 | } | 2009 | } |
2010 | |||
2011 | else if (strncmp(argv[i], "--netns=", 8) == 0) { | ||
2012 | if (checkcfg(CFG_NETWORK)) { | ||
2013 | arg_netns = argv[i] + 8; | ||
2014 | check_netns(arg_netns); | ||
2015 | } | ||
2016 | else | ||
2017 | exit_err_feature("networking"); | ||
2018 | } | ||
2002 | #endif | 2019 | #endif |
2003 | //************************************* | 2020 | //************************************* |
2004 | // command | 2021 | // command |
diff --git a/src/firejail/netns.c b/src/firejail/netns.c new file mode 100644 index 000000000..477d56b3d --- /dev/null +++ b/src/firejail/netns.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 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 <stdio.h> | ||
22 | #include <string.h> | ||
23 | #include <errno.h> | ||
24 | #include <sys/types.h> | ||
25 | #include <sys/mount.h> | ||
26 | #include <sys/stat.h> | ||
27 | #include <sys/syscall.h> | ||
28 | #include <dirent.h> | ||
29 | #include <fcntl.h> | ||
30 | #include <sched.h> | ||
31 | #include <unistd.h> | ||
32 | |||
33 | static char *netns_control_file(const char *nsname) { | ||
34 | char *rv = 0; | ||
35 | if (asprintf(&rv, "/var/run/netns/%s", nsname) <= 0) | ||
36 | errExit("asprintf"); | ||
37 | return rv; | ||
38 | } | ||
39 | |||
40 | static char *netns_etc_dir(const char *nsname) { | ||
41 | char *rv = 0; | ||
42 | if (asprintf(&rv, "/etc/netns/%s", nsname) <= 0) | ||
43 | errExit("asprintf"); | ||
44 | return rv; | ||
45 | } | ||
46 | |||
47 | void check_netns(const char *nsname) { | ||
48 | if (strchr(nsname, '/') || strstr(nsname, "..")) { | ||
49 | fprintf(stderr, "Error: invalid netns name %s\n", nsname); | ||
50 | exit(1); | ||
51 | } | ||
52 | invalid_filename(nsname); | ||
53 | char *control_file = netns_control_file(nsname); | ||
54 | |||
55 | EUID_ASSERT(); | ||
56 | |||
57 | struct stat st; | ||
58 | if (lstat(control_file, &st)) { | ||
59 | fprintf(stderr, "Error: invalid netns '%s' (%s: %s)\n", | ||
60 | nsname, control_file, strerror(errno)); | ||
61 | exit(1); | ||
62 | } | ||
63 | if (!S_ISREG(st.st_mode)) { | ||
64 | fprintf(stderr, "Error: invalid netns '%s' (%s: not a regular file)\n", | ||
65 | nsname, control_file); | ||
66 | exit(1); | ||
67 | } | ||
68 | free(control_file); | ||
69 | } | ||
70 | |||
71 | void netns(const char *nsname) { | ||
72 | char *control_file = netns_control_file(nsname); | ||
73 | int nsfd = open(control_file, O_RDONLY|O_CLOEXEC); | ||
74 | if (nsfd < 0) { | ||
75 | fprintf(stderr, "Error: cannot open netns '%s' (%s: %s)\n", | ||
76 | nsname, control_file, strerror(errno)); | ||
77 | exit(1); | ||
78 | } | ||
79 | if (syscall(__NR_setns, nsfd, CLONE_NEWNET) < 0) { | ||
80 | fprintf(stderr, "Error: cannot join netns '%s': %s\n", | ||
81 | nsname, strerror(errno)); | ||
82 | exit(1); | ||
83 | } | ||
84 | close(nsfd); | ||
85 | free(control_file); | ||
86 | } | ||
87 | |||
88 | void netns_mounts(const char *nsname) { | ||
89 | char *etcdir = netns_etc_dir(nsname); | ||
90 | char *netns_name, *etc_name; | ||
91 | struct dirent *entry; | ||
92 | DIR *dir; | ||
93 | |||
94 | dir = opendir(etcdir); | ||
95 | if (!dir) { | ||
96 | free(etcdir); | ||
97 | return; | ||
98 | } | ||
99 | while ((entry = readdir(dir))) { | ||
100 | if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) | ||
101 | continue; | ||
102 | if (asprintf(&netns_name, "%s/%s", etcdir, entry->d_name) < 0 || | ||
103 | asprintf(&etc_name, "/etc/%s", entry->d_name) < 0) | ||
104 | errExit("asprintf"); | ||
105 | if (mount(netns_name, etc_name, "none", MS_BIND, 0) < 0) { | ||
106 | fprintf(stderr, "Warning: bind %s -> %s failed: %s\n", | ||
107 | netns_name, etc_name, strerror(errno)); | ||
108 | } | ||
109 | free(netns_name); | ||
110 | free(etc_name); | ||
111 | } | ||
112 | closedir(dir); | ||
113 | free(etcdir); | ||
114 | } | ||
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 33b6eab91..4856b31ae 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -215,6 +215,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
215 | arg_no3d = 1; | 215 | arg_no3d = 1; |
216 | return 0; | 216 | return 0; |
217 | } | 217 | } |
218 | else if (strcmp(ptr, "allow-private-blacklist") == 0) { | ||
219 | arg_allow_private_blacklist = 1; | ||
220 | return 0; | ||
221 | } | ||
218 | else if (strcmp(ptr, "netfilter") == 0) { | 222 | else if (strcmp(ptr, "netfilter") == 0) { |
219 | #ifdef HAVE_NETWORK | 223 | #ifdef HAVE_NETWORK |
220 | if (checkcfg(CFG_NETWORK)) | 224 | if (checkcfg(CFG_NETWORK)) |
@@ -602,6 +606,12 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
602 | return 0; | 606 | return 0; |
603 | } | 607 | } |
604 | 608 | ||
609 | // hosts-file | ||
610 | if (strncmp(ptr, "hosts-file ", 11) == 0) { | ||
611 | cfg.hosts_file = fs_check_hosts_fiile(ptr + 11); | ||
612 | return 0; | ||
613 | } | ||
614 | |||
605 | // dns | 615 | // dns |
606 | if (strncmp(ptr, "dns ", 4) == 0) { | 616 | if (strncmp(ptr, "dns ", 4) == 0) { |
607 | uint32_t dns; | 617 | uint32_t dns; |
@@ -663,6 +673,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
663 | arg_writable_var = 1; | 673 | arg_writable_var = 1; |
664 | return 0; | 674 | return 0; |
665 | } | 675 | } |
676 | if (strcmp(ptr, "writable-var-log") == 0) { | ||
677 | arg_writable_var_log = 1; | ||
678 | return 0; | ||
679 | } | ||
666 | 680 | ||
667 | // private directory | 681 | // private directory |
668 | if (strncmp(ptr, "private ", 8) == 0) { | 682 | if (strncmp(ptr, "private ", 8) == 0) { |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 493877db3..e56526f34 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -386,7 +386,7 @@ static void enforce_filters(void) { | |||
386 | } | 386 | } |
387 | 387 | ||
388 | // disable all capabilities | 388 | // disable all capabilities |
389 | if (arg_caps_default_filter || arg_caps_list) | 389 | if (arg_caps_default_filter || arg_caps_list && !arg_quiet) |
390 | fprintf(stderr, "Warning: all capabilities disabled for a regular user in chroot\n"); | 390 | fprintf(stderr, "Warning: all capabilities disabled for a regular user in chroot\n"); |
391 | arg_caps_drop_all = 1; | 391 | arg_caps_drop_all = 1; |
392 | 392 | ||
@@ -467,6 +467,11 @@ int sandbox(void* sandbox_arg) { | |||
467 | if (arg_debug) | 467 | if (arg_debug) |
468 | printf("Network namespace enabled, only loopback interface available\n"); | 468 | printf("Network namespace enabled, only loopback interface available\n"); |
469 | } | 469 | } |
470 | else if (arg_netns) { | ||
471 | netns(arg_netns); | ||
472 | if (arg_debug) | ||
473 | printf("Network namespace '%s' activated\n", arg_netns); | ||
474 | } | ||
470 | else if (any_bridge_configured() || any_interface_configured()) { | 475 | else if (any_bridge_configured() || any_interface_configured()) { |
471 | // configure lo and eth0...eth3 | 476 | // configure lo and eth0...eth3 |
472 | net_if_up("lo"); | 477 | net_if_up("lo"); |
@@ -515,7 +520,8 @@ int sandbox(void* sandbox_arg) { | |||
515 | if (cfg.defaultgw) { | 520 | if (cfg.defaultgw) { |
516 | // set the default route | 521 | // set the default route |
517 | if (net_add_route(0, 0, cfg.defaultgw)) { | 522 | if (net_add_route(0, 0, cfg.defaultgw)) { |
518 | fprintf(stderr, "Warning: cannot configure default route\n"); | 523 | if (!arg_quiet) |
524 | fprintf(stderr, "Warning: cannot configure default route\n"); | ||
519 | gw_cfg_failed = 1; | 525 | gw_cfg_failed = 1; |
520 | } | 526 | } |
521 | } | 527 | } |
@@ -582,6 +588,10 @@ int sandbox(void* sandbox_arg) { | |||
582 | if (arg_trace || arg_tracelog || mask_x11_abstract_socket) | 588 | if (arg_trace || arg_tracelog || mask_x11_abstract_socket) |
583 | fs_trace_preload(); | 589 | fs_trace_preload(); |
584 | 590 | ||
591 | // store hosts file | ||
592 | if (cfg.hosts_file) | ||
593 | fs_store_hosts_file(); | ||
594 | |||
585 | //**************************** | 595 | //**************************** |
586 | // configure filesystem | 596 | // configure filesystem |
587 | //**************************** | 597 | //**************************** |
@@ -620,19 +630,29 @@ int sandbox(void* sandbox_arg) { | |||
620 | #ifdef HAVE_OVERLAYFS | 630 | #ifdef HAVE_OVERLAYFS |
621 | if (arg_overlay) { | 631 | if (arg_overlay) { |
622 | fs_overlayfs(); | 632 | fs_overlayfs(); |
633 | |||
634 | //todo - bring it back for overlay-named | ||
635 | #if 0 | ||
636 | fs_overlayfs(); | ||
637 | // force caps and seccomp if not started as root | ||
638 | if (getuid() != 0) { | ||
639 | enforce_filters(); | ||
640 | #ifdef HAVE_SECCOMP | ||
641 | enforce_seccomp = 1; | ||
642 | #endif | ||
643 | } | ||
644 | else | ||
645 | arg_seccomp = 1; | ||
646 | #endif | ||
647 | |||
648 | |||
649 | |||
623 | } | 650 | } |
624 | else | 651 | else |
625 | #endif | 652 | #endif |
626 | fs_basic_fs(); | 653 | fs_basic_fs(); |
627 | 654 | ||
628 | //**************************** | 655 | //**************************** |
629 | // set hostname in /etc/hostname | ||
630 | //**************************** | ||
631 | if (cfg.hostname) { | ||
632 | fs_hostname(cfg.hostname); | ||
633 | } | ||
634 | |||
635 | //**************************** | ||
636 | // private mode | 656 | // private mode |
637 | //**************************** | 657 | //**************************** |
638 | if (arg_private) { | 658 | if (arg_private) { |
@@ -729,6 +749,22 @@ int sandbox(void* sandbox_arg) { | |||
729 | EUID_ROOT(); | 749 | EUID_ROOT(); |
730 | } | 750 | } |
731 | } | 751 | } |
752 | |||
753 | |||
754 | //**************************** | ||
755 | // hosts and hostname | ||
756 | //**************************** | ||
757 | if (cfg.hostname) | ||
758 | fs_hostname(cfg.hostname); | ||
759 | |||
760 | if (cfg.hosts_file) | ||
761 | fs_mount_hosts_file(); | ||
762 | |||
763 | //**************************** | ||
764 | // /etc overrides from the network namespace | ||
765 | //**************************** | ||
766 | if (arg_netns) | ||
767 | netns_mounts(arg_netns); | ||
732 | 768 | ||
733 | //**************************** | 769 | //**************************** |
734 | // update /proc, /sys, /dev, /boot directorymy | 770 | // update /proc, /sys, /dev, /boot directorymy |
@@ -812,7 +848,8 @@ int sandbox(void* sandbox_arg) { | |||
812 | int rv = nice(cfg.nice); | 848 | int rv = nice(cfg.nice); |
813 | (void) rv; | 849 | (void) rv; |
814 | if (errno) { | 850 | if (errno) { |
815 | fprintf(stderr, "Warning: cannot set nice value\n"); | 851 | if (!arg_quiet) |
852 | fprintf(stderr, "Warning: cannot set nice value\n"); | ||
816 | errno = 0; | 853 | errno = 0; |
817 | } | 854 | } |
818 | } | 855 | } |
@@ -868,7 +905,8 @@ int sandbox(void* sandbox_arg) { | |||
868 | if (arg_noroot) { | 905 | if (arg_noroot) { |
869 | int rv = unshare(CLONE_NEWUSER); | 906 | int rv = unshare(CLONE_NEWUSER); |
870 | if (rv == -1) { | 907 | if (rv == -1) { |
871 | fprintf(stderr, "Warning: cannot create a new user namespace, going forward without it...\n"); | 908 | if (!arg_quiet) |
909 | fprintf(stderr, "Warning: cannot create a new user namespace, going forward without it...\n"); | ||
872 | drop_privs(arg_nogroups); | 910 | drop_privs(arg_nogroups); |
873 | arg_noroot = 0; | 911 | arg_noroot = 0; |
874 | } | 912 | } |
@@ -899,7 +937,7 @@ int sandbox(void* sandbox_arg) { | |||
899 | if (arg_nonewprivs) { | 937 | if (arg_nonewprivs) { |
900 | int no_new_privs = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); | 938 | int no_new_privs = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); |
901 | 939 | ||
902 | if(no_new_privs != 0) | 940 | if(no_new_privs != 0 && !arg_quiet) |
903 | fprintf(stderr, "Warning: NO_NEW_PRIVS disabled, it requires a Linux kernel version 3.5 or newer.\n"); | 941 | fprintf(stderr, "Warning: NO_NEW_PRIVS disabled, it requires a Linux kernel version 3.5 or newer.\n"); |
904 | else if (arg_debug) | 942 | else if (arg_debug) |
905 | printf("NO_NEW_PRIVS set\n"); | 943 | printf("NO_NEW_PRIVS set\n"); |
diff --git a/src/firejail/usage.c b/src/firejail/usage.c index 9f4dfd44c..15ba22d4d 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c | |||
@@ -78,6 +78,7 @@ void usage(void) { | |||
78 | printf(" --get=name|pid filename - get a file from sandbox container.\n"); | 78 | printf(" --get=name|pid filename - get a file from sandbox container.\n"); |
79 | printf(" --help, -? - this help screen.\n"); | 79 | printf(" --help, -? - this help screen.\n"); |
80 | printf(" --hostname=name - set sandbox hostname.\n"); | 80 | printf(" --hostname=name - set sandbox hostname.\n"); |
81 | printf(" --hosts-file=file - use file as /etc/hosts.\n"); | ||
81 | printf(" --ignore=command - ignore command in profile files.\n"); | 82 | printf(" --ignore=command - ignore command in profile files.\n"); |
82 | #ifdef HAVE_NETWORK | 83 | #ifdef HAVE_NETWORK |
83 | printf(" --interface=name - move interface in sandbox.\n"); | 84 | printf(" --interface=name - move interface in sandbox.\n"); |
@@ -191,6 +192,7 @@ void usage(void) { | |||
191 | #endif | 192 | #endif |
192 | printf(" --writable-etc - /etc directory is mounted read-write.\n"); | 193 | printf(" --writable-etc - /etc directory is mounted read-write.\n"); |
193 | printf(" --writable-var - /var directory is mounted read-write.\n"); | 194 | printf(" --writable-var - /var directory is mounted read-write.\n"); |
195 | printf(" --writable-var-log - use the real /var/log directory, not a clone.\n"); | ||
194 | printf(" --x11 - enable X11 sandboxing. The software checks first if Xpra is\n"); | 196 | printf(" --x11 - enable X11 sandboxing. The software checks first if Xpra is\n"); |
195 | printf("\tinstalled, then it checks if Xephyr is installed. If all fails, it will\n"); | 197 | printf("\tinstalled, then it checks if Xephyr is installed. If all fails, it will\n"); |
196 | printf("\tattempt to use X11 security extension.\n"); | 198 | printf("\tattempt to use X11 security extension.\n"); |
diff --git a/src/firejail/util.c b/src/firejail/util.c index 10000e912..44891ce2d 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -169,6 +169,25 @@ void logerr(const char *msg) { | |||
169 | closelog(); | 169 | closelog(); |
170 | } | 170 | } |
171 | 171 | ||
172 | static int copy_file_by_fd(int src, int dst) { | ||
173 | assert(src >= 0); | ||
174 | assert(dst >= 0); | ||
175 | |||
176 | ssize_t len; | ||
177 | static const int BUFLEN = 1024; | ||
178 | unsigned char buf[BUFLEN]; | ||
179 | while ((len = read(src, buf, BUFLEN)) > 0) { | ||
180 | int done = 0; | ||
181 | while (done != len) { | ||
182 | int rv = write(dst, buf + done, len - done); | ||
183 | if (rv == -1) | ||
184 | return -1; | ||
185 | done += rv; | ||
186 | } | ||
187 | } | ||
188 | fflush(0); | ||
189 | return 0; | ||
190 | } | ||
172 | 191 | ||
173 | // return -1 if error, 0 if no error; if destname already exists, return error | 192 | // return -1 if error, 0 if no error; if destname already exists, return error |
174 | int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) { | 193 | int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) { |
@@ -190,33 +209,16 @@ int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, m | |||
190 | return -1; | 209 | return -1; |
191 | } | 210 | } |
192 | 211 | ||
193 | // copy | 212 | int errors = copy_file_by_fd(src, dst); |
194 | ssize_t len; | 213 | if (!errors) { |
195 | static const int BUFLEN = 1024; | 214 | if (fchown(dst, uid, gid) == -1) |
196 | unsigned char buf[BUFLEN]; | 215 | errExit("fchown"); |
197 | while ((len = read(src, buf, BUFLEN)) > 0) { | 216 | if (fchmod(dst, mode) == -1) |
198 | int done = 0; | 217 | errExit("fchmod"); |
199 | while (done != len) { | ||
200 | int rv = write(dst, buf + done, len - done); | ||
201 | if (rv == -1) { | ||
202 | close(src); | ||
203 | close(dst); | ||
204 | return -1; | ||
205 | } | ||
206 | |||
207 | done += rv; | ||
208 | } | ||
209 | } | 218 | } |
210 | fflush(0); | ||
211 | |||
212 | if (fchown(dst, uid, gid) == -1) | ||
213 | errExit("fchown"); | ||
214 | if (fchmod(dst, mode) == -1) | ||
215 | errExit("fchmod"); | ||
216 | |||
217 | close(src); | 219 | close(src); |
218 | close(dst); | 220 | close(dst); |
219 | return 0; | 221 | return errors; |
220 | } | 222 | } |
221 | 223 | ||
222 | // return -1 if error, 0 if no error | 224 | // return -1 if error, 0 if no error |
@@ -241,6 +243,45 @@ void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid | |||
241 | waitpid(child, NULL, 0); | 243 | waitpid(child, NULL, 0); |
242 | } | 244 | } |
243 | 245 | ||
246 | void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) { | ||
247 | // open destination | ||
248 | int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | ||
249 | if (dst < 0) { | ||
250 | fprintf(stderr, "Warning: cannot open destination file %s, file not copied\n", destname); | ||
251 | return; | ||
252 | } | ||
253 | |||
254 | pid_t child = fork(); | ||
255 | if (child < 0) | ||
256 | errExit("fork"); | ||
257 | if (child == 0) { | ||
258 | // drop privileges | ||
259 | drop_privs(0); | ||
260 | |||
261 | int src = open(srcname, O_RDONLY); | ||
262 | if (src < 0) { | ||
263 | fprintf(stderr, "Warning: cannot open source file %s, file not copied\n", srcname); | ||
264 | } else { | ||
265 | if (copy_file_by_fd(src, dst)) { | ||
266 | fprintf(stderr, "Warning: cannot copy %s\n", srcname); | ||
267 | } | ||
268 | close(src); | ||
269 | } | ||
270 | close(dst); | ||
271 | #ifdef HAVE_GCOV | ||
272 | __gcov_flush(); | ||
273 | #endif | ||
274 | _exit(0); | ||
275 | } | ||
276 | // wait for the child to finish | ||
277 | waitpid(child, NULL, 0); | ||
278 | if (fchown(dst, uid, gid) == -1) | ||
279 | errExit("fchown"); | ||
280 | if (fchmod(dst, mode) == -1) | ||
281 | errExit("fchmod"); | ||
282 | close(dst); | ||
283 | } | ||
284 | |||
244 | // return -1 if error, 0 if no error | 285 | // return -1 if error, 0 if no error |
245 | void touch_file_as_user(const char *fname, uid_t uid, gid_t gid, mode_t mode) { | 286 | void touch_file_as_user(const char *fname, uid_t uid, gid_t gid, mode_t mode) { |
246 | pid_t child = fork(); | 287 | pid_t child = fork(); |
@@ -864,4 +905,4 @@ errexit: | |||
864 | close(fd); | 905 | close(fd); |
865 | fprintf(stderr, "Error: cannot read %s\n", fname); | 906 | fprintf(stderr, "Error: cannot read %s\n", fname); |
866 | exit(1); | 907 | exit(1); |
867 | } \ No newline at end of file | 908 | } |
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index 8fd4562b0..90dca19bf 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt | |||
@@ -244,6 +244,11 @@ Mount /etc directory read-write. | |||
244 | .TP | 244 | .TP |
245 | \fBwritable-var | 245 | \fBwritable-var |
246 | Mount /var directory read-write. | 246 | Mount /var directory read-write. |
247 | .TP | ||
248 | \fBwritable-var-log | ||
249 | Use the real /var/log directory, not a clone. By default, a tmpfs is mounted on top of /var/log | ||
250 | directory, and a skeleton filesystem is created based on the original /var/log. | ||
251 | |||
247 | .SH Security filters | 252 | .SH Security filters |
248 | The following security filters are currently implemented: | 253 | The following security filters are currently implemented: |
249 | 254 | ||
@@ -392,6 +397,10 @@ Set a DNS server for the sandbox. Up to three DNS servers can be defined. | |||
392 | Set a hostname for the sandbox. | 397 | Set a hostname for the sandbox. |
393 | 398 | ||
394 | .TP | 399 | .TP |
400 | \fBhosts-file file | ||
401 | Use file as /etc/hosts. | ||
402 | |||
403 | .TP | ||
395 | \fBip address | 404 | \fBip address |
396 | Assign IP addresses to the last network interface defined by a net command. A | 405 | Assign IP addresses to the last network interface defined by a net command. A |
397 | default gateway is assigned by default. | 406 | default gateway is assigned by default. |
@@ -452,7 +461,7 @@ Assign MAC addresses to the last network interface defined by a net command. | |||
452 | 461 | ||
453 | .TP | 462 | .TP |
454 | \fBmachine-id | 463 | \fBmachine-id |
455 | Preserve id number in /etc/machine-id file. By default a new random id is generated inside the sandbox. | 464 | Spoof id number in /etc/machine-id file - a new random id is generated inside the sandbox. |
456 | 465 | ||
457 | .TP | 466 | .TP |
458 | \fBmtu number | 467 | \fBmtu number |
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 69d28c788..993186476 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -192,7 +192,7 @@ Define a custom blacklist Linux capabilities filter. | |||
192 | .br | 192 | .br |
193 | Example: | 193 | Example: |
194 | .br | 194 | .br |
195 | $ firejail \-\-caps.keep=net_broadcast,net_admin,net_raw | 195 | $ firejail \-\-caps.drop=net_broadcast,net_admin,net_raw |
196 | 196 | ||
197 | .TP | 197 | .TP |
198 | \fB\-\-caps.keep=capability,capability,capability | 198 | \fB\-\-caps.keep=capability,capability,capability |
@@ -469,6 +469,16 @@ Example: | |||
469 | $ firejail \-\-hostname=officepc firefox | 469 | $ firejail \-\-hostname=officepc firefox |
470 | 470 | ||
471 | .TP | 471 | .TP |
472 | \fB\-\-hosts-file=file | ||
473 | Use file as /etc/hosts. | ||
474 | .br | ||
475 | |||
476 | .br | ||
477 | Example: | ||
478 | .br | ||
479 | $ firejail \-\-hosts-file=~/myhosts firefox | ||
480 | |||
481 | .TP | ||
472 | \fB\-\-ignore=command | 482 | \fB\-\-ignore=command |
473 | Ignore command in profile file. | 483 | Ignore command in profile file. |
474 | .br | 484 | .br |
@@ -678,7 +688,7 @@ $ firejail \-\-net=eth0 \-\-mac=00:11:22:33:44:55 firefox | |||
678 | 688 | ||
679 | .TP | 689 | .TP |
680 | \fB\-\-machine-id | 690 | \fB\-\-machine-id |
681 | Preserve id number in /etc/machine-id file. By default a new random id is generated inside the sandbox. | 691 | Spoof id number in /etc/machine-id file - a new random id is generated inside the sandbox. |
682 | .br | 692 | .br |
683 | 693 | ||
684 | .br | 694 | .br |
@@ -761,6 +771,11 @@ Example: | |||
761 | $ firejail \-\-net=none vlc | 771 | $ firejail \-\-net=none vlc |
762 | 772 | ||
763 | .TP | 773 | .TP |
774 | \fB\-\-netns=name | ||
775 | Run the program in a named, persistent network namespace. These can | ||
776 | be created and configured using "ip netns". | ||
777 | |||
778 | .TP | ||
764 | \fB\-\-netfilter | 779 | \fB\-\-netfilter |
765 | Enable a default client network filter in the new network namespace. | 780 | Enable a default client network filter in the new network namespace. |
766 | New network namespaces are created using \-\-net option. If a new network namespaces is not created, | 781 | New network namespaces are created using \-\-net option. If a new network namespaces is not created, |
@@ -1710,6 +1725,17 @@ Example: | |||
1710 | .br | 1725 | .br |
1711 | $ sudo firejail --writable-var | 1726 | $ sudo firejail --writable-var |
1712 | 1727 | ||
1728 | .TP | ||
1729 | \fB\-\-writable-var-log | ||
1730 | Use the real /var/log directory, not a clone. By default, a tmpfs is mounted on top of /var/log | ||
1731 | directory, and a skeleton filesystem is created based on the original /var/log. | ||
1732 | .br | ||
1733 | |||
1734 | .br | ||
1735 | Example: | ||
1736 | .br | ||
1737 | $ sudo firejail --writable-var-log | ||
1738 | |||
1713 | 1739 | ||
1714 | .TP | 1740 | .TP |
1715 | \fB\-\-x11 | 1741 | \fB\-\-x11 |