diff options
53 files changed, 600 insertions, 313 deletions
@@ -115,4 +115,5 @@ We also keep a list of profile fixes for previous released versions in [etc-fixe | |||
115 | 115 | ||
116 | ## New profiles: | 116 | ## New profiles: |
117 | 117 | ||
118 | gnome-sound-recorder, godot, jerry, keepassxc-cli, keepassxc-proxy, klatexformula, klatexformula_cmdl, links, newsbeuter, OpenArena, pandoc, qgis, rhythmbox-client, tcpdump, teams-for-linux, tshark, xlinks, zeal | 118 | gnome-sound-recorder, godot, jerry, keepassxc-cli, keepassxc-proxy, klatexformula, klatexformula_cmdl, links, newsbeuter, OpenArena, pandoc, qgis, rhythmbox-client, tcpdump, teams-for-linux, tshark, xlinks, zeal, |
119 | mpg123, | ||
@@ -1,10 +1,11 @@ | |||
1 | firejail (0.9.61) baseline; urgency=low | 1 | firejail (0.9.61) baseline; urgency=low |
2 | * work in progress | 2 | * work in progress |
3 | * added file-copy-limit in /etc/firejail/firejail.config | ||
3 | * profile templates | 4 | * profile templates |
4 | * new profiles: qgis, klatexformula, klatexformula_cmdl, links, xlinks | 5 | * new profiles: qgis, klatexformula, klatexformula_cmdl, links, xlinks |
5 | * new profiles: pandoc, teams-for-linux, OpenArena, gnome-sound-recorder | 6 | * new profiles: pandoc, teams-for-linux, OpenArena, gnome-sound-recorder |
6 | * new profiles: godot, tcpdump, tshark, newsbeuter, keepassxc-cli | 7 | * new profiles: godot, tcpdump, tshark, newsbeuter, keepassxc-cli |
7 | * new profiles: keepassxc-proxy, rhythmbox-client, jerry, zeal | 8 | * new profiles: keepassxc-proxy, rhythmbox-client, jerry, zeal, mpg123 |
8 | -- netblue30 <netblue30@yahoo.com> Sat, 1 Jun 2019 08:00:00 -0500 | 9 | -- netblue30 <netblue30@yahoo.com> Sat, 1 Jun 2019 08:00:00 -0500 |
9 | 10 | ||
10 | firejail (0.9.60) baseline; urgency=low | 11 | firejail (0.9.60) baseline; urgency=low |
diff --git a/contrib/fix_private-bin.py b/contrib/fix_private-bin.py index 65bfba52d..c6c6f908d 100755 --- a/contrib/fix_private-bin.py +++ b/contrib/fix_private-bin.py | |||
@@ -61,7 +61,6 @@ def fixSymlinkedBins(files, replMap): | |||
61 | if shouldUpdate: | 61 | if shouldUpdate: |
62 | with open(filename, "w") as file: | 62 | with open(filename, "w") as file: |
63 | file.writelines(lines) | 63 | file.writelines(lines) |
64 | pass | ||
65 | 64 | ||
66 | 65 | ||
67 | def createSetOfBinaries(files): | 66 | def createSetOfBinaries(files): |
@@ -70,7 +69,6 @@ def createSetOfBinaries(files): | |||
70 | """ | 69 | """ |
71 | s = set() | 70 | s = set() |
72 | for filename in files: | 71 | for filename in files: |
73 | lines = None | ||
74 | with open(filename, "r") as file: | 72 | with open(filename, "r") as file: |
75 | for line in file: | 73 | for line in file: |
76 | if privRx.search(line): | 74 | if privRx.search(line): |
diff --git a/contrib/fjclip.py b/contrib/fjclip.py index 3d0c56dc6..30323b1d5 100755 --- a/contrib/fjclip.py +++ b/contrib/fjclip.py | |||
@@ -1,6 +1,5 @@ | |||
1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
2 | 2 | ||
3 | import re | ||
4 | import sys | 3 | import sys |
5 | import subprocess | 4 | import subprocess |
6 | import fjdisplay | 5 | import fjdisplay |
diff --git a/contrib/gdb-firejail.sh b/contrib/gdb-firejail.sh new file mode 100755 index 000000000..3ee3fffb3 --- /dev/null +++ b/contrib/gdb-firejail.sh | |||
@@ -0,0 +1,21 @@ | |||
1 | #!/bin/bash | ||
2 | set -x | ||
3 | |||
4 | # gdb setuid helper script. | ||
5 | # This script forks a background process as the current user which will | ||
6 | # immediately send itself a `STOP` signal. Then gdb running as root will | ||
7 | # attach to that process, which will send it the `CONT` signal to continue | ||
8 | # execution. Then the backgrounded process will exec the program with the | ||
9 | # given arguments. This will allow the root gdb to trace the unprivileged | ||
10 | # setuid firejail process from the absolute beginning. | ||
11 | |||
12 | if [ -z "${1##*/firejail}" ]; then | ||
13 | FIREJAIL=$1 | ||
14 | else | ||
15 | # First argument is not named firejail, then add default unless environment | ||
16 | # variable already set. | ||
17 | set -- ${FIREJAIL:=$(which firejail)} "$@" | ||
18 | fi | ||
19 | |||
20 | bash -c "kill -STOP \$\$; exec \"\$0\" \"\$@\"" "$@" & | ||
21 | sudo gdb -e "$FIREJAIL" -p "$!" \ No newline at end of file | ||
diff --git a/etc/celluloid.profile b/etc/celluloid.profile index 89543d6cc..6b7db6b44 100644 --- a/etc/celluloid.profile +++ b/etc/celluloid.profile | |||
@@ -6,8 +6,9 @@ include celluloid.local | |||
6 | # Persistent global definitions | 6 | # Persistent global definitions |
7 | include globals.local | 7 | include globals.local |
8 | 8 | ||
9 | noblacklist ${HOME}/.config/gnome-mpv | ||
10 | noblacklist ${HOME}/.config/celluloid | 9 | noblacklist ${HOME}/.config/celluloid |
10 | noblacklist ${HOME}/.config/gnome-mpv | ||
11 | noblacklist ${HOME}/.config/youtube-dl | ||
11 | noblacklist ${MUSIC} | 12 | noblacklist ${MUSIC} |
12 | noblacklist ${VIDEOS} | 13 | noblacklist ${VIDEOS} |
13 | 14 | ||
diff --git a/etc/conplay.profile b/etc/conplay.profile new file mode 100644 index 000000000..101ce2f17 --- /dev/null +++ b/etc/conplay.profile | |||
@@ -0,0 +1,14 @@ | |||
1 | # Firejail profile for conplay | ||
2 | # Persistent local customizations | ||
3 | include conplay.local | ||
4 | # Persistent global definitions | ||
5 | # added by included profile | ||
6 | #include globals.local | ||
7 | |||
8 | ## system-wide profile | ||
9 | #+ overrides | ||
10 | # Allow perl (blacklisted by disable-interpreters.inc) | ||
11 | include allow-perl.inc | ||
12 | |||
13 | # Redirect | ||
14 | include mpg123.profile | ||
diff --git a/etc/disable-common.inc b/etc/disable-common.inc index ae82d72b5..7ca5a6b89 100644 --- a/etc/disable-common.inc +++ b/etc/disable-common.inc | |||
@@ -134,6 +134,8 @@ blacklist ${RUNUSER}/kdesud_* | |||
134 | # gnome | 134 | # gnome |
135 | # contains extensions, last used times of applications, and notifications | 135 | # contains extensions, last used times of applications, and notifications |
136 | blacklist ${HOME}/.local/share/gnome-shell | 136 | blacklist ${HOME}/.local/share/gnome-shell |
137 | # no direct modification of dconf database | ||
138 | read-only ${HOME}/.config/dconf | ||
137 | 139 | ||
138 | # systemd | 140 | # systemd |
139 | blacklist ${HOME}/.config/systemd | 141 | blacklist ${HOME}/.config/systemd |
diff --git a/etc/disable-programs.inc b/etc/disable-programs.inc index 3e6706101..c061e94a2 100644 --- a/etc/disable-programs.inc +++ b/etc/disable-programs.inc | |||
@@ -319,6 +319,7 @@ blacklist ${HOME}/.config/xviewer | |||
319 | blacklist ${HOME}/.config/yandex-browser | 319 | blacklist ${HOME}/.config/yandex-browser |
320 | blacklist ${HOME}/.config/yandex-browser-beta | 320 | blacklist ${HOME}/.config/yandex-browser-beta |
321 | blacklist ${HOME}/.config/yelp | 321 | blacklist ${HOME}/.config/yelp |
322 | blacklist ${HOME}/.config/youtube-dl | ||
322 | blacklist ${HOME}/.config/zathura | 323 | blacklist ${HOME}/.config/zathura |
323 | blacklist ${HOME}/.config/zoomus.conf | 324 | blacklist ${HOME}/.config/zoomus.conf |
324 | blacklist ${HOME}/.conkeror.mozdev.org | 325 | blacklist ${HOME}/.conkeror.mozdev.org |
diff --git a/etc/firejail.config b/etc/firejail.config index dbe4fb1ea..4c0cb2a41 100644 --- a/etc/firejail.config +++ b/etc/firejail.config | |||
@@ -2,6 +2,9 @@ | |||
2 | # keyword-argument pairs, one per line. Most features are enabled by default. | 2 | # keyword-argument pairs, one per line. Most features are enabled by default. |
3 | # Use 'yes' or 'no' as configuration values. | 3 | # Use 'yes' or 'no' as configuration values. |
4 | 4 | ||
5 | # Allow symbolic links in path of user home directories, default disabled. | ||
6 | # homedir-symlink no | ||
7 | |||
5 | # Enable AppArmor functionality, default enabled. | 8 | # Enable AppArmor functionality, default enabled. |
6 | # apparmor yes | 9 | # apparmor yes |
7 | 10 | ||
@@ -35,6 +38,11 @@ | |||
35 | # cannot be overridden by --noblacklist or --ignore. | 38 | # cannot be overridden by --noblacklist or --ignore. |
36 | # disable-mnt no | 39 | # disable-mnt no |
37 | 40 | ||
41 | # Set the limit for file copy in several --private-* options. The size is set | ||
42 | # in megabytes. By default we allow up to 500MB. | ||
43 | # Note: the files are copied in RAM. | ||
44 | # file-copy-limit 500 | ||
45 | |||
38 | # Enable or disable file transfer support, default enabled. | 46 | # Enable or disable file transfer support, default enabled. |
39 | # file-transfer yes | 47 | # file-transfer yes |
40 | 48 | ||
diff --git a/etc/gajim.profile b/etc/gajim.profile index 74ab9f8b7..85d9b9bd9 100644 --- a/etc/gajim.profile +++ b/etc/gajim.profile | |||
@@ -20,6 +20,7 @@ include disable-exec.inc | |||
20 | include disable-interpreters.inc | 20 | include disable-interpreters.inc |
21 | include disable-passwdmgr.inc | 21 | include disable-passwdmgr.inc |
22 | include disable-programs.inc | 22 | include disable-programs.inc |
23 | # Comment the following line if you need to whitelist other folders than ~/Downloads | ||
23 | include disable-xdg.inc | 24 | include disable-xdg.inc |
24 | 25 | ||
25 | mkdir ${HOME}/.cache/gajim | 26 | mkdir ${HOME}/.cache/gajim |
diff --git a/etc/galculator.profile b/etc/galculator.profile index 3dda48192..f757aed69 100644 --- a/etc/galculator.profile +++ b/etc/galculator.profile | |||
@@ -47,4 +47,4 @@ private-etc alternatives,fonts | |||
47 | private-lib | 47 | private-lib |
48 | private-tmp | 48 | private-tmp |
49 | 49 | ||
50 | memory-deny-write-execute | 50 | #memory-deny-write-execute - breaks on Arch (see issue #1803) |
diff --git a/etc/less.profile b/etc/less.profile index e6366ad28..0f31d344b 100644 --- a/etc/less.profile +++ b/etc/less.profile | |||
@@ -8,13 +8,13 @@ include less.local | |||
8 | include globals.local | 8 | include globals.local |
9 | 9 | ||
10 | noblacklist ${HOME}/.lesshst | 10 | noblacklist ${HOME}/.lesshst |
11 | read-only ${HOME} | ||
12 | read-write ${HOME}/.lesshst | ||
11 | 13 | ||
12 | include disable-common.inc | ||
13 | include disable-devel.inc | 14 | include disable-devel.inc |
14 | include disable-exec.inc | 15 | include disable-exec.inc |
15 | include disable-interpreters.inc | 16 | include disable-interpreters.inc |
16 | include disable-passwdmgr.inc | 17 | include disable-passwdmgr.inc |
17 | include disable-programs.inc | ||
18 | 18 | ||
19 | apparmor | 19 | apparmor |
20 | caps.drop all | 20 | caps.drop all |
diff --git a/etc/mpg123-alsa.profile b/etc/mpg123-alsa.profile new file mode 100644 index 000000000..378435af1 --- /dev/null +++ b/etc/mpg123-alsa.profile | |||
@@ -0,0 +1,9 @@ | |||
1 | # Firejail profile for mpg123-alsa | ||
2 | # Persistent local customizations | ||
3 | include mpg123-alsa.local | ||
4 | # Persistent global definitions | ||
5 | # added by included profile | ||
6 | #include globals.local | ||
7 | |||
8 | # Redirect | ||
9 | include mpg123.profile | ||
diff --git a/etc/mpg123-id3dump.profile b/etc/mpg123-id3dump.profile new file mode 100644 index 000000000..370a57b3c --- /dev/null +++ b/etc/mpg123-id3dump.profile | |||
@@ -0,0 +1,12 @@ | |||
1 | # Firejail profile for mpg123-id3dump | ||
2 | # Persistent local customizations | ||
3 | include mpg123-id3dump.local | ||
4 | # Persistent global definitions | ||
5 | # added by included profile | ||
6 | #include globals.local | ||
7 | |||
8 | machine-id | ||
9 | nosound | ||
10 | |||
11 | # Redirect | ||
12 | include mpg123.profile | ||
diff --git a/etc/mpg123-jack.profile b/etc/mpg123-jack.profile new file mode 100644 index 000000000..e36a2e5b3 --- /dev/null +++ b/etc/mpg123-jack.profile | |||
@@ -0,0 +1,9 @@ | |||
1 | # Firejail profile for mpg123-jack | ||
2 | # Persistent local customizations | ||
3 | include mpg123-jack.local | ||
4 | # Persistent global definitions | ||
5 | # added by included profile | ||
6 | #include globals.local | ||
7 | |||
8 | # Redirect | ||
9 | include mpg123.profile | ||
diff --git a/etc/mpg123-nas.profile b/etc/mpg123-nas.profile new file mode 100644 index 000000000..cdbf0b1d2 --- /dev/null +++ b/etc/mpg123-nas.profile | |||
@@ -0,0 +1,9 @@ | |||
1 | # Firejail profile for mpg123-nas | ||
2 | # Persistent local customizations | ||
3 | include mpg123-nas.local | ||
4 | # Persistent global definitions | ||
5 | # added by included profile | ||
6 | #include globals.local | ||
7 | |||
8 | # Redirect | ||
9 | include mpg123.profile | ||
diff --git a/etc/mpg123-openal.profile b/etc/mpg123-openal.profile new file mode 100644 index 000000000..e5585feaa --- /dev/null +++ b/etc/mpg123-openal.profile | |||
@@ -0,0 +1,9 @@ | |||
1 | # Firejail profile for mpg123-openal | ||
2 | # Persistent local customizations | ||
3 | include mpg123-openal.local | ||
4 | # Persistent global definitions | ||
5 | # added by included profile | ||
6 | #include globals.local | ||
7 | |||
8 | # Redirect | ||
9 | include mpg123.profile | ||
diff --git a/etc/mpg123-oss.profile b/etc/mpg123-oss.profile new file mode 100644 index 000000000..dcb92ecd6 --- /dev/null +++ b/etc/mpg123-oss.profile | |||
@@ -0,0 +1,9 @@ | |||
1 | # Firejail profile for mpg123-oss | ||
2 | # Persistent local customizations | ||
3 | include mpg123-oss.local | ||
4 | # Persistent global definitions | ||
5 | # added by included profile | ||
6 | #include globals.local | ||
7 | |||
8 | # Redirect | ||
9 | include mpg123.profile | ||
diff --git a/etc/mpg123-portaudio.profile b/etc/mpg123-portaudio.profile new file mode 100644 index 000000000..319843504 --- /dev/null +++ b/etc/mpg123-portaudio.profile | |||
@@ -0,0 +1,9 @@ | |||
1 | # Firejail profile for mpg123-portaudio | ||
2 | # Persistent local customizations | ||
3 | include mpg123-portaudio.local | ||
4 | # Persistent global definitions | ||
5 | # added by included profile | ||
6 | #include globals.local | ||
7 | |||
8 | # Redirect | ||
9 | include mpg123.profile | ||
diff --git a/etc/mpg123-pulse.profile b/etc/mpg123-pulse.profile new file mode 100644 index 000000000..31063a96b --- /dev/null +++ b/etc/mpg123-pulse.profile | |||
@@ -0,0 +1,9 @@ | |||
1 | # Firejail profile for mpg123-pulse | ||
2 | # Persistent local customizations | ||
3 | include mpg123-pulse.local | ||
4 | # Persistent global definitions | ||
5 | # added by included profile | ||
6 | #include globals.local | ||
7 | |||
8 | # Redirect | ||
9 | include mpg123.profile | ||
diff --git a/etc/mpg123-strip.profile b/etc/mpg123-strip.profile new file mode 100644 index 000000000..62de57c22 --- /dev/null +++ b/etc/mpg123-strip.profile | |||
@@ -0,0 +1,9 @@ | |||
1 | # Firejail profile for mpg123-strip | ||
2 | # Persistent local customizations | ||
3 | include mpg123-strip.local | ||
4 | # Persistent global definitions | ||
5 | # added by included profile | ||
6 | #include globals.local | ||
7 | |||
8 | # Redirect | ||
9 | include mpg123.profile | ||
diff --git a/etc/mpg123.bin.profile b/etc/mpg123.bin.profile new file mode 100644 index 000000000..0a01d0829 --- /dev/null +++ b/etc/mpg123.bin.profile | |||
@@ -0,0 +1,9 @@ | |||
1 | # Firejail profile for mpg123.bin | ||
2 | # Persistent local customizations | ||
3 | include mpg123.bin.local | ||
4 | # Persistent global definitions | ||
5 | # added by included profile | ||
6 | #include globals.local | ||
7 | |||
8 | # Redirect | ||
9 | include mpg123.profile | ||
diff --git a/etc/mpg123.profile b/etc/mpg123.profile new file mode 100644 index 000000000..8a8907c39 --- /dev/null +++ b/etc/mpg123.profile | |||
@@ -0,0 +1,38 @@ | |||
1 | # Firejail profile for mpg123 | ||
2 | # Description: MPEG audio player/decoder | ||
3 | # This file is overwritten after every install/update | ||
4 | # Persistent local customizations | ||
5 | include mpg123.local | ||
6 | # Persistent global definitions | ||
7 | include globals.local | ||
8 | |||
9 | noblacklist ${MUSIC} | ||
10 | noblacklist ${VIDEOS} | ||
11 | |||
12 | include disable-common.inc | ||
13 | include disable-devel.inc | ||
14 | include disable-exec.inc | ||
15 | include disable-interpreters.inc | ||
16 | include disable-passwdmgr.inc | ||
17 | include disable-programs.inc | ||
18 | include disable-xdg.inc | ||
19 | |||
20 | include whitelist-var-common.inc | ||
21 | |||
22 | apparmor | ||
23 | caps.drop all | ||
24 | netfilter | ||
25 | nodbus | ||
26 | nogroups | ||
27 | nonewprivs | ||
28 | noroot | ||
29 | nou2f | ||
30 | protocol unix,inet,inet6,netlink | ||
31 | seccomp | ||
32 | shell none | ||
33 | |||
34 | #private-bin mpg123* | ||
35 | private-dev | ||
36 | private-tmp | ||
37 | |||
38 | memory-deny-write-execute | ||
diff --git a/etc/mpsyt.profile b/etc/mpsyt.profile index f0309da9a..878a5f654 100644 --- a/etc/mpsyt.profile +++ b/etc/mpsyt.profile | |||
@@ -8,6 +8,7 @@ include globals.local | |||
8 | 8 | ||
9 | noblacklist ${HOME}/.config/mps-youtube | 9 | noblacklist ${HOME}/.config/mps-youtube |
10 | noblacklist ${HOME}/.config/mpv | 10 | noblacklist ${HOME}/.config/mpv |
11 | noblacklist ${HOME}/.config/youtube-dl | ||
11 | noblacklist ${HOME}/.mplayer | 12 | noblacklist ${HOME}/.mplayer |
12 | noblacklist ${HOME}/.netrc | 13 | noblacklist ${HOME}/.netrc |
13 | noblacklist ${HOME}/mps | 14 | noblacklist ${HOME}/mps |
@@ -29,10 +30,12 @@ include disable-xdg.inc | |||
29 | 30 | ||
30 | mkdir ${HOME}/.config/mps-youtube | 31 | mkdir ${HOME}/.config/mps-youtube |
31 | mkdir ${HOME}/.config/mpv | 32 | mkdir ${HOME}/.config/mpv |
33 | mkdir ${HOME}/.config/youtube-dl | ||
32 | mkdir ${HOME}/.mplayer | 34 | mkdir ${HOME}/.mplayer |
33 | mkdir ${HOME}/mps | 35 | mkdir ${HOME}/mps |
34 | whitelist ${HOME}/.config/mps-youtube | 36 | whitelist ${HOME}/.config/mps-youtube |
35 | whitelist ${HOME}/.config/mpv | 37 | whitelist ${HOME}/.config/mpv |
38 | whitelist ${HOME}/.config/youtube-dl | ||
36 | whitelist ${HOME}/.mplayer | 39 | whitelist ${HOME}/.mplayer |
37 | whitelist ${HOME}/.netrc | 40 | whitelist ${HOME}/.netrc |
38 | whitelist ${HOME}/mps | 41 | whitelist ${HOME}/mps |
diff --git a/etc/mpv.profile b/etc/mpv.profile index 07a6ba42b..d8163d20a 100644 --- a/etc/mpv.profile +++ b/etc/mpv.profile | |||
@@ -8,6 +8,7 @@ include mpv.local | |||
8 | include globals.local | 8 | include globals.local |
9 | 9 | ||
10 | noblacklist ${HOME}/.config/mpv | 10 | noblacklist ${HOME}/.config/mpv |
11 | noblacklist ${HOME}/.config/youtube-dl | ||
11 | noblacklist ${HOME}/.netrc | 12 | noblacklist ${HOME}/.netrc |
12 | 13 | ||
13 | # Allow python (blacklisted by disable-interpreters.inc) | 14 | # Allow python (blacklisted by disable-interpreters.inc) |
@@ -42,5 +43,6 @@ shell none | |||
42 | tracelog | 43 | tracelog |
43 | 44 | ||
44 | private-bin env,mpv,python*,youtube-dl | 45 | private-bin env,mpv,python*,youtube-dl |
45 | private-cache | 46 | # Causes slow OSD, see #2838 |
47 | #private-cache | ||
46 | private-dev | 48 | private-dev |
diff --git a/etc/mumble.profile b/etc/mumble.profile index 2d8607e53..94ccbad0c 100644 --- a/etc/mumble.profile +++ b/etc/mumble.profile | |||
@@ -43,4 +43,4 @@ disable-mnt | |||
43 | private-bin mumble | 43 | private-bin mumble |
44 | private-tmp | 44 | private-tmp |
45 | 45 | ||
46 | memory-deny-write-execute | 46 | #memory-deny-write-execute - breaks on Arch (see issue #1803) |
diff --git a/etc/obs.profile b/etc/obs.profile index 038242cae..4277bdab3 100644 --- a/etc/obs.profile +++ b/etc/obs.profile | |||
@@ -36,7 +36,7 @@ seccomp | |||
36 | shell none | 36 | shell none |
37 | tracelog | 37 | tracelog |
38 | 38 | ||
39 | private-bin obs,python* | 39 | private-bin bash,obs,obs-ffmpeg-mux,python*,sh |
40 | private-cache | 40 | private-cache |
41 | private-dev | 41 | private-dev |
42 | private-tmp | 42 | private-tmp |
diff --git a/etc/out123.profile b/etc/out123.profile new file mode 100644 index 000000000..4754c05ba --- /dev/null +++ b/etc/out123.profile | |||
@@ -0,0 +1,9 @@ | |||
1 | # Firejail profile for out123 | ||
2 | # Persistent local customizations | ||
3 | include out123.local | ||
4 | # Persistent global definitions | ||
5 | # added by included profile | ||
6 | #include globals.local | ||
7 | |||
8 | # Redirect | ||
9 | include mpg123.profile | ||
diff --git a/etc/pavucontrol.profile b/etc/pavucontrol.profile index 621fef49f..e74394b22 100644 --- a/etc/pavucontrol.profile +++ b/etc/pavucontrol.profile | |||
@@ -45,4 +45,4 @@ private-etc alternatives,asound.conf,avahi,fonts,machine-id,pulse | |||
45 | private-lib | 45 | private-lib |
46 | private-tmp | 46 | private-tmp |
47 | 47 | ||
48 | memory-deny-write-execute | 48 | #memory-deny-write-execute - breaks on Arch (see issue #1803) |
diff --git a/etc/qpdfview.profile b/etc/qpdfview.profile index 6cb3fe4cd..abbd76aff 100644 --- a/etc/qpdfview.profile +++ b/etc/qpdfview.profile | |||
@@ -22,6 +22,7 @@ include whitelist-var-common.inc | |||
22 | 22 | ||
23 | caps.drop all | 23 | caps.drop all |
24 | machine-id | 24 | machine-id |
25 | nodbus | ||
25 | nodvd | 26 | nodvd |
26 | nogroups | 27 | nogroups |
27 | nonewprivs | 28 | nonewprivs |
@@ -38,5 +39,3 @@ tracelog | |||
38 | private-bin qpdfview | 39 | private-bin qpdfview |
39 | private-dev | 40 | private-dev |
40 | private-tmp | 41 | private-tmp |
41 | |||
42 | memory-deny-write-execute | ||
diff --git a/etc/riot-desktop.profile b/etc/riot-desktop.profile index e91d25196..e6af4c2cb 100644 --- a/etc/riot-desktop.profile +++ b/etc/riot-desktop.profile | |||
@@ -7,5 +7,8 @@ include riot-desktop.local | |||
7 | # added by included profile | 7 | # added by included profile |
8 | #include globals.local | 8 | #include globals.local |
9 | 9 | ||
10 | ignore seccomp | ||
11 | seccomp.drop @clock,@cpu-emulation,@debug,@module,@obsolete,@raw-io,@reboot,@resources,@swap,acct,add_key,bpf,fanotify_init,io_cancel,io_destroy,io_getevents,io_setup,io_submit,ioprio_set,kcmp,keyctl,mincore,mount,name_to_handle_at,nfsservctl,ni_syscall,open_by_handle_at,pivot_root,remap_file_pages,request_key,setdomainname,sethostname,syslog,umount,umount2,userfaultfd,vhangup,vmsplice | ||
12 | |||
10 | # Redirect | 13 | # Redirect |
11 | include riot-web.profile | 14 | include riot-web.profile |
diff --git a/etc/smplayer.profile b/etc/smplayer.profile index f83caee8a..c7324e6ca 100644 --- a/etc/smplayer.profile +++ b/etc/smplayer.profile | |||
@@ -7,6 +7,7 @@ include smplayer.local | |||
7 | include globals.local | 7 | include globals.local |
8 | 8 | ||
9 | noblacklist ${HOME}/.config/smplayer | 9 | noblacklist ${HOME}/.config/smplayer |
10 | noblacklist ${HOME}/.config/youtube-dl | ||
10 | noblacklist ${HOME}/.mplayer | 11 | noblacklist ${HOME}/.mplayer |
11 | 12 | ||
12 | # Allow python (blacklisted by disable-interpreters.inc) | 13 | # Allow python (blacklisted by disable-interpreters.inc) |
diff --git a/etc/wire-desktop.profile b/etc/wire-desktop.profile index f41453bf3..490255fa6 100644 --- a/etc/wire-desktop.profile +++ b/etc/wire-desktop.profile | |||
@@ -34,7 +34,7 @@ shell none | |||
34 | # it is not in PATH. To use Wire with firejail, run "firejail /opt/wire-desktop/wire-desktop" | 34 | # it is not in PATH. To use Wire with firejail, run "firejail /opt/wire-desktop/wire-desktop" |
35 | 35 | ||
36 | disable-mnt | 36 | disable-mnt |
37 | private-bin bash,electron,env,sh,wire-desktop | 37 | private-bin bash,electron,electron4,env,sh,wire-desktop |
38 | private-dev | 38 | private-dev |
39 | private-etc alternatives,ca-certificates,crypto-policies,fonts,machine-id,pki,resolv.conf,ssl | 39 | private-etc alternatives,ca-certificates,crypto-policies,fonts,machine-id,pki,resolv.conf,ssl |
40 | private-tmp | 40 | private-tmp |
diff --git a/etc/youtube-dl.profile b/etc/youtube-dl.profile index 28b5f2376..6fc519bee 100644 --- a/etc/youtube-dl.profile +++ b/etc/youtube-dl.profile | |||
@@ -7,9 +7,10 @@ include youtube-dl.local | |||
7 | # Persistent global definitions | 7 | # Persistent global definitions |
8 | include globals.local | 8 | include globals.local |
9 | 9 | ||
10 | # breaks when installed via pip | 10 | # breaks when installed under ${HOME} via `pip install --user` (see #2833) |
11 | ignore noexec ${HOME} | 11 | ignore noexec ${HOME} |
12 | 12 | ||
13 | noblacklist ${HOME}/.config/youtube-dl | ||
13 | noblacklist ${HOME}/.netrc | 14 | noblacklist ${HOME}/.netrc |
14 | noblacklist ${MUSIC} | 15 | noblacklist ${MUSIC} |
15 | noblacklist ${VIDEOS} | 16 | noblacklist ${VIDEOS} |
@@ -48,7 +49,6 @@ seccomp | |||
48 | shell none | 49 | shell none |
49 | tracelog | 50 | tracelog |
50 | 51 | ||
51 | disable-mnt | ||
52 | private-bin env,ffmpeg,python*,youtube-dl | 52 | private-bin env,ffmpeg,python*,youtube-dl |
53 | private-cache | 53 | private-cache |
54 | private-dev | 54 | private-dev |
diff --git a/src/fcopy/main.c b/src/fcopy/main.c index 9fca2a39b..3f507a361 100644 --- a/src/fcopy/main.c +++ b/src/fcopy/main.c | |||
@@ -25,9 +25,11 @@ | |||
25 | #include <pwd.h> | 25 | #include <pwd.h> |
26 | 26 | ||
27 | int arg_quiet = 0; | 27 | int arg_quiet = 0; |
28 | int arg_debug = 0; | ||
28 | static int arg_follow_link = 0; | 29 | static int arg_follow_link = 0; |
29 | 30 | ||
30 | #define COPY_LIMIT (500 * 1024 *1024) | 31 | static int copy_limit = 500 * 1024 *1024; // 500 MB |
32 | #define COPY_LIMIT ( | ||
31 | static int size_limit_reached = 0; | 33 | static int size_limit_reached = 0; |
32 | static unsigned file_cnt = 0; | 34 | static unsigned file_cnt = 0; |
33 | static unsigned size_cnt = 0; | 35 | static unsigned size_cnt = 0; |
@@ -184,8 +186,8 @@ static int fs_copydir(const char *infname, const struct stat *st, int ftype, str | |||
184 | mode_t mode = s.st_mode; | 186 | mode_t mode = s.st_mode; |
185 | 187 | ||
186 | // recalculate size | 188 | // recalculate size |
187 | if ((s.st_size + size_cnt) > COPY_LIMIT) { | 189 | if ((s.st_size + size_cnt) > copy_limit) { |
188 | fprintf(stderr, "Error fcopy: size limit of %dMB reached\n", (COPY_LIMIT / 1024) / 1024); | 190 | fprintf(stderr, "Error fcopy: size limit of %dMB reached\n", (copy_limit / 1024) / 1024); |
189 | size_limit_reached = 1; | 191 | size_limit_reached = 1; |
190 | free(outfname); | 192 | free(outfname); |
191 | return 0; | 193 | return 0; |
@@ -330,6 +332,9 @@ int main(int argc, char **argv) { | |||
330 | char *quiet = getenv("FIREJAIL_QUIET"); | 332 | char *quiet = getenv("FIREJAIL_QUIET"); |
331 | if (quiet && strcmp(quiet, "yes") == 0) | 333 | if (quiet && strcmp(quiet, "yes") == 0) |
332 | arg_quiet = 1; | 334 | arg_quiet = 1; |
335 | char *debug = getenv("FIREJAIL_DEBUG"); | ||
336 | if (debug && strcmp(debug, "yes") == 0) | ||
337 | arg_debug = 1; | ||
333 | 338 | ||
334 | char *src; | 339 | char *src; |
335 | char *dest; | 340 | char *dest; |
@@ -384,6 +389,14 @@ int main(int argc, char **argv) { | |||
384 | exit(1); | 389 | exit(1); |
385 | } | 390 | } |
386 | 391 | ||
392 | // extract copy limit size from env variable, if any | ||
393 | char *cl = getenv("FIREJAIL_FILE_COPY_LIMIT"); | ||
394 | if (cl) { | ||
395 | copy_limit = atoi(cl) * 1024 * 1024; | ||
396 | if (arg_debug) | ||
397 | printf("file copy limit %d bytes\n", copy_limit); | ||
398 | } | ||
399 | |||
387 | // copy files | 400 | // copy files |
388 | if ((arg_follow_link ? stat : lstat)(src, &s) == -1) { | 401 | if ((arg_follow_link ? stat : lstat)(src, &s) == -1) { |
389 | fprintf(stderr, "Error fcopy: src %s: %s\n", src, strerror(errno)); | 402 | fprintf(stderr, "Error fcopy: src %s: %s\n", src, strerror(errno)); |
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config index 04bf123ad..95ad95e95 100644 --- a/src/firecfg/firecfg.config +++ b/src/firecfg/firecfg.config | |||
@@ -119,6 +119,7 @@ code | |||
119 | code-oss | 119 | code-oss |
120 | conkeror | 120 | conkeror |
121 | conky | 121 | conky |
122 | conplay | ||
122 | corebird | 123 | corebird |
123 | crawl | 124 | crawl |
124 | crawl-tiles | 125 | crawl-tiles |
@@ -379,6 +380,17 @@ mp3splt | |||
379 | mp3splt-gtk | 380 | mp3splt-gtk |
380 | mp3wrap | 381 | mp3wrap |
381 | mpDris2 | 382 | mpDris2 |
383 | mpg123 | ||
384 | mpg123.bin | ||
385 | mpg123-alsa | ||
386 | mpg123-id3dump | ||
387 | mpg123-jack | ||
388 | mpg123-nas | ||
389 | mpg123-openal | ||
390 | mpg123-oss | ||
391 | mpg123-portaudio | ||
392 | mpg123-pulse | ||
393 | mpg123-strip | ||
382 | mplayer | 394 | mplayer |
383 | mpsyt | 395 | mpsyt |
384 | mpv | 396 | mpv |
@@ -432,6 +444,7 @@ opera | |||
432 | opera-beta | 444 | opera-beta |
433 | orage | 445 | orage |
434 | ostrichriders | 446 | ostrichriders |
447 | out123 | ||
435 | palemoon | 448 | palemoon |
436 | pandoc | 449 | pandoc |
437 | parole | 450 | parole |
diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c index 7c60d9189..1da765d8f 100644 --- a/src/firejail/appimage.c +++ b/src/firejail/appimage.c | |||
@@ -126,16 +126,25 @@ void appimage_set(const char *appimage) { | |||
126 | printf("appimage mounted on %s\n", mntdir); | 126 | printf("appimage mounted on %s\n", mntdir); |
127 | EUID_USER(); | 127 | EUID_USER(); |
128 | 128 | ||
129 | char* abspath = realpath(appimage, NULL); | ||
130 | if (abspath == NULL) | ||
131 | errExit("Failed to obtain absolute path"); | ||
132 | |||
129 | // set environment | 133 | // set environment |
130 | if (setenv("APPIMAGE", appimage, 1) < 0) | 134 | if (setenv("APPIMAGE", abspath, 1) < 0) |
131 | errExit("setenv"); | 135 | errExit("setenv"); |
132 | if (mntdir && setenv("APPDIR", mntdir, 1) < 0) | 136 | if (mntdir && setenv("APPDIR", mntdir, 1) < 0) |
133 | errExit("setenv"); | 137 | errExit("setenv"); |
138 | if (size != 0 && setenv("ARGV0", appimage, 1) < 0) | ||
139 | errExit("setenv"); | ||
140 | if (setenv("OWD", cfg.cwd, 1) < 0) | ||
141 | errExit("setenv"); | ||
134 | 142 | ||
135 | // build new command line | 143 | // build new command line |
136 | if (asprintf(&cfg.command_line, "%s/AppRun", mntdir) == -1) | 144 | if (asprintf(&cfg.command_line, "%s/AppRun", mntdir) == -1) |
137 | errExit("asprintf"); | 145 | errExit("asprintf"); |
138 | 146 | ||
147 | free(abspath); | ||
139 | free(mode); | 148 | free(mode); |
140 | #ifdef HAVE_GCOV | 149 | #ifdef HAVE_GCOV |
141 | __gcov_flush(); | 150 | __gcov_flush(); |
diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c index b11d795a9..84054fe76 100644 --- a/src/firejail/checkcfg.c +++ b/src/firejail/checkcfg.c | |||
@@ -50,6 +50,7 @@ int checkcfg(int val) { | |||
50 | cfg_val[CFG_DISABLE_MNT] = 0; | 50 | cfg_val[CFG_DISABLE_MNT] = 0; |
51 | cfg_val[CFG_ARP_PROBES] = DEFAULT_ARP_PROBES; | 51 | cfg_val[CFG_ARP_PROBES] = DEFAULT_ARP_PROBES; |
52 | cfg_val[CFG_XPRA_ATTACH] = 0; | 52 | cfg_val[CFG_XPRA_ATTACH] = 0; |
53 | cfg_val[CFG_HOMEDIR_SYMLINK] = 0; | ||
53 | 54 | ||
54 | // open configuration file | 55 | // open configuration file |
55 | const char *fname = SYSCONFDIR "/firejail.config"; | 56 | const char *fname = SYSCONFDIR "/firejail.config"; |
@@ -85,6 +86,7 @@ int checkcfg(int val) { | |||
85 | ptr = line_remove_spaces(buf); | 86 | ptr = line_remove_spaces(buf); |
86 | if (!ptr) | 87 | if (!ptr) |
87 | continue; | 88 | continue; |
89 | PARSE_YESNO(CFG_HOMEDIR_SYMLINK, "homedir-symlink") | ||
88 | PARSE_YESNO(CFG_FILE_TRANSFER, "file-transfer") | 90 | PARSE_YESNO(CFG_FILE_TRANSFER, "file-transfer") |
89 | PARSE_YESNO(CFG_DBUS, "dbus") | 91 | PARSE_YESNO(CFG_DBUS, "dbus") |
90 | PARSE_YESNO(CFG_JOIN, "join") | 92 | PARSE_YESNO(CFG_JOIN, "join") |
@@ -207,6 +209,12 @@ int checkcfg(int val) { | |||
207 | goto errout; | 209 | goto errout; |
208 | cfg_val[CFG_ARP_PROBES] = arp_probes; | 210 | cfg_val[CFG_ARP_PROBES] = arp_probes; |
209 | } | 211 | } |
212 | |||
213 | // file copy limit | ||
214 | else if (strncmp(ptr, "file-copy-limit ", 16) == 0) { | ||
215 | if (setenv("FIREJAIL_FILE_COPY_LIMIT", ptr + 16, 1) == -1) | ||
216 | errExit("setenv"); | ||
217 | } | ||
210 | else | 218 | else |
211 | goto errout; | 219 | goto errout; |
212 | 220 | ||
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 630adc3d7..4bd70697e 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -720,6 +720,8 @@ enum { | |||
720 | CFG_PRIVATE_CACHE, | 720 | CFG_PRIVATE_CACHE, |
721 | CFG_CGROUP, | 721 | CFG_CGROUP, |
722 | CFG_NAME_CHANGE, | 722 | CFG_NAME_CHANGE, |
723 | CFG_HOMEDIR_SYMLINK, | ||
724 | // CFG_FILE_COPY_LIMIT - file copy limit handled using setenv/getenv | ||
723 | CFG_MAX // this should always be the last entry | 725 | CFG_MAX // this should always be the last entry |
724 | }; | 726 | }; |
725 | extern char *xephyr_screen; | 727 | extern char *xephyr_screen; |
diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 9a15d825e..ce2ca5e2a 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c | |||
@@ -441,6 +441,8 @@ static int get_mount_flags(const char *path, unsigned long *flags) { | |||
441 | // mount a writable tmpfs on directory | 441 | // mount a writable tmpfs on directory |
442 | void fs_tmpfs(const char *dir, unsigned check_owner) { | 442 | void fs_tmpfs(const char *dir, unsigned check_owner) { |
443 | assert(dir); | 443 | assert(dir); |
444 | if (arg_debug) | ||
445 | printf("Mounting tmpfs on %s\n", dir); | ||
444 | // get a file descriptor for dir, fails if there is any symlink | 446 | // get a file descriptor for dir, fails if there is any symlink |
445 | int fd = safe_fd(dir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); | 447 | int fd = safe_fd(dir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); |
446 | if (fd == -1) | 448 | if (fd == -1) |
@@ -449,12 +451,9 @@ void fs_tmpfs(const char *dir, unsigned check_owner) { | |||
449 | if (fstat(fd, &s) == -1) | 451 | if (fstat(fd, &s) == -1) |
450 | errExit("fstat"); | 452 | errExit("fstat"); |
451 | if (check_owner && s.st_uid != getuid()) { | 453 | if (check_owner && s.st_uid != getuid()) { |
452 | fwarning("no tmpfs mounted on %s: not owned by the current user\n", dir); | 454 | fprintf(stderr, "Error: cannot mount tmpfs on %s: not owned by the current user\n", dir); |
453 | close(fd); | 455 | exit(1); |
454 | return; | ||
455 | } | 456 | } |
456 | if (arg_debug) | ||
457 | printf("Mounting tmpfs on %s\n", dir); | ||
458 | // preserve ownership, mode | 457 | // preserve ownership, mode |
459 | char *options; | 458 | char *options; |
460 | if (asprintf(&options, "mode=%o,uid=%u,gid=%u", s.st_mode & 07777, s.st_uid, s.st_gid) == -1) | 459 | if (asprintf(&options, "mode=%o,uid=%u,gid=%u", s.st_mode & 07777, s.st_uid, s.st_gid) == -1) |
@@ -1127,11 +1126,36 @@ void fs_overlayfs(void) { | |||
1127 | 1126 | ||
1128 | #ifdef HAVE_CHROOT | 1127 | #ifdef HAVE_CHROOT |
1129 | // exit if error | 1128 | // exit if error |
1129 | static void fs_check_chroot_subdir(const char *subdir, int parentfd, int check_writable) { | ||
1130 | assert(subdir); | ||
1131 | int fd = openat(parentfd, subdir, O_PATH|O_CLOEXEC); | ||
1132 | if (fd == -1) { | ||
1133 | if (errno == ENOENT) | ||
1134 | fprintf(stderr, "Error: cannot find /%s in chroot directory\n", subdir); | ||
1135 | else { | ||
1136 | perror("open"); | ||
1137 | fprintf(stderr, "Error: cannot open /%s in chroot directory\n", subdir); | ||
1138 | } | ||
1139 | exit(1); | ||
1140 | } | ||
1141 | struct stat s; | ||
1142 | if (fstat(fd, &s) == -1) | ||
1143 | errExit("fstat"); | ||
1144 | close(fd); | ||
1145 | if (!S_ISDIR(s.st_mode) || s.st_uid != 0) { | ||
1146 | fprintf(stderr, "Error: chroot /%s should be a directory owned by root\n", subdir); | ||
1147 | exit(1); | ||
1148 | } | ||
1149 | if (check_writable && ((S_IWGRP|S_IWOTH) & s.st_mode) != 0) { | ||
1150 | fprintf(stderr, "Error: only root user should be given write permission on chroot /%s\n", subdir); | ||
1151 | exit(1); | ||
1152 | } | ||
1153 | } | ||
1154 | |||
1155 | // exit if error | ||
1130 | void fs_check_chroot_dir(const char *rootdir) { | 1156 | void fs_check_chroot_dir(const char *rootdir) { |
1131 | EUID_ASSERT(); | 1157 | EUID_ASSERT(); |
1132 | assert(rootdir); | 1158 | assert(rootdir); |
1133 | char *dir = EMPTY_STRING; | ||
1134 | struct stat s; | ||
1135 | 1159 | ||
1136 | char *overlay; | 1160 | char *overlay; |
1137 | if (asprintf(&overlay, "%s/.firejail", cfg.homedir) == -1) | 1161 | if (asprintf(&overlay, "%s/.firejail", cfg.homedir) == -1) |
@@ -1150,6 +1174,7 @@ void fs_check_chroot_dir(const char *rootdir) { | |||
1150 | } | 1174 | } |
1151 | // rootdir has to be owned by root and is not allowed to be generally writable, | 1175 | // rootdir has to be owned by root and is not allowed to be generally writable, |
1152 | // this also excludes /tmp, /var/tmp and such | 1176 | // this also excludes /tmp, /var/tmp and such |
1177 | struct stat s; | ||
1153 | if (fstat(parentfd, &s) == -1) | 1178 | if (fstat(parentfd, &s) == -1) |
1154 | errExit("fstat"); | 1179 | errExit("fstat"); |
1155 | if (s.st_uid != 0) { | 1180 | if (s.st_uid != 0) { |
@@ -1161,64 +1186,12 @@ void fs_check_chroot_dir(const char *rootdir) { | |||
1161 | exit(1); | 1186 | exit(1); |
1162 | } | 1187 | } |
1163 | 1188 | ||
1164 | // check /dev | 1189 | // check subdirectories in rootdir |
1165 | dir = "dev"; | 1190 | fs_check_chroot_subdir("dev", parentfd, 0); |
1166 | int fd = openat(parentfd, dir, O_PATH|O_CLOEXEC); | 1191 | fs_check_chroot_subdir("etc", parentfd, 1); |
1167 | if (fd == -1) | 1192 | fs_check_chroot_subdir("proc", parentfd, 0); |
1168 | goto error1; | 1193 | fs_check_chroot_subdir("tmp", parentfd, 0); |
1169 | if (fstat(fd, &s) == -1) | 1194 | fs_check_chroot_subdir("var/tmp", parentfd, 0); |
1170 | errExit("fstat"); | ||
1171 | if (!S_ISDIR(s.st_mode) || s.st_uid != 0) | ||
1172 | goto error2; | ||
1173 | close(fd); | ||
1174 | |||
1175 | // check /var/tmp | ||
1176 | dir = "var/tmp"; | ||
1177 | fd = openat(parentfd, dir, O_PATH|O_CLOEXEC); | ||
1178 | if (fd == -1) | ||
1179 | goto error1; | ||
1180 | if (fstat(fd, &s) == -1) | ||
1181 | errExit("fstat"); | ||
1182 | if (!S_ISDIR(s.st_mode) || s.st_uid != 0) | ||
1183 | goto error2; | ||
1184 | close(fd); | ||
1185 | |||
1186 | // check /proc | ||
1187 | dir = "proc"; | ||
1188 | fd = openat(parentfd, dir, O_PATH|O_CLOEXEC); | ||
1189 | if (fd == -1) | ||
1190 | goto error1; | ||
1191 | if (fstat(fd, &s) == -1) | ||
1192 | errExit("fstat"); | ||
1193 | if (!S_ISDIR(s.st_mode) || s.st_uid != 0) | ||
1194 | goto error2; | ||
1195 | close(fd); | ||
1196 | |||
1197 | // check /tmp | ||
1198 | dir = "tmp"; | ||
1199 | fd = openat(parentfd, dir, O_PATH|O_CLOEXEC); | ||
1200 | if (fd == -1) | ||
1201 | goto error1; | ||
1202 | if (fstat(fd, &s) == -1) | ||
1203 | errExit("fstat"); | ||
1204 | if (!S_ISDIR(s.st_mode) || s.st_uid != 0) | ||
1205 | goto error2; | ||
1206 | close(fd); | ||
1207 | |||
1208 | // check /etc | ||
1209 | dir = "etc"; | ||
1210 | fd = openat(parentfd, dir, O_PATH|O_CLOEXEC); | ||
1211 | if (fd == -1) | ||
1212 | goto error1; | ||
1213 | if (fstat(fd, &s) == -1) | ||
1214 | errExit("fstat"); | ||
1215 | if (!S_ISDIR(s.st_mode) || s.st_uid != 0) | ||
1216 | goto error2; | ||
1217 | if (((S_IWGRP|S_IWOTH) & s.st_mode) != 0) { | ||
1218 | fprintf(stderr, "Error: only root user should be given write permission on chroot /etc\n"); | ||
1219 | exit(1); | ||
1220 | } | ||
1221 | close(fd); | ||
1222 | 1195 | ||
1223 | // there should be no checking on <chrootdir>/etc/resolv.conf | 1196 | // there should be no checking on <chrootdir>/etc/resolv.conf |
1224 | // the file is replaced with the real /etc/resolv.conf anyway | 1197 | // the file is replaced with the real /etc/resolv.conf anyway |
@@ -1249,32 +1222,10 @@ void fs_check_chroot_dir(const char *rootdir) { | |||
1249 | #endif | 1222 | #endif |
1250 | 1223 | ||
1251 | // check x11 socket directory | 1224 | // check x11 socket directory |
1252 | if (getenv("FIREJAIL_X11")) { | 1225 | if (getenv("FIREJAIL_X11")) |
1253 | dir = "tmp/.X11-unix"; | 1226 | fs_check_chroot_subdir("tmp/.X11-unix", parentfd, 0); |
1254 | fd = openat(parentfd, dir, O_PATH|O_CLOEXEC); | ||
1255 | if (fd == -1) | ||
1256 | goto error1; | ||
1257 | if (fstat(fd, &s) == -1) | ||
1258 | errExit("fstat"); | ||
1259 | if (!S_ISDIR(s.st_mode) || s.st_uid != 0) | ||
1260 | goto error2; | ||
1261 | close(fd); | ||
1262 | } | ||
1263 | 1227 | ||
1264 | close(parentfd); | 1228 | close(parentfd); |
1265 | return; | ||
1266 | |||
1267 | error1: | ||
1268 | if (errno == ENOENT) | ||
1269 | fprintf(stderr, "Error: cannot find /%s in chroot directory\n", dir); | ||
1270 | else { | ||
1271 | perror("open"); | ||
1272 | fprintf(stderr, "Error: cannot open /%s in chroot directory\n", dir); | ||
1273 | } | ||
1274 | exit(1); | ||
1275 | error2: | ||
1276 | fprintf(stderr, "Error: chroot /%s should be a directory owned by root\n", dir); | ||
1277 | exit(1); | ||
1278 | } | 1229 | } |
1279 | 1230 | ||
1280 | // chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf | 1231 | // chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf |
diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c index bd036908a..d807f527d 100644 --- a/src/firejail/fs_dev.c +++ b/src/firejail/fs_dev.c | |||
@@ -137,8 +137,8 @@ static void deventry_mount(void) { | |||
137 | } | 137 | } |
138 | 138 | ||
139 | static void create_char_dev(const char *path, mode_t mode, int major, int minor) { | 139 | static void create_char_dev(const char *path, mode_t mode, int major, int minor) { |
140 | dev_t dev = makedev(major, minor); | 140 | dev_t device = makedev(major, minor); |
141 | if (mknod(path, S_IFCHR | mode, dev) == -1) | 141 | if (mknod(path, S_IFCHR | mode, device) == -1) |
142 | goto errexit; | 142 | goto errexit; |
143 | if (chmod(path, mode) < 0) | 143 | if (chmod(path, mode) < 0) |
144 | goto errexit; | 144 | goto errexit; |
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index 3f6d78db4..01a807883 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c | |||
@@ -239,13 +239,16 @@ void fs_private_homedir(void) { | |||
239 | // mount bind private_homedir on top of homedir | 239 | // mount bind private_homedir on top of homedir |
240 | if (arg_debug) | 240 | if (arg_debug) |
241 | printf("Mount-bind %s on top of %s\n", private_homedir, homedir); | 241 | printf("Mount-bind %s on top of %s\n", private_homedir, homedir); |
242 | // get a file descriptor for private_homedir, fails if there is any symlink | 242 | // get file descriptors for homedir and private_homedir, fails if there is any symlink |
243 | int fd = safe_fd(private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); | 243 | int src = safe_fd(private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); |
244 | if (fd == -1) | 244 | if (src == -1) |
245 | errExit("safe_fd"); | ||
246 | int dst = safe_fd(homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); | ||
247 | if (dst == -1) | ||
245 | errExit("safe_fd"); | 248 | errExit("safe_fd"); |
246 | // check if new home directory is owned by the user | 249 | // check if new home directory is owned by the user |
247 | struct stat s; | 250 | struct stat s; |
248 | if (fstat(fd, &s) == -1) | 251 | if (fstat(src, &s) == -1) |
249 | errExit("fstat"); | 252 | errExit("fstat"); |
250 | if (s.st_uid != getuid()) { | 253 | if (s.st_uid != getuid()) { |
251 | fprintf(stderr, "Error: private directory is not owned by the current user\n"); | 254 | fprintf(stderr, "Error: private directory is not owned by the current user\n"); |
@@ -253,17 +256,27 @@ void fs_private_homedir(void) { | |||
253 | } | 256 | } |
254 | if ((S_IRWXU & s.st_mode) != S_IRWXU) | 257 | if ((S_IRWXU & s.st_mode) != S_IRWXU) |
255 | fwarning("no full permissions on private directory\n"); | 258 | fwarning("no full permissions on private directory\n"); |
256 | // mount via the link in /proc/self/fd | 259 | // mount via the links in /proc/self/fd |
257 | char *proc; | 260 | char *proc_src, *proc_dst; |
258 | if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) | 261 | if (asprintf(&proc_src, "/proc/self/fd/%d", src) == -1) |
262 | errExit("asprintf"); | ||
263 | if (asprintf(&proc_dst, "/proc/self/fd/%d", dst) == -1) | ||
259 | errExit("asprintf"); | 264 | errExit("asprintf"); |
260 | if (mount(proc, homedir, NULL, MS_NOSUID | MS_NODEV | MS_BIND | MS_REC, NULL) < 0) | 265 | if (mount(proc_src, proc_dst, NULL, MS_NOSUID | MS_NODEV | MS_BIND | MS_REC, NULL) < 0) |
261 | errExit("mount bind"); | 266 | errExit("mount bind"); |
262 | free(proc); | 267 | free(proc_src); |
263 | close(fd); | 268 | free(proc_dst); |
264 | 269 | close(src); | |
265 | fs_logger3("mount-bind", private_homedir, cfg.homedir); | 270 | close(dst); |
266 | fs_logger2("whitelist", cfg.homedir); | 271 | // check /proc/self/mountinfo to confirm the mount is ok |
272 | MountData *mptr = get_last_mount(); | ||
273 | size_t len = strlen(homedir); | ||
274 | if (strncmp(mptr->dir, homedir, len) != 0 || | ||
275 | (*(mptr->dir + len) != '\0' && *(mptr->dir + len) != '/')) | ||
276 | errLogExit("invalid private mount"); | ||
277 | |||
278 | fs_logger3("mount-bind", private_homedir, homedir); | ||
279 | fs_logger2("whitelist", homedir); | ||
267 | // preserve mode and ownership | 280 | // preserve mode and ownership |
268 | // if (chown(homedir, s.st_uid, s.st_gid) == -1) | 281 | // if (chown(homedir, s.st_uid, s.st_gid) == -1) |
269 | // errExit("mount-bind chown"); | 282 | // errExit("mount-bind chown"); |
@@ -310,13 +323,13 @@ void fs_private(void) { | |||
310 | int aflag = store_asoundrc(); | 323 | int aflag = store_asoundrc(); |
311 | 324 | ||
312 | // mask /home | 325 | // mask /home |
313 | if (arg_debug) | ||
314 | printf("Mounting a new /home directory\n"); | ||
315 | if (u == 0 && arg_allusers) // allow --allusers when starting the sandbox as root | 326 | if (u == 0 && arg_allusers) // allow --allusers when starting the sandbox as root |
316 | ; | 327 | ; |
317 | else { | 328 | else { |
329 | if (arg_debug) | ||
330 | printf("Mounting a new /home directory\n"); | ||
318 | if (arg_allusers) | 331 | if (arg_allusers) |
319 | fwarning("--allusers disabled by --private or --whitelist\n"); | 332 | fwarning("allusers option disabled by private or whitelist option\n"); |
320 | if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME, "mode=755,gid=0") < 0) | 333 | if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME, "mode=755,gid=0") < 0) |
321 | errExit("mounting home directory"); | 334 | errExit("mounting home directory"); |
322 | fs_logger("tmpfs /home"); | 335 | fs_logger("tmpfs /home"); |
@@ -330,19 +343,24 @@ void fs_private(void) { | |||
330 | fs_logger("tmpfs /root"); | 343 | fs_logger("tmpfs /root"); |
331 | 344 | ||
332 | if (u != 0) { | 345 | if (u != 0) { |
333 | // create /home/user | 346 | if (strncmp(homedir, "/home/", 6) == 0) { |
334 | if (arg_debug) | 347 | // create /home/user |
335 | printf("Create a new user directory\n"); | 348 | if (arg_debug) |
336 | if (mkdir(homedir, S_IRWXU) == -1) { | 349 | printf("Create a new user directory\n"); |
337 | if (mkpath_as_root(homedir) == -1) | 350 | if (mkdir(homedir, S_IRWXU) == -1) { |
338 | errExit("mkpath"); | 351 | if (mkpath_as_root(homedir) == -1) |
339 | if (mkdir(homedir, S_IRWXU) == -1 && errno != EEXIST) | 352 | errExit("mkpath"); |
340 | errExit("mkdir"); | 353 | if (mkdir(homedir, S_IRWXU) == -1 && errno != EEXIST) |
354 | errExit("mkdir"); | ||
355 | } | ||
356 | if (chown(homedir, u, g) < 0) | ||
357 | errExit("chown"); | ||
358 | fs_logger2("mkdir", homedir); | ||
359 | fs_logger2("tmpfs", homedir); | ||
341 | } | 360 | } |
342 | if (chown(homedir, u, g) < 0) | 361 | else |
343 | errExit("chown"); | 362 | // user directory is outside /home, mask it as well |
344 | fs_logger2("mkdir", homedir); | 363 | fs_tmpfs(homedir, 1); |
345 | fs_logger2("tmpfs", homedir); | ||
346 | } | 364 | } |
347 | 365 | ||
348 | skel(homedir, u, g); | 366 | skel(homedir, u, g); |
@@ -464,14 +482,14 @@ static void duplicate(char *name) { | |||
464 | } | 482 | } |
465 | else if (S_ISDIR(s.st_mode)) { | 483 | else if (S_ISDIR(s.st_mode)) { |
466 | // create the directory in RUN_HOME_DIR | 484 | // create the directory in RUN_HOME_DIR |
467 | char *name; | 485 | char *path; |
468 | char *ptr = strrchr(fname, '/'); | 486 | char *ptr = strrchr(fname, '/'); |
469 | ptr++; | 487 | ptr++; |
470 | if (asprintf(&name, "%s/%s", RUN_HOME_DIR, ptr) == -1) | 488 | if (asprintf(&path, "%s/%s", RUN_HOME_DIR, ptr) == -1) |
471 | errExit("asprintf"); | 489 | errExit("asprintf"); |
472 | mkdir_attr(name, 0755, getuid(), getgid()); | 490 | mkdir_attr(path, 0755, getuid(), getgid()); |
473 | sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FCOPY, fname, name); | 491 | sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FCOPY, fname, path); |
474 | free(name); | 492 | free(path); |
475 | } | 493 | } |
476 | else | 494 | else |
477 | sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FCOPY, fname, RUN_HOME_DIR); | 495 | sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FCOPY, fname, RUN_HOME_DIR); |
@@ -528,8 +546,20 @@ void fs_private_home_list(void) { | |||
528 | if (arg_debug) | 546 | if (arg_debug) |
529 | printf("Mount-bind %s on top of %s\n", RUN_HOME_DIR, homedir); | 547 | printf("Mount-bind %s on top of %s\n", RUN_HOME_DIR, homedir); |
530 | 548 | ||
531 | if (mount(RUN_HOME_DIR, homedir, NULL, MS_BIND|MS_REC, NULL) < 0) | 549 | int fd = safe_fd(homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); |
550 | if (fd == -1) | ||
551 | errExit("safe_fd"); | ||
552 | char *proc; | ||
553 | if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) | ||
554 | errExit("asprintf"); | ||
555 | if (mount(RUN_HOME_DIR, proc, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
532 | errExit("mount bind"); | 556 | errExit("mount bind"); |
557 | free(proc); | ||
558 | close(fd); | ||
559 | // check /proc/self/mountinfo to confirm the mount is ok | ||
560 | MountData *mptr = get_last_mount(); | ||
561 | if (strcmp(mptr->dir, homedir) != 0 || strcmp(mptr->fstype, "tmpfs") != 0) | ||
562 | errLogExit("invalid private-home mount"); | ||
533 | fs_logger2("tmpfs", homedir); | 563 | fs_logger2("tmpfs", homedir); |
534 | 564 | ||
535 | if (uid != 0) { | 565 | if (uid != 0) { |
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index bce44b9e5..a950d1124 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c | |||
@@ -237,11 +237,6 @@ static void whitelist_path(ProfileEntry *entry) { | |||
237 | return; | 237 | return; |
238 | } | 238 | } |
239 | 239 | ||
240 | #ifdef TEST_MOUNTINFO | ||
241 | printf("TEST_MOUNTINFO\n"); | ||
242 | path = "/etc/."; | ||
243 | #endif | ||
244 | |||
245 | // create path of the mount target if necessary | 240 | // create path of the mount target if necessary |
246 | int fd2 = mkpath(path, 0755); | 241 | int fd2 = mkpath(path, 0755); |
247 | if (fd2 == -1) { | 242 | if (fd2 == -1) { |
@@ -305,7 +300,10 @@ static void whitelist_path(ProfileEntry *entry) { | |||
305 | 300 | ||
306 | // check the last mount operation | 301 | // check the last mount operation |
307 | MountData *mptr = get_last_mount(); // will do exit(1) if the mount cannot be found | 302 | MountData *mptr = get_last_mount(); // will do exit(1) if the mount cannot be found |
308 | 303 | #ifdef TEST_MOUNTINFO | |
304 | printf("TEST_MOUNTINFO\n"); | ||
305 | mptr->dir = "foo"; | ||
306 | #endif | ||
309 | // confirm the file was mounted on the right target | 307 | // confirm the file was mounted on the right target |
310 | // strcmp does not work here, because mptr->dir can be a child mount | 308 | // strcmp does not work here, because mptr->dir can be a child mount |
311 | size_t path_len = strlen(path); | 309 | size_t path_len = strlen(path); |
@@ -712,8 +710,16 @@ void fs_whitelist(void) { | |||
712 | if (stat(cfg.homedir, &s) == 0) { | 710 | if (stat(cfg.homedir, &s) == 0) { |
713 | // keep a copy of real home dir in RUN_WHITELIST_HOME_USER_DIR | 711 | // keep a copy of real home dir in RUN_WHITELIST_HOME_USER_DIR |
714 | mkdir_attr(RUN_WHITELIST_HOME_USER_DIR, 0755, getuid(), getgid()); | 712 | mkdir_attr(RUN_WHITELIST_HOME_USER_DIR, 0755, getuid(), getgid()); |
715 | if (mount(cfg.homedir, RUN_WHITELIST_HOME_USER_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) | 713 | int fd = safe_fd(cfg.homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); |
714 | if (fd == -1) | ||
715 | errExit("safe_fd"); | ||
716 | char *proc; | ||
717 | if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) | ||
718 | errExit("asprintf"); | ||
719 | if (mount(proc, RUN_WHITELIST_HOME_USER_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
716 | errExit("mount bind"); | 720 | errExit("mount bind"); |
721 | free(proc); | ||
722 | close(fd); | ||
717 | 723 | ||
718 | // mount a tmpfs and initialize /home/user, overrides --allusers | 724 | // mount a tmpfs and initialize /home/user, overrides --allusers |
719 | fs_private(); | 725 | fs_private(); |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 34c6f4044..d00147c74 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <sys/mount.h> | 26 | #include <sys/mount.h> |
27 | #include <sys/wait.h> | 27 | #include <sys/wait.h> |
28 | #include <sys/stat.h> | 28 | #include <sys/stat.h> |
29 | #include <fcntl.h> | ||
30 | #include <dirent.h> | 29 | #include <dirent.h> |
31 | #include <pwd.h> | 30 | #include <pwd.h> |
32 | #include <errno.h> | 31 | #include <errno.h> |
@@ -38,6 +37,20 @@ | |||
38 | #include <net/if.h> | 37 | #include <net/if.h> |
39 | #include <sys/utsname.h> | 38 | #include <sys/utsname.h> |
40 | 39 | ||
40 | #include <fcntl.h> | ||
41 | #ifndef O_PATH | ||
42 | #define O_PATH 010000000 | ||
43 | #endif | ||
44 | |||
45 | #ifdef __ia64__ | ||
46 | /* clone(2) has a different interface on ia64, as it needs to know | ||
47 | the size of the stack */ | ||
48 | int __clone2(int (*fn)(void *), | ||
49 | void *child_stack_base, size_t stack_size, | ||
50 | int flags, void *arg, ... | ||
51 | /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ ); | ||
52 | #endif | ||
53 | |||
41 | uid_t firejail_uid = 0; | 54 | uid_t firejail_uid = 0; |
42 | gid_t firejail_gid = 0; | 55 | gid_t firejail_gid = 0; |
43 | 56 | ||
@@ -233,6 +246,41 @@ static pid_t require_pid(const char *name) { | |||
233 | return pid; | 246 | return pid; |
234 | } | 247 | } |
235 | 248 | ||
249 | // return 1 if there is a link somewhere in path of directory | ||
250 | static int has_link(const char *dir) { | ||
251 | assert(dir); | ||
252 | int fd = safe_fd(dir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); | ||
253 | if (fd == -1) { | ||
254 | if (errno == ENOTDIR && is_dir(dir)) | ||
255 | return 1; | ||
256 | } | ||
257 | else | ||
258 | close(fd); | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static void build_cfg_homedir(const char *dir) { | ||
263 | EUID_ASSERT(); | ||
264 | assert(dir); | ||
265 | if (dir[0] != '/') { | ||
266 | fprintf(stderr, "Error: invalid user directory \"%s\"\n", dir); | ||
267 | exit(1); | ||
268 | } | ||
269 | // symlinks are rejected in many places, provide a solution for home directories | ||
270 | if (checkcfg(CFG_HOMEDIR_SYMLINK)) { | ||
271 | cfg.homedir = realpath(dir, NULL); | ||
272 | if (cfg.homedir) | ||
273 | return; | ||
274 | } | ||
275 | else if (has_link(dir)) { | ||
276 | fprintf(stderr, "Error: path of user directory contains a symbolic link. " | ||
277 | "Please provide resolved path in password database (/etc/passwd) " | ||
278 | "or enable symbolic link resolution in Firejail configuration file.\n"); | ||
279 | exit(1); | ||
280 | } | ||
281 | cfg.homedir = clean_pathname(dir); | ||
282 | } | ||
283 | |||
236 | // init configuration | 284 | // init configuration |
237 | static void init_cfg(int argc, char **argv) { | 285 | static void init_cfg(int argc, char **argv) { |
238 | EUID_ASSERT(); | 286 | EUID_ASSERT(); |
@@ -256,15 +304,12 @@ static void init_cfg(int argc, char **argv) { | |||
256 | errExit("strdup"); | 304 | errExit("strdup"); |
257 | 305 | ||
258 | // build home directory name | 306 | // build home directory name |
259 | cfg.homedir = NULL; | 307 | if (pw->pw_dir == NULL) { |
260 | if (pw->pw_dir != NULL) { | ||
261 | cfg.homedir = clean_pathname(pw->pw_dir); | ||
262 | assert(cfg.homedir); | ||
263 | } | ||
264 | else { | ||
265 | fprintf(stderr, "Error: user %s doesn't have a user directory assigned\n", cfg.username); | 308 | fprintf(stderr, "Error: user %s doesn't have a user directory assigned\n", cfg.username); |
266 | exit(1); | 309 | exit(1); |
267 | } | 310 | } |
311 | build_cfg_homedir(pw->pw_dir); | ||
312 | assert(cfg.homedir); | ||
268 | 313 | ||
269 | cfg.cwd = getcwd(NULL, 0); | 314 | cfg.cwd = getcwd(NULL, 0); |
270 | if (!cfg.cwd && errno != ENOENT) | 315 | if (!cfg.cwd && errno != ENOENT) |
@@ -917,7 +962,6 @@ int main(int argc, char **argv) { | |||
917 | 962 | ||
918 | // check if the user is allowed to use firejail | 963 | // check if the user is allowed to use firejail |
919 | init_cfg(argc, argv); | 964 | init_cfg(argc, argv); |
920 | assert(cfg.homedir); | ||
921 | 965 | ||
922 | // get starting timestamp, process --quiet | 966 | // get starting timestamp, process --quiet |
923 | start_timestamp = getticks(); | 967 | start_timestamp = getticks(); |
@@ -2541,10 +2585,18 @@ int main(int argc, char **argv) { | |||
2541 | 2585 | ||
2542 | EUID_ASSERT(); | 2586 | EUID_ASSERT(); |
2543 | EUID_ROOT(); | 2587 | EUID_ROOT(); |
2588 | #ifdef __ia64__ | ||
2589 | child = __clone2(sandbox, | ||
2590 | child_stack, | ||
2591 | STACK_SIZE, | ||
2592 | flags, | ||
2593 | NULL); | ||
2594 | #else | ||
2544 | child = clone(sandbox, | 2595 | child = clone(sandbox, |
2545 | child_stack + STACK_SIZE, | 2596 | child_stack + STACK_SIZE, |
2546 | flags, | 2597 | flags, |
2547 | NULL); | 2598 | NULL); |
2599 | #endif | ||
2548 | if (child == -1) | 2600 | if (child == -1) |
2549 | errExit("clone"); | 2601 | errExit("clone"); |
2550 | EUID_USER(); | 2602 | EUID_USER(); |
diff --git a/src/firejail/restrict_users.c b/src/firejail/restrict_users.c index 5c5ace90b..ee2e497cb 100644 --- a/src/firejail/restrict_users.c +++ b/src/firejail/restrict_users.c | |||
@@ -25,9 +25,13 @@ | |||
25 | #include <fnmatch.h> | 25 | #include <fnmatch.h> |
26 | #include <glob.h> | 26 | #include <glob.h> |
27 | #include <dirent.h> | 27 | #include <dirent.h> |
28 | #include <fcntl.h> | ||
29 | #include <errno.h> | 28 | #include <errno.h> |
30 | 29 | ||
30 | #include <fcntl.h> | ||
31 | #ifndef O_PATH | ||
32 | # define O_PATH 010000000 | ||
33 | #endif | ||
34 | |||
31 | #define MAXBUF 1024 | 35 | #define MAXBUF 1024 |
32 | 36 | ||
33 | // linked list of users | 37 | // linked list of users |
@@ -79,8 +83,16 @@ static void sanitize_home(void) { | |||
79 | errExit("mkdir"); | 83 | errExit("mkdir"); |
80 | 84 | ||
81 | // keep a copy of the user home directory | 85 | // keep a copy of the user home directory |
82 | if (mount(cfg.homedir, RUN_WHITELIST_HOME_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) | 86 | int fd = safe_fd(cfg.homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); |
87 | if (fd == -1) | ||
88 | errExit("safe_fd"); | ||
89 | char *proc; | ||
90 | if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) | ||
91 | errExit("asprintf"); | ||
92 | if (mount(proc, RUN_WHITELIST_HOME_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
83 | errExit("mount bind"); | 93 | errExit("mount bind"); |
94 | free(proc); | ||
95 | close(fd); | ||
84 | 96 | ||
85 | // mount tmpfs in the new home | 97 | // mount tmpfs in the new home |
86 | if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0) | 98 | if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0) |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index f91e5ab7c..288726d22 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -268,6 +268,7 @@ static int monitor_application(pid_t app_pid) { | |||
268 | if (cfg.timeout) { | 268 | if (cfg.timeout) { |
269 | options = WNOHANG; | 269 | options = WNOHANG; |
270 | timeout = cfg.timeout; | 270 | timeout = cfg.timeout; |
271 | sleep(1); | ||
271 | } | 272 | } |
272 | 273 | ||
273 | int status = 0; | 274 | int status = 0; |
@@ -302,8 +303,11 @@ static int monitor_application(pid_t app_pid) { | |||
302 | // handle --timeout | 303 | // handle --timeout |
303 | if (options) { | 304 | if (options) { |
304 | if (--timeout == 0) { | 305 | if (--timeout == 0) { |
306 | // SIGTERM might fail if the process ignores it (SIG_IGN) | ||
307 | // we give it 100ms to close properly and after that we SIGKILL it | ||
305 | kill(-1, SIGTERM); | 308 | kill(-1, SIGTERM); |
306 | sleep(1); | 309 | usleep(100000); |
310 | kill(-1, SIGKILL); | ||
307 | flush_stdin(); | 311 | flush_stdin(); |
308 | _exit(1); | 312 | _exit(1); |
309 | } | 313 | } |
diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c index 7dca9aa99..a41e32569 100644 --- a/src/firejail/sbox.c +++ b/src/firejail/sbox.c | |||
@@ -104,7 +104,7 @@ static struct sock_fprog prog = { | |||
104 | .filter = filter, | 104 | .filter = filter, |
105 | }; | 105 | }; |
106 | 106 | ||
107 | int sbox_run(unsigned filter, int num, ...) { | 107 | int sbox_run(unsigned filtermask, int num, ...) { |
108 | EUID_ROOT(); | 108 | EUID_ROOT(); |
109 | 109 | ||
110 | int i; | 110 | int i; |
@@ -129,10 +129,26 @@ int sbox_run(unsigned filter, int num, ...) { | |||
129 | if (child < 0) | 129 | if (child < 0) |
130 | errExit("fork"); | 130 | errExit("fork"); |
131 | if (child == 0) { | 131 | if (child == 0) { |
132 | // clean the new process | 132 | // preserve firejail-specific env vars |
133 | char *cl = getenv("FIREJAIL_FILE_COPY_LIMIT"); | ||
134 | if (cl) { | ||
135 | // duplicate the value, who knows what's going to happen with it in clearenv! | ||
136 | cl = strdup(cl); | ||
137 | if (!cl) | ||
138 | errExit("strdup"); | ||
139 | } | ||
133 | clearenv(); | 140 | clearenv(); |
141 | if (cl) { | ||
142 | if (setenv("FIREJAIL_FILE_COPY_LIMIT", cl, 1) == -1) | ||
143 | errExit("setenv"); | ||
144 | free(cl); | ||
145 | } | ||
146 | if (arg_quiet) // --quiet is passed as an environment variable | ||
147 | setenv("FIREJAIL_QUIET", "yes", 1); | ||
148 | if (arg_debug) // --debug is passed as an environment variable | ||
149 | setenv("FIREJAIL_DEBUG", "yes", 1); | ||
134 | 150 | ||
135 | if (filter & SBOX_STDIN_FROM_FILE) { | 151 | if (filtermask & SBOX_STDIN_FROM_FILE) { |
136 | int fd; | 152 | int fd; |
137 | if((fd = open(SBOX_STDIN_FILE, O_RDONLY)) == -1) { | 153 | if((fd = open(SBOX_STDIN_FILE, O_RDONLY)) == -1) { |
138 | fprintf(stderr,"Error: cannot open %s\n", SBOX_STDIN_FILE); | 154 | fprintf(stderr,"Error: cannot open %s\n", SBOX_STDIN_FILE); |
@@ -141,7 +157,7 @@ int sbox_run(unsigned filter, int num, ...) { | |||
141 | dup2(fd,STDIN_FILENO); | 157 | dup2(fd,STDIN_FILENO); |
142 | close(fd); | 158 | close(fd); |
143 | } | 159 | } |
144 | else if ((filter & SBOX_ALLOW_STDIN) == 0) { | 160 | else if ((filtermask & SBOX_ALLOW_STDIN) == 0) { |
145 | int fd = open("/dev/null",O_RDWR, 0); | 161 | int fd = open("/dev/null",O_RDWR, 0); |
146 | if (fd != -1) { | 162 | if (fd != -1) { |
147 | dup2(fd, STDIN_FILENO); | 163 | dup2(fd, STDIN_FILENO); |
@@ -159,17 +175,17 @@ int sbox_run(unsigned filter, int num, ...) { | |||
159 | umask(027); | 175 | umask(027); |
160 | 176 | ||
161 | // apply filters | 177 | // apply filters |
162 | if (filter & SBOX_CAPS_NONE) { | 178 | if (filtermask & SBOX_CAPS_NONE) { |
163 | caps_drop_all(); | 179 | caps_drop_all(); |
164 | } | 180 | } |
165 | else if (filter & SBOX_CAPS_NETWORK) { | 181 | else if (filtermask & SBOX_CAPS_NETWORK) { |
166 | #ifndef HAVE_GCOV // the following filter will prevent GCOV from saving info in .gcda files | 182 | #ifndef HAVE_GCOV // the following filter will prevent GCOV from saving info in .gcda files |
167 | uint64_t set = ((uint64_t) 1) << CAP_NET_ADMIN; | 183 | uint64_t set = ((uint64_t) 1) << CAP_NET_ADMIN; |
168 | set |= ((uint64_t) 1) << CAP_NET_RAW; | 184 | set |= ((uint64_t) 1) << CAP_NET_RAW; |
169 | caps_set(set); | 185 | caps_set(set); |
170 | #endif | 186 | #endif |
171 | } | 187 | } |
172 | else if (filter & SBOX_CAPS_HIDEPID) { | 188 | else if (filtermask & SBOX_CAPS_HIDEPID) { |
173 | #ifndef HAVE_GCOV // the following filter will prevent GCOV from saving info in .gcda files | 189 | #ifndef HAVE_GCOV // the following filter will prevent GCOV from saving info in .gcda files |
174 | uint64_t set = ((uint64_t) 1) << CAP_SYS_PTRACE; | 190 | uint64_t set = ((uint64_t) 1) << CAP_SYS_PTRACE; |
175 | set |= ((uint64_t) 1) << CAP_SYS_PACCT; | 191 | set |= ((uint64_t) 1) << CAP_SYS_PACCT; |
@@ -177,7 +193,7 @@ int sbox_run(unsigned filter, int num, ...) { | |||
177 | #endif | 193 | #endif |
178 | } | 194 | } |
179 | 195 | ||
180 | if (filter & SBOX_SECCOMP) { | 196 | if (filtermask & SBOX_SECCOMP) { |
181 | if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { | 197 | if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { |
182 | perror("prctl(NO_NEW_PRIVS)"); | 198 | perror("prctl(NO_NEW_PRIVS)"); |
183 | } | 199 | } |
@@ -186,22 +202,16 @@ int sbox_run(unsigned filter, int num, ...) { | |||
186 | } | 202 | } |
187 | } | 203 | } |
188 | 204 | ||
189 | if (filter & SBOX_ROOT) { | 205 | if (filtermask & SBOX_ROOT) { |
190 | // elevate privileges in order to get grsecurity working | 206 | // elevate privileges in order to get grsecurity working |
191 | if (setreuid(0, 0)) | 207 | if (setreuid(0, 0)) |
192 | errExit("setreuid"); | 208 | errExit("setreuid"); |
193 | if (setregid(0, 0)) | 209 | if (setregid(0, 0)) |
194 | errExit("setregid"); | 210 | errExit("setregid"); |
195 | } | 211 | } |
196 | else if (filter & SBOX_USER) | 212 | else if (filtermask & SBOX_USER) |
197 | drop_privs(1); | 213 | drop_privs(1); |
198 | 214 | ||
199 | clearenv(); | ||
200 | |||
201 | // --quiet is passed as an environment variable | ||
202 | if (arg_quiet) | ||
203 | setenv("FIREJAIL_QUIET", "yes", 1); | ||
204 | |||
205 | if (arg[0]) // get rid of scan-build warning | 215 | if (arg[0]) // get rid of scan-build warning |
206 | execvp(arg[0], arg); | 216 | execvp(arg[0], arg); |
207 | else | 217 | else |
diff --git a/src/firejail/util.c b/src/firejail/util.c index fff0bbf2f..918077235 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -50,7 +50,7 @@ void errLogExit(char* fmt, ...) { | |||
50 | char *msg1; | 50 | char *msg1; |
51 | char *msg2 = "Access error"; | 51 | char *msg2 = "Access error"; |
52 | if (vasprintf(&msg1, fmt, args) != -1 && | 52 | if (vasprintf(&msg1, fmt, args) != -1 && |
53 | asprintf(&msg2, "Access error: pid %d, last mount name:%s dir:%s type:%s - %s", getuid(), m->fsname, m->dir, m->fstype, msg1) != -1) | 53 | asprintf(&msg2, "Access error: uid %d, last mount name:%s dir:%s type:%s - %s", getuid(), m->fsname, m->dir, m->fstype, msg1) != -1) |
54 | syslog(LOG_CRIT, "%s", msg2); | 54 | syslog(LOG_CRIT, "%s", msg2); |
55 | va_end(args); | 55 | va_end(args); |
56 | closelog(); | 56 | closelog(); |
@@ -487,7 +487,6 @@ char *line_remove_spaces(const char *buf) { | |||
487 | size_t len = strlen(buf); | 487 | size_t len = strlen(buf); |
488 | if (len == 0) | 488 | if (len == 0) |
489 | return NULL; | 489 | return NULL; |
490 | assert(len + 1 != 0 && buf[len] == '\0'); | ||
491 | 490 | ||
492 | // allocate memory for the new string | 491 | // allocate memory for the new string |
493 | char *rv = malloc(len + 1); | 492 | char *rv = malloc(len + 1); |
@@ -554,15 +553,13 @@ char *split_comma(char *str) { | |||
554 | char *clean_pathname(const char *path) { | 553 | char *clean_pathname(const char *path) { |
555 | assert(path); | 554 | assert(path); |
556 | size_t len = strlen(path); | 555 | size_t len = strlen(path); |
557 | assert(len + 1 != 0 && path[len] == '\0'); | ||
558 | |||
559 | char *rv = malloc(len + 1); | 556 | char *rv = malloc(len + 1); |
560 | if (!rv) | 557 | if (!rv) |
561 | errExit("malloc"); | 558 | errExit("malloc"); |
562 | 559 | ||
563 | if (len > 0) { | 560 | if (len > 0) { |
564 | size_t i, j, cnt; | 561 | size_t i = 0, j = 0, cnt = 0; |
565 | for (i = 0, j = 0, cnt = 0; i < len; i++) { | 562 | for (; i < len; i++) { |
566 | if (path[i] == '/') | 563 | if (path[i] == '/') |
567 | cnt++; | 564 | cnt++; |
568 | else | 565 | else |
@@ -1142,56 +1139,47 @@ void disable_file_path(const char *path, const char *file) { | |||
1142 | free(fname); | 1139 | free(fname); |
1143 | } | 1140 | } |
1144 | 1141 | ||
1145 | // The returned file descriptor should be suitable for privileged operations on | 1142 | // open file without following any symbolic link |
1146 | // user controlled paths | 1143 | // returns a file descriptor on success, or -1 if a symlink is found |
1147 | int safe_fd(const char *path, int flags) { | 1144 | int safe_fd(const char *path, int flags) { |
1148 | assert(path); | 1145 | assert(path); |
1149 | |||
1150 | // reject empty string, relative path | ||
1151 | if (*path != '/') | 1146 | if (*path != '/') |
1152 | goto errexit; | 1147 | goto errexit; |
1153 | // reject ".." | ||
1154 | if (strstr(path, "..")) | 1148 | if (strstr(path, "..")) |
1155 | goto errexit; | 1149 | goto errexit; |
1156 | char *p = strrchr(path, '/'); | ||
1157 | assert(p); | ||
1158 | // reject trailing slash, root directory | ||
1159 | if (*(p + 1) == '\0') | ||
1160 | goto errexit; | ||
1161 | // reject trailing dot | ||
1162 | if (*(p + 1) == '.' && *(p + 2) == '\0') | ||
1163 | goto errexit; | ||
1164 | |||
1165 | // work with a copy of path | ||
1166 | char *dup = strdup(path); | ||
1167 | if (!dup) | ||
1168 | errExit("strdup"); | ||
1169 | 1150 | ||
1170 | int parentfd = open("/", O_PATH|O_DIRECTORY|O_CLOEXEC); | 1151 | int parentfd = open("/", O_PATH|O_DIRECTORY|O_CLOEXEC); |
1171 | if (parentfd == -1) | 1152 | if (parentfd == -1) |
1172 | errExit("open"); | 1153 | errExit("open"); |
1173 | |||
1174 | // traverse the path and return -1 if a symlink is encountered | ||
1175 | int fd = -1; | 1154 | int fd = -1; |
1176 | char *current_tok = EMPTY_STRING; | 1155 | |
1156 | char *last_tok = EMPTY_STRING; | ||
1157 | char *dup = strdup(path); | ||
1158 | if (!dup) | ||
1159 | errExit("strdup"); | ||
1177 | char *tok = strtok(dup, "/"); | 1160 | char *tok = strtok(dup, "/"); |
1178 | assert(tok); | 1161 | if (!tok) { // root directory |
1162 | free(dup); | ||
1163 | return parentfd; | ||
1164 | } | ||
1165 | |||
1179 | while (tok) { | 1166 | while (tok) { |
1180 | // open the element, assuming it is a directory; this fails with ENOTDIR if it is a symbolic link | 1167 | // open the element, assuming it is a directory; this fails with ENOTDIR if it is a symbolic link |
1168 | // if token is a single dot, the previous directory is reopened | ||
1181 | fd = openat(parentfd, tok, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); | 1169 | fd = openat(parentfd, tok, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); |
1182 | if (fd == -1) { | 1170 | if (fd == -1) { |
1183 | // if the following token is NULL, the current token is the final path element | 1171 | // if the following token is NULL, the current token is the final path element |
1184 | // try again to open it, this time using the passed flags, and return -1 or the descriptor | 1172 | // try again to open it, this time using the passed flags, and return -1 or the descriptor |
1185 | current_tok = tok; | 1173 | last_tok = tok; |
1186 | tok = strtok(NULL, "/"); | 1174 | tok = strtok(NULL, "/"); |
1187 | if (!tok) | 1175 | if (!tok) |
1188 | fd = openat(parentfd, current_tok, flags|O_NOFOLLOW); | 1176 | fd = openat(parentfd, last_tok, flags|O_NOFOLLOW); |
1189 | close(parentfd); | 1177 | close(parentfd); |
1190 | free(dup); | 1178 | free(dup); |
1191 | return fd; // -1 if open failed | 1179 | return fd; // -1 if open failed |
1192 | } | 1180 | } |
1193 | // move on to next path segment | 1181 | // move on to next path segment |
1194 | current_tok = tok; | 1182 | last_tok = tok; |
1195 | tok = strtok(NULL, "/"); | 1183 | tok = strtok(NULL, "/"); |
1196 | if (tok) { | 1184 | if (tok) { |
1197 | close(parentfd); | 1185 | close(parentfd); |
@@ -1202,13 +1190,13 @@ int safe_fd(const char *path, int flags) { | |||
1202 | // we are here because the last path element exists and is of file type directory | 1190 | // we are here because the last path element exists and is of file type directory |
1203 | // reopen it using the passed flags | 1191 | // reopen it using the passed flags |
1204 | close(fd); | 1192 | close(fd); |
1205 | fd = openat(parentfd, current_tok, flags|O_NOFOLLOW); | 1193 | fd = openat(parentfd, last_tok, flags|O_NOFOLLOW); |
1206 | close(parentfd); | 1194 | close(parentfd); |
1207 | free(dup); | 1195 | free(dup); |
1208 | return fd; // -1 if open failed | 1196 | return fd; // -1 if open failed |
1209 | 1197 | ||
1210 | errexit: | 1198 | errexit: |
1211 | fprintf(stderr, "Error: cannot open \"%s\", invalid filename\n", path); | 1199 | fprintf(stderr, "Error: cannot open \"%s\": invalid path\n", path); |
1212 | exit(1); | 1200 | exit(1); |
1213 | } | 1201 | } |
1214 | 1202 | ||
diff --git a/src/lib/pid.c b/src/lib/pid.c index c4235ede3..04bc8d132 100644 --- a/src/lib/pid.c +++ b/src/lib/pid.c | |||
@@ -329,10 +329,9 @@ void pid_read(pid_t mon_pid) { | |||
329 | } | 329 | } |
330 | } | 330 | } |
331 | 331 | ||
332 | pid_t child = -1; | ||
333 | struct dirent *entry; | 332 | struct dirent *entry; |
334 | char *end; | 333 | char *end; |
335 | while (child < 0 && (entry = readdir(dir))) { | 334 | while ((entry = readdir(dir))) { |
336 | pid_t pid = strtol(entry->d_name, &end, 10); | 335 | pid_t pid = strtol(entry->d_name, &end, 10); |
337 | pid %= max_pids; | 336 | pid %= max_pids; |
338 | if (end == entry->d_name || *end) | 337 | if (end == entry->d_name || *end) |
diff --git a/src/libpostexecseccomp/libpostexecseccomp.c b/src/libpostexecseccomp/libpostexecseccomp.c index 3983510ec..b2f64f18e 100644 --- a/src/libpostexecseccomp/libpostexecseccomp.c +++ b/src/libpostexecseccomp/libpostexecseccomp.c | |||
@@ -40,9 +40,7 @@ static void load_seccomp(void) { | |||
40 | return; | 40 | return; |
41 | } | 41 | } |
42 | unsigned short entries = (unsigned short) size / (unsigned short) sizeof(struct sock_filter); | 42 | unsigned short entries = (unsigned short) size / (unsigned short) sizeof(struct sock_filter); |
43 | struct sock_filter *filter = MAP_FAILED; | 43 | struct sock_filter *filter = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); |
44 | if (size != 0) | ||
45 | filter = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); | ||
46 | close(fd); | 44 | close(fd); |
47 | 45 | ||
48 | if (filter == MAP_FAILED) { | 46 | if (filter == MAP_FAILED) { |
diff --git a/src/libtrace/libtrace.c b/src/libtrace/libtrace.c index 397761c74..60fdb5470 100644 --- a/src/libtrace/libtrace.c +++ b/src/libtrace/libtrace.c | |||
@@ -41,54 +41,45 @@ typedef FILE *(*orig_fopen64_t)(const char *pathname, const char *mode); | |||
41 | static orig_fopen64_t orig_fopen64 = NULL; | 41 | static orig_fopen64_t orig_fopen64 = NULL; |
42 | 42 | ||
43 | // | 43 | // |
44 | // pid | 44 | // library constructor/destructor |
45 | // | 45 | // |
46 | static FILE *ftty = NULL; | ||
46 | static pid_t mypid = 0; | 47 | static pid_t mypid = 0; |
47 | static inline pid_t pid(void) { | ||
48 | if (!mypid) | ||
49 | mypid = getpid(); | ||
50 | return mypid; | ||
51 | } | ||
52 | |||
53 | // | ||
54 | // process name | ||
55 | // | ||
56 | #define MAXNAME 16 | 48 | #define MAXNAME 16 |
57 | static char myname[MAXNAME]; | 49 | static char myname[MAXNAME] = {'\0', }; |
58 | static int nameinit = 0; | 50 | |
59 | static char *name(void) { | 51 | static void init(void) __attribute__((constructor)); |
60 | if (!nameinit) { | 52 | void init(void) { |
61 | // initialize the name of the process based on /proc/PID/comm | 53 | orig_fopen = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen"); |
62 | memset(myname, 0, MAXNAME); | 54 | |
63 | 55 | // tty | |
64 | pid_t p = pid(); | 56 | ftty = orig_fopen("/dev/tty", "w"); |
65 | char *fname; | 57 | |
66 | if (asprintf(&fname, "/proc/%u/comm", p) == -1) | 58 | // pid |
67 | return "unknown"; | 59 | mypid = getpid(); |
68 | 60 | ||
69 | // read file | 61 | // process name |
70 | if (!orig_fopen) | 62 | char *fname; |
71 | orig_fopen = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen"); | 63 | if (asprintf(&fname, "/proc/%u/comm", mypid) == -1) |
72 | FILE *fp = orig_fopen(fname, "r"); | 64 | strncpy(myname, "unknown", MAXNAME-1); |
73 | if (!fp) | 65 | |
74 | return "unknown"; | 66 | // read file |
75 | if (fgets(myname, MAXNAME, fp) == NULL) { | 67 | FILE *fp = orig_fopen(fname, "r"); |
76 | fclose(fp); | 68 | if (!fp || fgets(myname, MAXNAME, fp) == NULL) |
77 | free(fname); | 69 | strncpy(myname, "unknown", MAXNAME-1); |
78 | return "unknown"; | 70 | |
79 | } | 71 | // clean '\n' |
80 | 72 | char *ptr = strchr(myname, '\n'); | |
81 | // clean '\n' | 73 | if (ptr) |
82 | char *ptr = strchr(myname, '\n'); | 74 | *ptr = '\0'; |
83 | if (ptr) | 75 | |
84 | *ptr = '\0'; | 76 | fclose(fp); |
85 | 77 | free(fname); | |
86 | fclose(fp); | 78 | } |
87 | free(fname); | ||
88 | nameinit = 1; | ||
89 | } | ||
90 | 79 | ||
91 | return myname; | 80 | static void fini(void) __attribute__((destructor)); |
81 | void fini(void) { | ||
82 | fclose(ftty); | ||
92 | } | 83 | } |
93 | 84 | ||
94 | // | 85 | // |
@@ -235,23 +226,23 @@ static char *translate(XTable *table, int val) { | |||
235 | static void print_sockaddr(int sockfd, const char *call, const struct sockaddr *addr, int rv) { | 226 | static void print_sockaddr(int sockfd, const char *call, const struct sockaddr *addr, int rv) { |
236 | if (addr->sa_family == AF_INET) { | 227 | if (addr->sa_family == AF_INET) { |
237 | struct sockaddr_in *a = (struct sockaddr_in *) addr; | 228 | struct sockaddr_in *a = (struct sockaddr_in *) addr; |
238 | printf("%u:%s:%s %d %s port %u:%d\n", pid(), name(), call, sockfd, inet_ntoa(a->sin_addr), ntohs(a->sin_port), rv); | 229 | fprintf(ftty, "%u:%s:%s %d %s port %u:%d\n", mypid, myname, call, sockfd, inet_ntoa(a->sin_addr), ntohs(a->sin_port), rv); |
239 | } | 230 | } |
240 | else if (addr->sa_family == AF_INET6) { | 231 | else if (addr->sa_family == AF_INET6) { |
241 | struct sockaddr_in6 *a = (struct sockaddr_in6 *) addr; | 232 | struct sockaddr_in6 *a = (struct sockaddr_in6 *) addr; |
242 | char str[INET6_ADDRSTRLEN]; | 233 | char str[INET6_ADDRSTRLEN]; |
243 | inet_ntop(AF_INET6, &(a->sin6_addr), str, INET6_ADDRSTRLEN); | 234 | inet_ntop(AF_INET6, &(a->sin6_addr), str, INET6_ADDRSTRLEN); |
244 | printf("%u:%s:%s %d %s:%d\n", pid(), name(), call, sockfd, str, rv); | 235 | fprintf(ftty, "%u:%s:%s %d %s:%d\n", mypid, myname, call, sockfd, str, rv); |
245 | } | 236 | } |
246 | else if (addr->sa_family == AF_UNIX) { | 237 | else if (addr->sa_family == AF_UNIX) { |
247 | struct sockaddr_un *a = (struct sockaddr_un *) addr; | 238 | struct sockaddr_un *a = (struct sockaddr_un *) addr; |
248 | if (a->sun_path[0]) | 239 | if (a->sun_path[0]) |
249 | printf("%u:%s:%s %d %s:%d\n", pid(), name(), call, sockfd, a->sun_path, rv); | 240 | fprintf(ftty, "%u:%s:%s %d %s:%d\n", mypid, myname, call, sockfd, a->sun_path, rv); |
250 | else | 241 | else |
251 | printf("%u:%s:%s %d @%s:%d\n", pid(), name(), call, sockfd, a->sun_path + 1, rv); | 242 | fprintf(ftty, "%u:%s:%s %d @%s:%d\n", mypid, myname, call, sockfd, a->sun_path + 1, rv); |
252 | } | 243 | } |
253 | else { | 244 | else { |
254 | printf("%u:%s:%s %d family %d:%d\n", pid(), name(), call, sockfd, addr->sa_family, rv); | 245 | fprintf(ftty, "%u:%s:%s %d family %d:%d\n", mypid, myname, call, sockfd, addr->sa_family, rv); |
255 | } | 246 | } |
256 | } | 247 | } |
257 | 248 | ||
@@ -267,7 +258,7 @@ int open(const char *pathname, int flags, mode_t mode) { | |||
267 | orig_open = (orig_open_t)dlsym(RTLD_NEXT, "open"); | 258 | orig_open = (orig_open_t)dlsym(RTLD_NEXT, "open"); |
268 | 259 | ||
269 | int rv = orig_open(pathname, flags, mode); | 260 | int rv = orig_open(pathname, flags, mode); |
270 | printf("%u:%s:open %s:%d\n", pid(), name(), pathname, rv); | 261 | fprintf(ftty, "%u:%s:open %s:%d\n", mypid, myname, pathname, rv); |
271 | return rv; | 262 | return rv; |
272 | } | 263 | } |
273 | 264 | ||
@@ -278,7 +269,7 @@ int open64(const char *pathname, int flags, mode_t mode) { | |||
278 | orig_open64 = (orig_open64_t)dlsym(RTLD_NEXT, "open64"); | 269 | orig_open64 = (orig_open64_t)dlsym(RTLD_NEXT, "open64"); |
279 | 270 | ||
280 | int rv = orig_open64(pathname, flags, mode); | 271 | int rv = orig_open64(pathname, flags, mode); |
281 | printf("%u:%s:open64 %s:%d\n", pid(), name(), pathname, rv); | 272 | fprintf(ftty, "%u:%s:open64 %s:%d\n", mypid, myname, pathname, rv); |
282 | return rv; | 273 | return rv; |
283 | } | 274 | } |
284 | 275 | ||
@@ -290,7 +281,7 @@ int openat(int dirfd, const char *pathname, int flags, mode_t mode) { | |||
290 | orig_openat = (orig_openat_t)dlsym(RTLD_NEXT, "openat"); | 281 | orig_openat = (orig_openat_t)dlsym(RTLD_NEXT, "openat"); |
291 | 282 | ||
292 | int rv = orig_openat(dirfd, pathname, flags, mode); | 283 | int rv = orig_openat(dirfd, pathname, flags, mode); |
293 | printf("%u:%s:openat %s:%d\n", pid(), name(), pathname, rv); | 284 | fprintf(ftty, "%u:%s:openat %s:%d\n", mypid, myname, pathname, rv); |
294 | return rv; | 285 | return rv; |
295 | } | 286 | } |
296 | 287 | ||
@@ -301,7 +292,7 @@ int openat64(int dirfd, const char *pathname, int flags, mode_t mode) { | |||
301 | orig_openat64 = (orig_openat64_t)dlsym(RTLD_NEXT, "openat64"); | 292 | orig_openat64 = (orig_openat64_t)dlsym(RTLD_NEXT, "openat64"); |
302 | 293 | ||
303 | int rv = orig_openat64(dirfd, pathname, flags, mode); | 294 | int rv = orig_openat64(dirfd, pathname, flags, mode); |
304 | printf("%u:%s:openat64 %s:%d\n", pid(), name(), pathname, rv); | 295 | fprintf(ftty, "%u:%s:openat64 %s:%d\n", mypid, myname, pathname, rv); |
305 | return rv; | 296 | return rv; |
306 | } | 297 | } |
307 | 298 | ||
@@ -312,7 +303,7 @@ FILE *fopen(const char *pathname, const char *mode) { | |||
312 | orig_fopen = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen"); | 303 | orig_fopen = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen"); |
313 | 304 | ||
314 | FILE *rv = orig_fopen(pathname, mode); | 305 | FILE *rv = orig_fopen(pathname, mode); |
315 | printf("%u:%s:fopen %s:%p\n", pid(), name(), pathname, rv); | 306 | fprintf(ftty, "%u:%s:fopen %s:%p\n", mypid, myname, pathname, rv); |
316 | return rv; | 307 | return rv; |
317 | } | 308 | } |
318 | 309 | ||
@@ -322,7 +313,7 @@ FILE *fopen64(const char *pathname, const char *mode) { | |||
322 | orig_fopen64 = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen64"); | 313 | orig_fopen64 = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen64"); |
323 | 314 | ||
324 | FILE *rv = orig_fopen64(pathname, mode); | 315 | FILE *rv = orig_fopen64(pathname, mode); |
325 | printf("%u:%s:fopen64 %s:%p\n", pid(), name(), pathname, rv); | 316 | fprintf(ftty, "%u:%s:fopen64 %s:%p\n", mypid, myname, pathname, rv); |
326 | return rv; | 317 | return rv; |
327 | } | 318 | } |
328 | #endif /* __GLIBC__ */ | 319 | #endif /* __GLIBC__ */ |
@@ -336,7 +327,7 @@ FILE *freopen(const char *pathname, const char *mode, FILE *stream) { | |||
336 | orig_freopen = (orig_freopen_t)dlsym(RTLD_NEXT, "freopen"); | 327 | orig_freopen = (orig_freopen_t)dlsym(RTLD_NEXT, "freopen"); |
337 | 328 | ||
338 | FILE *rv = orig_freopen(pathname, mode, stream); | 329 | FILE *rv = orig_freopen(pathname, mode, stream); |
339 | printf("%u:%s:freopen %s:%p\n", pid(), name(), pathname, rv); | 330 | fprintf(ftty, "%u:%s:freopen %s:%p\n", mypid, myname, pathname, rv); |
340 | return rv; | 331 | return rv; |
341 | } | 332 | } |
342 | 333 | ||
@@ -348,7 +339,7 @@ FILE *freopen64(const char *pathname, const char *mode, FILE *stream) { | |||
348 | orig_freopen64 = (orig_freopen64_t)dlsym(RTLD_NEXT, "freopen64"); | 339 | orig_freopen64 = (orig_freopen64_t)dlsym(RTLD_NEXT, "freopen64"); |
349 | 340 | ||
350 | FILE *rv = orig_freopen64(pathname, mode, stream); | 341 | FILE *rv = orig_freopen64(pathname, mode, stream); |
351 | printf("%u:%s:freopen64 %s:%p\n", pid(), name(), pathname, rv); | 342 | fprintf(ftty, "%u:%s:freopen64 %s:%p\n", mypid, myname, pathname, rv); |
352 | return rv; | 343 | return rv; |
353 | } | 344 | } |
354 | #endif /* __GLIBC__ */ | 345 | #endif /* __GLIBC__ */ |
@@ -361,7 +352,7 @@ int unlink(const char *pathname) { | |||
361 | orig_unlink = (orig_unlink_t)dlsym(RTLD_NEXT, "unlink"); | 352 | orig_unlink = (orig_unlink_t)dlsym(RTLD_NEXT, "unlink"); |
362 | 353 | ||
363 | int rv = orig_unlink(pathname); | 354 | int rv = orig_unlink(pathname); |
364 | printf("%u:%s:unlink %s:%d\n", pid(), name(), pathname, rv); | 355 | fprintf(ftty, "%u:%s:unlink %s:%d\n", mypid, myname, pathname, rv); |
365 | return rv; | 356 | return rv; |
366 | } | 357 | } |
367 | 358 | ||
@@ -372,7 +363,7 @@ int unlinkat(int dirfd, const char *pathname, int flags) { | |||
372 | orig_unlinkat = (orig_unlinkat_t)dlsym(RTLD_NEXT, "unlinkat"); | 363 | orig_unlinkat = (orig_unlinkat_t)dlsym(RTLD_NEXT, "unlinkat"); |
373 | 364 | ||
374 | int rv = orig_unlinkat(dirfd, pathname, flags); | 365 | int rv = orig_unlinkat(dirfd, pathname, flags); |
375 | printf("%u:%s:unlinkat %s:%d\n", pid(), name(), pathname, rv); | 366 | fprintf(ftty, "%u:%s:unlinkat %s:%d\n", mypid, myname, pathname, rv); |
376 | return rv; | 367 | return rv; |
377 | } | 368 | } |
378 | 369 | ||
@@ -384,7 +375,7 @@ int mkdir(const char *pathname, mode_t mode) { | |||
384 | orig_mkdir = (orig_mkdir_t)dlsym(RTLD_NEXT, "mkdir"); | 375 | orig_mkdir = (orig_mkdir_t)dlsym(RTLD_NEXT, "mkdir"); |
385 | 376 | ||
386 | int rv = orig_mkdir(pathname, mode); | 377 | int rv = orig_mkdir(pathname, mode); |
387 | printf("%u:%s:mkdir %s:%d\n", pid(), name(), pathname, rv); | 378 | fprintf(ftty, "%u:%s:mkdir %s:%d\n", mypid, myname, pathname, rv); |
388 | return rv; | 379 | return rv; |
389 | } | 380 | } |
390 | 381 | ||
@@ -395,7 +386,7 @@ int mkdirat(int dirfd, const char *pathname, mode_t mode) { | |||
395 | orig_mkdirat = (orig_mkdirat_t)dlsym(RTLD_NEXT, "mkdirat"); | 386 | orig_mkdirat = (orig_mkdirat_t)dlsym(RTLD_NEXT, "mkdirat"); |
396 | 387 | ||
397 | int rv = orig_mkdirat(dirfd, pathname, mode); | 388 | int rv = orig_mkdirat(dirfd, pathname, mode); |
398 | printf("%u:%s:mkdirat %s:%d\n", pid(), name(), pathname, rv); | 389 | fprintf(ftty, "%u:%s:mkdirat %s:%d\n", mypid, myname, pathname, rv); |
399 | return rv; | 390 | return rv; |
400 | } | 391 | } |
401 | 392 | ||
@@ -406,56 +397,56 @@ int rmdir(const char *pathname) { | |||
406 | orig_rmdir = (orig_rmdir_t)dlsym(RTLD_NEXT, "rmdir"); | 397 | orig_rmdir = (orig_rmdir_t)dlsym(RTLD_NEXT, "rmdir"); |
407 | 398 | ||
408 | int rv = orig_rmdir(pathname); | 399 | int rv = orig_rmdir(pathname); |
409 | printf("%u:%s:rmdir %s:%d\n", pid(), name(), pathname, rv); | 400 | fprintf(ftty, "%u:%s:rmdir %s:%d\n", mypid, myname, pathname, rv); |
410 | return rv; | 401 | return rv; |
411 | } | 402 | } |
412 | 403 | ||
413 | // stat | 404 | // stat |
414 | typedef int (*orig_stat_t)(const char *pathname, struct stat *buf); | 405 | typedef int (*orig_stat_t)(const char *pathname, struct stat *statbuf); |
415 | static orig_stat_t orig_stat = NULL; | 406 | static orig_stat_t orig_stat = NULL; |
416 | int stat(const char *pathname, struct stat *buf) { | 407 | int stat(const char *pathname, struct stat *statbuf) { |
417 | if (!orig_stat) | 408 | if (!orig_stat) |
418 | orig_stat = (orig_stat_t)dlsym(RTLD_NEXT, "stat"); | 409 | orig_stat = (orig_stat_t)dlsym(RTLD_NEXT, "stat"); |
419 | 410 | ||
420 | int rv = orig_stat(pathname, buf); | 411 | int rv = orig_stat(pathname, statbuf); |
421 | printf("%u:%s:stat %s:%d\n", pid(), name(), pathname, rv); | 412 | fprintf(ftty, "%u:%s:stat %s:%d\n", mypid, myname, pathname, rv); |
422 | return rv; | 413 | return rv; |
423 | } | 414 | } |
424 | 415 | ||
425 | #ifdef __GLIBC__ | 416 | #ifdef __GLIBC__ |
426 | typedef int (*orig_stat64_t)(const char *pathname, struct stat64 *buf); | 417 | typedef int (*orig_stat64_t)(const char *pathname, struct stat64 *statbuf); |
427 | static orig_stat64_t orig_stat64 = NULL; | 418 | static orig_stat64_t orig_stat64 = NULL; |
428 | int stat64(const char *pathname, struct stat64 *buf) { | 419 | int stat64(const char *pathname, struct stat64 *statbuf) { |
429 | if (!orig_stat64) | 420 | if (!orig_stat64) |
430 | orig_stat64 = (orig_stat64_t)dlsym(RTLD_NEXT, "stat64"); | 421 | orig_stat64 = (orig_stat64_t)dlsym(RTLD_NEXT, "stat64"); |
431 | 422 | ||
432 | int rv = orig_stat64(pathname, buf); | 423 | int rv = orig_stat64(pathname, statbuf); |
433 | printf("%u:%s:stat64 %s:%d\n", pid(), name(), pathname, rv); | 424 | fprintf(ftty, "%u:%s:stat64 %s:%d\n", mypid, myname, pathname, rv); |
434 | return rv; | 425 | return rv; |
435 | } | 426 | } |
436 | #endif /* __GLIBC__ */ | 427 | #endif /* __GLIBC__ */ |
437 | 428 | ||
438 | // lstat | 429 | // lstat |
439 | typedef int (*orig_lstat_t)(const char *pathname, struct stat *buf); | 430 | typedef int (*orig_lstat_t)(const char *pathname, struct stat *statbuf); |
440 | static orig_lstat_t orig_lstat = NULL; | 431 | static orig_lstat_t orig_lstat = NULL; |
441 | int lstat(const char *pathname, struct stat *buf) { | 432 | int lstat(const char *pathname, struct stat *statbuf) { |
442 | if (!orig_lstat) | 433 | if (!orig_lstat) |
443 | orig_lstat = (orig_lstat_t)dlsym(RTLD_NEXT, "lstat"); | 434 | orig_lstat = (orig_lstat_t)dlsym(RTLD_NEXT, "lstat"); |
444 | 435 | ||
445 | int rv = orig_lstat(pathname, buf); | 436 | int rv = orig_lstat(pathname, statbuf); |
446 | printf("%u:%s:lstat %s:%d\n", pid(), name(), pathname, rv); | 437 | fprintf(ftty, "%u:%s:lstat %s:%d\n", mypid, myname, pathname, rv); |
447 | return rv; | 438 | return rv; |
448 | } | 439 | } |
449 | 440 | ||
450 | #ifdef __GLIBC__ | 441 | #ifdef __GLIBC__ |
451 | typedef int (*orig_lstat64_t)(const char *pathname, struct stat64 *buf); | 442 | typedef int (*orig_lstat64_t)(const char *pathname, struct stat64 *statbuf); |
452 | static orig_lstat64_t orig_lstat64 = NULL; | 443 | static orig_lstat64_t orig_lstat64 = NULL; |
453 | int lstat64(const char *pathname, struct stat64 *buf) { | 444 | int lstat64(const char *pathname, struct stat64 *statbuf) { |
454 | if (!orig_lstat64) | 445 | if (!orig_lstat64) |
455 | orig_lstat64 = (orig_lstat64_t)dlsym(RTLD_NEXT, "lstat64"); | 446 | orig_lstat64 = (orig_lstat64_t)dlsym(RTLD_NEXT, "lstat64"); |
456 | 447 | ||
457 | int rv = orig_lstat64(pathname, buf); | 448 | int rv = orig_lstat64(pathname, statbuf); |
458 | printf("%u:%s:lstat64 %s:%d\n", pid(), name(), pathname, rv); | 449 | fprintf(ftty, "%u:%s:lstat64 %s:%d\n", mypid, myname, pathname, rv); |
459 | return rv; | 450 | return rv; |
460 | } | 451 | } |
461 | #endif /* __GLIBC__ */ | 452 | #endif /* __GLIBC__ */ |
@@ -468,7 +459,7 @@ DIR *opendir(const char *pathname) { | |||
468 | orig_opendir = (orig_opendir_t)dlsym(RTLD_NEXT, "opendir"); | 459 | orig_opendir = (orig_opendir_t)dlsym(RTLD_NEXT, "opendir"); |
469 | 460 | ||
470 | DIR *rv = orig_opendir(pathname); | 461 | DIR *rv = orig_opendir(pathname); |
471 | printf("%u:%s:opendir %s:%p\n", pid(), name(), pathname, rv); | 462 | fprintf(ftty, "%u:%s:opendir %s:%p\n", mypid, myname, pathname, rv); |
472 | return rv; | 463 | return rv; |
473 | } | 464 | } |
474 | 465 | ||
@@ -480,7 +471,7 @@ int access(const char *pathname, int mode) { | |||
480 | orig_access = (orig_access_t)dlsym(RTLD_NEXT, "access"); | 471 | orig_access = (orig_access_t)dlsym(RTLD_NEXT, "access"); |
481 | 472 | ||
482 | int rv = orig_access(pathname, mode); | 473 | int rv = orig_access(pathname, mode); |
483 | printf("%u:%s:access %s:%d\n", pid(), name(), pathname, rv); | 474 | fprintf(ftty, "%u:%s:access %s:%d\n", mypid, myname, pathname, rv); |
484 | return rv; | 475 | return rv; |
485 | } | 476 | } |
486 | 477 | ||
@@ -501,14 +492,14 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { | |||
501 | // socket | 492 | // socket |
502 | typedef int (*orig_socket_t)(int domain, int type, int protocol); | 493 | typedef int (*orig_socket_t)(int domain, int type, int protocol); |
503 | static orig_socket_t orig_socket = NULL; | 494 | static orig_socket_t orig_socket = NULL; |
504 | static char buf[1024]; | 495 | static char socketbuf[1024]; |
505 | int socket(int domain, int type, int protocol) { | 496 | int socket(int domain, int type, int protocol) { |
506 | if (!orig_socket) | 497 | if (!orig_socket) |
507 | orig_socket = (orig_socket_t)dlsym(RTLD_NEXT, "socket"); | 498 | orig_socket = (orig_socket_t)dlsym(RTLD_NEXT, "socket"); |
508 | 499 | ||
509 | int rv = orig_socket(domain, type, protocol); | 500 | int rv = orig_socket(domain, type, protocol); |
510 | char *ptr = buf; | 501 | char *ptr = socketbuf; |
511 | ptr += sprintf(ptr, "%u:%s:socket ", pid(), name()); | 502 | ptr += sprintf(ptr, "%u:%s:socket ", mypid, myname); |
512 | char *str = translate(socket_domain, domain); | 503 | char *str = translate(socket_domain, domain); |
513 | if (str == NULL) | 504 | if (str == NULL) |
514 | ptr += sprintf(ptr, "%d ", domain); | 505 | ptr += sprintf(ptr, "%d ", domain); |
@@ -538,7 +529,7 @@ int socket(int domain, int type, int protocol) { | |||
538 | sprintf(ptr, "%s", str); | 529 | sprintf(ptr, "%s", str); |
539 | } | 530 | } |
540 | 531 | ||
541 | printf("%s:%d\n", buf, rv); | 532 | fprintf(ftty, "%s:%d\n", socketbuf, rv); |
542 | return rv; | 533 | return rv; |
543 | } | 534 | } |
544 | 535 | ||
@@ -576,7 +567,7 @@ int system(const char *command) { | |||
576 | orig_system = (orig_system_t)dlsym(RTLD_NEXT, "system"); | 567 | orig_system = (orig_system_t)dlsym(RTLD_NEXT, "system"); |
577 | 568 | ||
578 | int rv = orig_system(command); | 569 | int rv = orig_system(command); |
579 | printf("%u:%s:system %s:%d\n", pid(), name(), command, rv); | 570 | fprintf(ftty, "%u:%s:system %s:%d\n", mypid, myname, command, rv); |
580 | 571 | ||
581 | return rv; | 572 | return rv; |
582 | } | 573 | } |
@@ -588,7 +579,7 @@ int setuid(uid_t uid) { | |||
588 | orig_setuid = (orig_setuid_t)dlsym(RTLD_NEXT, "setuid"); | 579 | orig_setuid = (orig_setuid_t)dlsym(RTLD_NEXT, "setuid"); |
589 | 580 | ||
590 | int rv = orig_setuid(uid); | 581 | int rv = orig_setuid(uid); |
591 | printf("%u:%s:setuid %d:%d\n", pid(), name(), uid, rv); | 582 | fprintf(ftty, "%u:%s:setuid %d:%d\n", mypid, myname, uid, rv); |
592 | 583 | ||
593 | return rv; | 584 | return rv; |
594 | } | 585 | } |
@@ -600,7 +591,7 @@ int setgid(gid_t gid) { | |||
600 | orig_setgid = (orig_setgid_t)dlsym(RTLD_NEXT, "setgid"); | 591 | orig_setgid = (orig_setgid_t)dlsym(RTLD_NEXT, "setgid"); |
601 | 592 | ||
602 | int rv = orig_setgid(gid); | 593 | int rv = orig_setgid(gid); |
603 | printf("%u:%s:setgid %d:%d\n", pid(), name(), gid, rv); | 594 | fprintf(ftty, "%u:%s:setgid %d:%d\n", mypid, myname, gid, rv); |
604 | 595 | ||
605 | return rv; | 596 | return rv; |
606 | } | 597 | } |
@@ -612,7 +603,7 @@ int setfsuid(uid_t uid) { | |||
612 | orig_setfsuid = (orig_setfsuid_t)dlsym(RTLD_NEXT, "setfsuid"); | 603 | orig_setfsuid = (orig_setfsuid_t)dlsym(RTLD_NEXT, "setfsuid"); |
613 | 604 | ||
614 | int rv = orig_setfsuid(uid); | 605 | int rv = orig_setfsuid(uid); |
615 | printf("%u:%s:setfsuid %d:%d\n", pid(), name(), uid, rv); | 606 | fprintf(ftty, "%u:%s:setfsuid %d:%d\n", mypid, myname, uid, rv); |
616 | 607 | ||
617 | return rv; | 608 | return rv; |
618 | } | 609 | } |
@@ -624,7 +615,7 @@ int setfsgid(gid_t gid) { | |||
624 | orig_setfsgid = (orig_setfsgid_t)dlsym(RTLD_NEXT, "setfsgid"); | 615 | orig_setfsgid = (orig_setfsgid_t)dlsym(RTLD_NEXT, "setfsgid"); |
625 | 616 | ||
626 | int rv = orig_setfsgid(gid); | 617 | int rv = orig_setfsgid(gid); |
627 | printf("%u:%s:setfsgid %d:%d\n", pid(), name(), gid, rv); | 618 | fprintf(ftty, "%u:%s:setfsgid %d:%d\n", mypid, myname, gid, rv); |
628 | 619 | ||
629 | return rv; | 620 | return rv; |
630 | } | 621 | } |
@@ -636,7 +627,7 @@ int setreuid(uid_t ruid, uid_t euid) { | |||
636 | orig_setreuid = (orig_setreuid_t)dlsym(RTLD_NEXT, "setreuid"); | 627 | orig_setreuid = (orig_setreuid_t)dlsym(RTLD_NEXT, "setreuid"); |
637 | 628 | ||
638 | int rv = orig_setreuid(ruid, euid); | 629 | int rv = orig_setreuid(ruid, euid); |
639 | printf("%u:%s:setreuid %d %d:%d\n", pid(), name(), ruid, euid, rv); | 630 | fprintf(ftty, "%u:%s:setreuid %d %d:%d\n", mypid, myname, ruid, euid, rv); |
640 | 631 | ||
641 | return rv; | 632 | return rv; |
642 | } | 633 | } |
@@ -648,7 +639,7 @@ int setregid(gid_t rgid, gid_t egid) { | |||
648 | orig_setregid = (orig_setregid_t)dlsym(RTLD_NEXT, "setregid"); | 639 | orig_setregid = (orig_setregid_t)dlsym(RTLD_NEXT, "setregid"); |
649 | 640 | ||
650 | int rv = orig_setregid(rgid, egid); | 641 | int rv = orig_setregid(rgid, egid); |
651 | printf("%u:%s:setregid %d %d:%d\n", pid(), name(), rgid, egid, rv); | 642 | fprintf(ftty, "%u:%s:setregid %d %d:%d\n", mypid, myname, rgid, egid, rv); |
652 | 643 | ||
653 | return rv; | 644 | return rv; |
654 | } | 645 | } |
@@ -660,7 +651,7 @@ int setresuid(uid_t ruid, uid_t euid, uid_t suid) { | |||
660 | orig_setresuid = (orig_setresuid_t)dlsym(RTLD_NEXT, "setresuid"); | 651 | orig_setresuid = (orig_setresuid_t)dlsym(RTLD_NEXT, "setresuid"); |
661 | 652 | ||
662 | int rv = orig_setresuid(ruid, euid, suid); | 653 | int rv = orig_setresuid(ruid, euid, suid); |
663 | printf("%u:%s:setresuid %d %d %d:%d\n", pid(), name(), ruid, euid, suid, rv); | 654 | fprintf(ftty, "%u:%s:setresuid %d %d %d:%d\n", mypid, myname, ruid, euid, suid, rv); |
664 | 655 | ||
665 | return rv; | 656 | return rv; |
666 | } | 657 | } |
@@ -672,7 +663,7 @@ int setresgid(gid_t rgid, gid_t egid, gid_t sgid) { | |||
672 | orig_setresgid = (orig_setresgid_t)dlsym(RTLD_NEXT, "setresgid"); | 663 | orig_setresgid = (orig_setresgid_t)dlsym(RTLD_NEXT, "setresgid"); |
673 | 664 | ||
674 | int rv = orig_setresgid(rgid, egid, sgid); | 665 | int rv = orig_setresgid(rgid, egid, sgid); |
675 | printf("%u:%s:setresgid %d %d %d:%d\n", pid(), name(), rgid, egid, sgid, rv); | 666 | fprintf(ftty, "%u:%s:setresgid %d %d %d:%d\n", mypid, myname, rgid, egid, sgid, rv); |
676 | 667 | ||
677 | return rv; | 668 | return rv; |
678 | } | 669 | } |
@@ -687,6 +678,6 @@ static void log_exec(int argc, char** argv) { | |||
687 | int rv = readlink("/proc/self/exe", buf, PATH_MAX); | 678 | int rv = readlink("/proc/self/exe", buf, PATH_MAX); |
688 | if (rv != -1) { | 679 | if (rv != -1) { |
689 | buf[rv] = '\0'; // readlink does not add a '\0' at the end | 680 | buf[rv] = '\0'; // readlink does not add a '\0' at the end |
690 | printf("%u:%s:exec %s:0\n", pid(), name(), buf); | 681 | fprintf(ftty, "%u:%s:exec %s:0\n", mypid, myname, buf); |
691 | } | 682 | } |
692 | } | 683 | } |
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 201339c8b..951618669 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -8,6 +8,12 @@ Start a sandbox: | |||
8 | firejail [OPTIONS] [program and arguments] | 8 | firejail [OPTIONS] [program and arguments] |
9 | .RE | 9 | .RE |
10 | .PP | 10 | .PP |
11 | Start an AppImage program: | ||
12 | .PP | ||
13 | .RS | ||
14 | firejail [OPTIONS] --appimage [appimage-file and arguments] | ||
15 | .RE | ||
16 | .PP | ||
11 | File transfer from an existing sandbox | 17 | File transfer from an existing sandbox |
12 | .PP | 18 | .PP |
13 | .RS | 19 | .RS |