diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Makefile.in | 4 | ||||
-rw-r--r-- | README.md | 32 | ||||
-rw-r--r-- | RELNOTES | 3 | ||||
-rwxr-xr-x | configure | 3 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | etc/ids.config | 142 | ||||
-rw-r--r-- | etc/inc/disable-programs.inc | 1 | ||||
-rw-r--r-- | etc/profile-a-l/chromium-common-hardened.inc.profile | 3 | ||||
-rw-r--r-- | etc/profile-a-l/code.profile | 39 | ||||
-rw-r--r-- | etc/profile-a-l/firefox.profile | 2 | ||||
-rw-r--r-- | etc/profile-a-l/kodi.profile | 6 | ||||
-rw-r--r-- | etc/profile-m-z/minitube.profile | 2 | ||||
-rw-r--r-- | etc/profile-m-z/ncdu2.profile | 11 | ||||
-rw-r--r-- | etc/profile-m-z/telegram.profile | 1 | ||||
-rw-r--r-- | etc/templates/syscalls.txt | 30 | ||||
-rw-r--r-- | src/common.mk.in | 2 | ||||
-rw-r--r-- | src/fids/Makefile.in | 18 | ||||
-rw-r--r-- | src/fids/blake2b.c | 176 | ||||
-rw-r--r-- | src/fids/config | 16 | ||||
-rw-r--r-- | src/fids/db.c | 158 | ||||
-rw-r--r-- | src/fids/db_exclude.c | 56 | ||||
-rw-r--r-- | src/fids/fids.h | 51 | ||||
-rw-r--r-- | src/fids/main.c | 371 | ||||
-rw-r--r-- | src/firecfg/firecfg.config | 1 | ||||
-rw-r--r-- | src/firejail/firejail.h | 9 | ||||
-rw-r--r-- | src/firejail/ids.c | 89 | ||||
-rw-r--r-- | src/firejail/main.c | 4 | ||||
-rw-r--r-- | src/firejail/usage.c | 2 | ||||
-rwxr-xr-x | src/tools/profcleaner.sh | 8 |
30 files changed, 1193 insertions, 52 deletions
diff --git a/.gitignore b/.gitignore index ea053b503..ace86f218 100644 --- a/.gitignore +++ b/.gitignore | |||
@@ -22,12 +22,13 @@ firejail-users.5 | |||
22 | firejail.1 | 22 | firejail.1 |
23 | firemon.1 | 23 | firemon.1 |
24 | firecfg.1 | 24 | firecfg.1 |
25 | jailcheck.5 | 25 | jailcheck.1 |
26 | mkdeb.sh | 26 | mkdeb.sh |
27 | src/firejail/firejail | 27 | src/firejail/firejail |
28 | src/firemon/firemon | 28 | src/firemon/firemon |
29 | src/firecfg/firecfg | 29 | src/firecfg/firecfg |
30 | src/ftee/ftee | 30 | src/ftee/ftee |
31 | src/fids/fids | ||
31 | src/tags | 32 | src/tags |
32 | src/faudit/faudit | 33 | src/faudit/faudit |
33 | src/fnet/fnet | 34 | src/fnet/fnet |
diff --git a/Makefile.in b/Makefile.in index 17bd76464..c94d8c7a4 100644 --- a/Makefile.in +++ b/Makefile.in | |||
@@ -26,7 +26,7 @@ COMPLETIONDIRS = src/zsh_completion src/bash_completion | |||
26 | .PHONY: all | 26 | .PHONY: all |
27 | all: all_items mydirs $(MAN_TARGET) filters | 27 | all: all_items mydirs $(MAN_TARGET) filters |
28 | APPS = src/firecfg/firecfg src/firejail/firejail src/firemon/firemon src/profstats/profstats src/jailcheck/jailcheck | 28 | APPS = src/firecfg/firecfg src/firejail/firejail src/firemon/firemon src/profstats/profstats src/jailcheck/jailcheck |
29 | SBOX_APPS = src/fbuilder/fbuilder src/ftee/ftee | 29 | SBOX_APPS = src/fbuilder/fbuilder src/ftee/ftee src/fids/fids |
30 | SBOX_APPS_NON_DUMPABLE = src/fcopy/fcopy src/fldd/fldd src/fnet/fnet src/fnetfilter/fnetfilter | 30 | SBOX_APPS_NON_DUMPABLE = src/fcopy/fcopy src/fldd/fldd src/fnet/fnet src/fnetfilter/fnetfilter |
31 | MYDIRS = src/lib $(MAN_SRC) $(COMPLETIONDIRS) | 31 | MYDIRS = src/lib $(MAN_SRC) $(COMPLETIONDIRS) |
32 | MYLIBS = src/libpostexecseccomp/libpostexecseccomp.so src/libtrace/libtrace.so src/libtracelog/libtracelog.so | 32 | MYLIBS = src/libpostexecseccomp/libpostexecseccomp.so src/libtrace/libtrace.so src/libtracelog/libtracelog.so |
@@ -135,7 +135,7 @@ endif | |||
135 | install -m 0644 -t $(DESTDIR)$(DOCDIR) COPYING README RELNOTES etc/templates/* | 135 | install -m 0644 -t $(DESTDIR)$(DOCDIR) COPYING README RELNOTES etc/templates/* |
136 | # profiles and settings | 136 | # profiles and settings |
137 | install -m 0755 -d $(DESTDIR)$(sysconfdir)/firejail | 137 | install -m 0755 -d $(DESTDIR)$(sysconfdir)/firejail |
138 | install -m 0644 -t $(DESTDIR)$(sysconfdir)/firejail etc/profile-a-l/*.profile etc/profile-m-z/*.profile etc/inc/*.inc etc/net/*.net etc/firejail.config | 138 | install -m 0644 -t $(DESTDIR)$(sysconfdir)/firejail etc/profile-a-l/*.profile etc/profile-m-z/*.profile etc/inc/*.inc etc/net/*.net etc/firejail.config etc/ids.config |
139 | sh -c "if [ ! -f $(DESTDIR)/$(sysconfdir)/firejail/login.users ]; then install -c -m 0644 etc/login.users $(DESTDIR)/$(sysconfdir)/firejail/.; fi;" | 139 | sh -c "if [ ! -f $(DESTDIR)/$(sysconfdir)/firejail/login.users ]; then install -c -m 0644 etc/login.users $(DESTDIR)/$(sysconfdir)/firejail/.; fi;" |
140 | ifeq ($(BUSYBOX_WORKAROUND),yes) | 140 | ifeq ($(BUSYBOX_WORKAROUND),yes) |
141 | ./mketc.sh $(DESTDIR)$(sysconfdir)/firejail/disable-common.inc | 141 | ./mketc.sh $(DESTDIR)$(sysconfdir)/firejail/disable-common.inc |
@@ -202,6 +202,36 @@ The old whitelist/blacklist will remain as aliasses for the next one or two rele | |||
202 | in order to give users a chance to switch their local profiles. | 202 | in order to give users a chance to switch their local profiles. |
203 | The latest discussion on this issue is here: https://github.com/netblue30/firejail/issues/4379 | 203 | The latest discussion on this issue is here: https://github.com/netblue30/firejail/issues/4379 |
204 | 204 | ||
205 | ### Intrusion Detection System ### | ||
206 | |||
207 | We are adding IDS capabilities in the next release. We have the list of files in [/etc/firejail/ids.config](https://github.com/netblue30/firejail/blob/master/etc/ids.config), | ||
208 | and we generate a [BLAKE2](https://en.wikipedia.org/wiki/BLAKE_%28hash_function%29) checksum in /var/lib/firejail/username.ids. | ||
209 | The program runs as regular user, each user has his own file in /var/lib/firejail. | ||
210 | |||
211 | Initialize the database: | ||
212 | ````` | ||
213 | $ firejail --ids-init | ||
214 | Loading /etc/firejail/ids.config config file | ||
215 | 500 1000 1500 2000 | ||
216 | 2457 files scanned | ||
217 | IDS database initialized | ||
218 | ````` | ||
219 | |||
220 | Later, we check it: | ||
221 | ````` | ||
222 | $ firejail --ids-check | ||
223 | Loading /etc/firejail/ids.config config file | ||
224 | 500 1000 1500 | ||
225 | Warning: modified /home/netblue/.bashrc | ||
226 | 2000 | ||
227 | 2457 files scanned: modified 1, permissions 0, new 0, removed 0 | ||
228 | ````` | ||
229 | The program will print the files that have been modified since the database was created, or the files with different access permissions. | ||
230 | New files and deleted files are also flagged. | ||
231 | |||
232 | Currently while scanning the file system symbolic links are not followed, and files the user doesn't have read access to are silently dropped. | ||
233 | The program can also be run as root (sudo firejail --ids-init/--ids-check). | ||
234 | |||
205 | ### Profile Statistics | 235 | ### Profile Statistics |
206 | 236 | ||
207 | A small tool to print profile statistics. Compile as usual and run in /etc/profiles: | 237 | A small tool to print profile statistics. Compile as usual and run in /etc/profiles: |
@@ -237,4 +267,4 @@ $ ./profstats *.profile | |||
237 | 267 | ||
238 | ### New profiles: | 268 | ### New profiles: |
239 | 269 | ||
240 | clion-eap, lifeograph, io.github.lainsce.Notejot, rednotebook, zim, microsoft-edge-beta | 270 | clion-eap, lifeograph, io.github.lainsce.Notejot, rednotebook, zim, microsoft-edge-beta, ncdu2 |
@@ -2,7 +2,8 @@ firejail (0.9.67) baseline; urgency=low | |||
2 | * work in progress | 2 | * work in progress |
3 | * deprecated --disable-whitelist at compile time | 3 | * deprecated --disable-whitelist at compile time |
4 | * deprecated whitelist=yes/no in /etc/firejail/firejail.config | 4 | * deprecated whitelist=yes/no in /etc/firejail/firejail.config |
5 | * new profiles: microsoft-edge-beta | 5 | * new profiles: microsoft-edge-beta, clion-eap, lifeograph, zim |
6 | * new profiles: io.github.lainsce.Notejot, rednotebook | ||
6 | -- netblue30 <netblue30@yahoo.com> Mon, 28 Jun 2021 09:00:00 -0500 | 7 | -- netblue30 <netblue30@yahoo.com> Mon, 28 Jun 2021 09:00:00 -0500 |
7 | 8 | ||
8 | firejail (0.9.66) baseline; urgency=low | 9 | firejail (0.9.66) baseline; urgency=low |
@@ -4350,7 +4350,7 @@ fi | |||
4350 | 4350 | ||
4351 | ac_config_files="$ac_config_files mkdeb.sh" | 4351 | ac_config_files="$ac_config_files mkdeb.sh" |
4352 | 4352 | ||
4353 | ac_config_files="$ac_config_files Makefile src/common.mk src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/fnetfilter/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/fsec-print/Makefile src/ftee/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile src/fsec-optimize/Makefile src/profstats/Makefile src/man/Makefile src/zsh_completion/Makefile src/bash_completion/Makefile test/Makefile src/jailcheck/Makefile" | 4353 | ac_config_files="$ac_config_files Makefile src/common.mk src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/fnetfilter/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/fsec-print/Makefile src/ftee/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile src/fsec-optimize/Makefile src/profstats/Makefile src/man/Makefile src/zsh_completion/Makefile src/bash_completion/Makefile test/Makefile src/jailcheck/Makefile src/fids/Makefile" |
4354 | 4354 | ||
4355 | cat >confcache <<\_ACEOF | 4355 | cat >confcache <<\_ACEOF |
4356 | # This file is a shell script that caches the results of configure | 4356 | # This file is a shell script that caches the results of configure |
@@ -5084,6 +5084,7 @@ do | |||
5084 | "src/bash_completion/Makefile") CONFIG_FILES="$CONFIG_FILES src/bash_completion/Makefile" ;; | 5084 | "src/bash_completion/Makefile") CONFIG_FILES="$CONFIG_FILES src/bash_completion/Makefile" ;; |
5085 | "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; | 5085 | "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; |
5086 | "src/jailcheck/Makefile") CONFIG_FILES="$CONFIG_FILES src/jailcheck/Makefile" ;; | 5086 | "src/jailcheck/Makefile") CONFIG_FILES="$CONFIG_FILES src/jailcheck/Makefile" ;; |
5087 | "src/fids/Makefile") CONFIG_FILES="$CONFIG_FILES src/fids/Makefile" ;; | ||
5087 | 5088 | ||
5088 | *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; | 5089 | *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; |
5089 | esac | 5090 | esac |
diff --git a/configure.ac b/configure.ac index 1f8e802b5..7879a5239 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -300,7 +300,7 @@ AC_CONFIG_FILES([Makefile src/common.mk src/lib/Makefile src/fcopy/Makefile src/ | |||
300 | src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/fsec-print/Makefile \ | 300 | src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/fsec-print/Makefile \ |
301 | src/ftee/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile src/fsec-optimize/Makefile \ | 301 | src/ftee/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile src/fsec-optimize/Makefile \ |
302 | src/profstats/Makefile src/man/Makefile src/zsh_completion/Makefile src/bash_completion/Makefile test/Makefile \ | 302 | src/profstats/Makefile src/man/Makefile src/zsh_completion/Makefile src/bash_completion/Makefile test/Makefile \ |
303 | src/jailcheck/Makefile]) | 303 | src/jailcheck/Makefile src/fids/Makefile]) |
304 | AC_OUTPUT | 304 | AC_OUTPUT |
305 | 305 | ||
306 | cat <<EOF | 306 | cat <<EOF |
diff --git a/etc/ids.config b/etc/ids.config new file mode 100644 index 000000000..09b0ae912 --- /dev/null +++ b/etc/ids.config | |||
@@ -0,0 +1,142 @@ | |||
1 | # /etc/firejail/ids.config - configuration file for Firejail's Intrusion Detection System | ||
2 | # This config file is overwritten when a new version of Firejail is installed. | ||
3 | # For global customization use /etc/firejail/ids.config.local. | ||
4 | include ids.config.local | ||
5 | # | ||
6 | # Each line is a file or directory name such as | ||
7 | # /usr/bin | ||
8 | # or | ||
9 | # ${HOME}/Desktop/*.desktop | ||
10 | # | ||
11 | # ${HOME} is expanded to the user's home directory, and * is the regular | ||
12 | # globbing match for zero or more characters. | ||
13 | # | ||
14 | # File or directory names starting with ! are not scanned. For example | ||
15 | # !${HOME}/.ssh/known_hosts | ||
16 | # ${HOME}/.ssh | ||
17 | # will scan all files in ~/.ssh directory with the exception of known_hosts | ||
18 | |||
19 | ### system executables ### | ||
20 | /bin | ||
21 | /sbin | ||
22 | /usr/bin | ||
23 | /usr/games | ||
24 | /usr/libexec | ||
25 | /usr/sbin | ||
26 | |||
27 | ### user executables ### | ||
28 | #/opt | ||
29 | #/usr/local | ||
30 | |||
31 | ### system libraries ### | ||
32 | #/lib | ||
33 | #/usr/lib | ||
34 | #/usr/lib32 | ||
35 | #/usr/lib64 | ||
36 | #/usr/libx32 | ||
37 | |||
38 | ### shells local ### | ||
39 | # bash | ||
40 | ${HOME}/.bash_login | ||
41 | ${HOME}/.bash_logout | ||
42 | ${HOME}/.bash_profile | ||
43 | ${HOME}/.bashrc | ||
44 | # fish | ||
45 | ${HOME}/.config/fish/config.fish | ||
46 | # others | ||
47 | ${HOME}/.cshrc | ||
48 | ${HOME}/.kshrc | ||
49 | ${HOME}/.login | ||
50 | ${HOME}/.logout | ||
51 | ${HOME}/.profile | ||
52 | ${HOME}/.tcshrc | ||
53 | # zsh | ||
54 | ${HOME}/.zlogin | ||
55 | ${HOME}/.zlogout | ||
56 | ${HOME}/.zshenv | ||
57 | ${HOME}/.zshprofile | ||
58 | ${HOME}/.zshrc | ||
59 | |||
60 | ### shells global ### | ||
61 | # all | ||
62 | /etc/dircolors | ||
63 | /etc/environment | ||
64 | /etc/profile | ||
65 | /etc/profile.d | ||
66 | /etc/shells | ||
67 | /etc/skel | ||
68 | # bash | ||
69 | /etc/bash_completion* | ||
70 | /etc/bash.bashrc | ||
71 | /etc/bashrc | ||
72 | # fish | ||
73 | /etc/fish | ||
74 | # ksh | ||
75 | /etc/ksh.kshrc | ||
76 | # tcsh | ||
77 | /etc/complete.tcsh | ||
78 | /etc/csh.cshrc | ||
79 | /etc/csh.login | ||
80 | /etc/csh.logout | ||
81 | # zsh | ||
82 | /etc/zlogin | ||
83 | /etc/zlogout | ||
84 | /etc/zprofile | ||
85 | /etc/zshenv | ||
86 | /etc/zshrc | ||
87 | |||
88 | ### X11 ### | ||
89 | /etc/X11 | ||
90 | ${HOME}/.xinitrc | ||
91 | ${HOME}/.xmodmaprc | ||
92 | ${HOME}/.xprofile | ||
93 | ${HOME}/.Xresources | ||
94 | ${HOME}/.xserverrc | ||
95 | ${HOME}/.Xsession | ||
96 | ${HOME}/.xsession | ||
97 | ${HOME}/.xsessionrc | ||
98 | |||
99 | ### window/desktop manager ### | ||
100 | ${HOME}/Desktop/*.desktop | ||
101 | ${HOME}/.config/autostart | ||
102 | ${HOME}/.config/lxsession/LXDE/autostart | ||
103 | ${HOME}/.gnomerc | ||
104 | ${HOME}/.gtkrc | ||
105 | ${HOME}/.kderc | ||
106 | |||
107 | ### security ### | ||
108 | /etc/aide | ||
109 | /etc/apparmor* | ||
110 | /etc/chkrootkit.conf | ||
111 | /etc/cracklib | ||
112 | /etc/libaudit.conf | ||
113 | /etc/group* | ||
114 | /etc/gshadow* | ||
115 | /etc/pam.* | ||
116 | /etc/passwd* | ||
117 | /etc/rkhunter* | ||
118 | /etc/securetty | ||
119 | /etc/security | ||
120 | /etc/selinux | ||
121 | /etc/shadow* | ||
122 | /etc/sudoers* | ||
123 | /etc/tripwire | ||
124 | ${HOME}/.config/firejail | ||
125 | ${HOME}/.gnupg | ||
126 | |||
127 | ### network security ### | ||
128 | /etc/ca-certificates* | ||
129 | /etc/hosts.* | ||
130 | /etc/services | ||
131 | /etc/snort | ||
132 | /etc/ssh | ||
133 | /etc/ssl | ||
134 | /etc/wireshark | ||
135 | !${HOME}/.ssh/known_hosts # excluding | ||
136 | ${HOME}/.ssh | ||
137 | /usr/share/ca-certificates | ||
138 | |||
139 | ### system config ### | ||
140 | /etc/cron.* | ||
141 | /etc/crontab | ||
142 | /etc/default | ||
diff --git a/etc/inc/disable-programs.inc b/etc/inc/disable-programs.inc index 44983dd14..7da2f276c 100644 --- a/etc/inc/disable-programs.inc +++ b/etc/inc/disable-programs.inc | |||
@@ -1103,4 +1103,5 @@ blacklist ${HOME}/.cache/yandex-browser | |||
1103 | blacklist ${HOME}/.cache/yandex-browser-beta | 1103 | blacklist ${HOME}/.cache/yandex-browser-beta |
1104 | blacklist ${HOME}/.cache/youtube-dl | 1104 | blacklist ${HOME}/.cache/youtube-dl |
1105 | blacklist ${HOME}/.cache/youtube-viewer | 1105 | blacklist ${HOME}/.cache/youtube-viewer |
1106 | blacklist ${RUNUSER}/*firefox* | ||
1106 | blacklist ${HOME}/.cache/zim | 1107 | blacklist ${HOME}/.cache/zim |
diff --git a/etc/profile-a-l/chromium-common-hardened.inc.profile b/etc/profile-a-l/chromium-common-hardened.inc.profile index 87a0a0994..19addd285 100644 --- a/etc/profile-a-l/chromium-common-hardened.inc.profile +++ b/etc/profile-a-l/chromium-common-hardened.inc.profile | |||
@@ -6,5 +6,4 @@ caps.drop all | |||
6 | nonewprivs | 6 | nonewprivs |
7 | noroot | 7 | noroot |
8 | protocol unix,inet,inet6,netlink | 8 | protocol unix,inet,inet6,netlink |
9 | # kcmp is required for ozone-platform=wayland, see #3783. | 9 | seccomp !chroot |
10 | seccomp !chroot,!kcmp | ||
diff --git a/etc/profile-a-l/code.profile b/etc/profile-a-l/code.profile index e19b78908..fdf94ec41 100644 --- a/etc/profile-a-l/code.profile +++ b/etc/profile-a-l/code.profile | |||
@@ -5,6 +5,21 @@ include code.local | |||
5 | # Persistent global definitions | 5 | # Persistent global definitions |
6 | include globals.local | 6 | include globals.local |
7 | 7 | ||
8 | # Disabled until someone reported positive feedback | ||
9 | ignore include disable-devel.inc | ||
10 | ignore include disable-exec.inc | ||
11 | ignore include disable-interpreters.inc | ||
12 | ignore include disable-xdg.inc | ||
13 | ignore whitelist ${DOWNLOADS} | ||
14 | ignore include whitelist-common.inc | ||
15 | ignore include whitelist-runuser-common.inc | ||
16 | ignore include whitelist-usr-share-common.inc | ||
17 | ignore include whitelist-var-common.inc | ||
18 | ignore apparmor | ||
19 | ignore disable-mnt | ||
20 | ignore dbus-user none | ||
21 | ignore dbus-system none | ||
22 | |||
8 | noblacklist ${HOME}/.config/Code | 23 | noblacklist ${HOME}/.config/Code |
9 | noblacklist ${HOME}/.config/Code - OSS | 24 | noblacklist ${HOME}/.config/Code - OSS |
10 | noblacklist ${HOME}/.vscode | 25 | noblacklist ${HOME}/.vscode |
@@ -13,31 +28,13 @@ noblacklist ${HOME}/.vscode-oss | |||
13 | # Allows files commonly used by IDEs | 28 | # Allows files commonly used by IDEs |
14 | include allow-common-devel.inc | 29 | include allow-common-devel.inc |
15 | 30 | ||
16 | include disable-common.inc | ||
17 | include disable-passwdmgr.inc | ||
18 | include disable-programs.inc | ||
19 | |||
20 | caps.drop all | ||
21 | netfilter | ||
22 | nodvd | ||
23 | nogroups | ||
24 | noinput | ||
25 | nonewprivs | ||
26 | noroot | ||
27 | nosound | 31 | nosound |
28 | notv | ||
29 | nou2f | ||
30 | novideo | ||
31 | protocol unix,inet,inet6,netlink | ||
32 | seccomp | ||
33 | shell none | ||
34 | |||
35 | private-cache | ||
36 | private-dev | ||
37 | private-tmp | ||
38 | 32 | ||
39 | # Disabling noexec ${HOME} for now since it will | 33 | # Disabling noexec ${HOME} for now since it will |
40 | # probably interfere with running some programmes | 34 | # probably interfere with running some programmes |
41 | # in VS Code | 35 | # in VS Code |
42 | # noexec ${HOME} | 36 | # noexec ${HOME} |
43 | noexec /tmp | 37 | noexec /tmp |
38 | |||
39 | # Redirect | ||
40 | include electron.profile | ||
diff --git a/etc/profile-a-l/firefox.profile b/etc/profile-a-l/firefox.profile index 3ad67734d..ff2a499dc 100644 --- a/etc/profile-a-l/firefox.profile +++ b/etc/profile-a-l/firefox.profile | |||
@@ -16,6 +16,7 @@ include globals.local | |||
16 | 16 | ||
17 | noblacklist ${HOME}/.cache/mozilla | 17 | noblacklist ${HOME}/.cache/mozilla |
18 | noblacklist ${HOME}/.mozilla | 18 | noblacklist ${HOME}/.mozilla |
19 | noblacklist ${RUNUSER}/*firefox* | ||
19 | 20 | ||
20 | blacklist /usr/libexec | 21 | blacklist /usr/libexec |
21 | 22 | ||
@@ -35,6 +36,7 @@ whitelist /usr/share/gnome-shell/search-providers/firefox-search-provider.ini | |||
35 | whitelist /usr/share/gtk-doc/html | 36 | whitelist /usr/share/gtk-doc/html |
36 | whitelist /usr/share/mozilla | 37 | whitelist /usr/share/mozilla |
37 | whitelist /usr/share/webext | 38 | whitelist /usr/share/webext |
39 | whitelist ${RUNUSER}/*firefox* | ||
38 | include whitelist-usr-share-common.inc | 40 | include whitelist-usr-share-common.inc |
39 | 41 | ||
40 | # firefox requires a shell to launch on Arch - add the next line to your firefox.local to enable private-bin. | 42 | # firefox requires a shell to launch on Arch - add the next line to your firefox.local to enable private-bin. |
diff --git a/etc/profile-a-l/kodi.profile b/etc/profile-a-l/kodi.profile index b7091f1fc..f909728a5 100644 --- a/etc/profile-a-l/kodi.profile +++ b/etc/profile-a-l/kodi.profile | |||
@@ -12,6 +12,12 @@ ignore noexec ${HOME} | |||
12 | #ignore nogroups | 12 | #ignore nogroups |
13 | #ignore noroot | 13 | #ignore noroot |
14 | #ignore private-dev | 14 | #ignore private-dev |
15 | # Add the following to your kodi.local if you use the Lutris Kodi Addon | ||
16 | #noblacklist /sbin | ||
17 | #noblacklist /usr/sbin | ||
18 | #noblacklist ${HOME}/.cache/lutris | ||
19 | #noblacklist ${HOME}/.config/lutris | ||
20 | #noblacklist ${HOME}/.local/share/lutris | ||
15 | 21 | ||
16 | noblacklist ${HOME}/.kodi | 22 | noblacklist ${HOME}/.kodi |
17 | noblacklist ${MUSIC} | 23 | noblacklist ${MUSIC} |
diff --git a/etc/profile-m-z/minitube.profile b/etc/profile-m-z/minitube.profile index 3fe3428d0..b8a551b6c 100644 --- a/etc/profile-m-z/minitube.profile +++ b/etc/profile-m-z/minitube.profile | |||
@@ -47,7 +47,7 @@ notv | |||
47 | nou2f | 47 | nou2f |
48 | novideo | 48 | novideo |
49 | protocol unix,inet,inet6,netlink | 49 | protocol unix,inet,inet6,netlink |
50 | seccomp !kcmp | 50 | seccomp |
51 | shell none | 51 | shell none |
52 | tracelog | 52 | tracelog |
53 | 53 | ||
diff --git a/etc/profile-m-z/ncdu2.profile b/etc/profile-m-z/ncdu2.profile new file mode 100644 index 000000000..5b6364c5d --- /dev/null +++ b/etc/profile-m-z/ncdu2.profile | |||
@@ -0,0 +1,11 @@ | |||
1 | # Firejail profile for ncdu2 | ||
2 | # Description: Ncurses disk usage viewer (zig rewrite) | ||
3 | # This file is overwritten after every install/update | ||
4 | # Persistent local customizations | ||
5 | include ncdu2.local | ||
6 | # Persistent global definitions | ||
7 | # added by included profile | ||
8 | #include globals.local | ||
9 | |||
10 | # Redirect | ||
11 | include ncdu.profile | ||
diff --git a/etc/profile-m-z/telegram.profile b/etc/profile-m-z/telegram.profile index e7580938d..53f932eef 100644 --- a/etc/profile-m-z/telegram.profile +++ b/etc/profile-m-z/telegram.profile | |||
@@ -48,6 +48,7 @@ private-etc alsa,alternatives,ca-certificates,crypto-policies,fonts,group,ld.so. | |||
48 | private-tmp | 48 | private-tmp |
49 | 49 | ||
50 | dbus-user filter | 50 | dbus-user filter |
51 | dbus-user.own org.telegram.desktop.* | ||
51 | dbus-user.talk org.freedesktop.Notifications | 52 | dbus-user.talk org.freedesktop.Notifications |
52 | dbus-user.talk org.kde.StatusNotifierWatcher | 53 | dbus-user.talk org.kde.StatusNotifierWatcher |
53 | dbus-user.talk org.gnome.Mutter.IdleMonitor | 54 | dbus-user.talk org.gnome.Mutter.IdleMonitor |
diff --git a/etc/templates/syscalls.txt b/etc/templates/syscalls.txt index 3992c984a..38f789923 100644 --- a/etc/templates/syscalls.txt +++ b/etc/templates/syscalls.txt | |||
@@ -89,18 +89,24 @@ Inheritance of groups | |||
89 | What to do if seccomp breaks a program | 89 | What to do if seccomp breaks a program |
90 | -------------------------------------- | 90 | -------------------------------------- |
91 | 91 | ||
92 | Start `journalctl --grep=SECCOMP --follow` in a terminal and run | ||
93 | `firejail --seccomp-error-action=log /path/to/program` in a second terminal. | ||
94 | Now switch back to the first terminal (where `journalctl` is running) and look | ||
95 | for the numbers of the blocked syscall(s) (`syscall=<NUMBER>`). As soon as you | ||
96 | have found them, you can stop `journalctl` (^C) and execute | ||
97 | `firejail --debug-syscalls | grep NUMBER` to get the name of the syscall. | ||
98 | In the particular case that it is a 32bit syscall on a 64bit system, use `ausyscall i386 NUMBER`. | ||
99 | Now you can add a seccomp exception using `seccomp !NAME`. | ||
100 | |||
101 | If the blocked syscall is ptrace, consider to add allow-debuggers to the profile. | ||
102 | |||
92 | ``` | 103 | ``` |
93 | $ journalctl --grep=syscall --follow | 104 | term1$ journalctl --grep=SECCOMP --follow |
94 | <...> audit[…]: SECCOMP <...> syscall=161 <...> | 105 | term2$ firejail --seccomp-error-action=log /usr/bin/signal-desktop |
95 | $ firejail --debug-syscalls | grep 161 | 106 | term1$ (journalctl --grep=SECCOMP --follow) |
96 | 161 - chroot | 107 | audit[1234]: SECCOMP ... comm="signal-desktop" exe="/usr/bin/signal-desktop" sig=31 arch=c000003e syscall=161 ... |
108 | ^C | ||
109 | term1$ firejail --debug-syscalls | grep "^161[[:space:]]" | ||
110 | 161 - chroot | ||
97 | ``` | 111 | ``` |
98 | Profile: `seccomp -> seccomp !chroot` | 112 | Profile: `seccomp -> seccomp !chroot` |
99 | |||
100 | Start `journalctl --grep=syscall --follow` in a terminal, then start the broken | ||
101 | program. Now you see one or more long lines containing `syscall=NUMBER` somewhere. | ||
102 | Stop journalctl (^C) and execute `firejail --debug-syscalls | grep NUMBER`. You | ||
103 | will see something like `NUMBER - NAME`, because you now know the name of the | ||
104 | syscall, you can add an exception to seccomp by putting `!NAME` to seccomp. | ||
105 | |||
106 | If the blocked syscall is ptrace, consider to add allow-debuggers to the profile. | ||
diff --git a/src/common.mk.in b/src/common.mk.in index 5ae8bf204..d117433dc 100644 --- a/src/common.mk.in +++ b/src/common.mk.in | |||
@@ -40,7 +40,7 @@ BINOBJS = $(foreach file, $(OBJS), $file) | |||
40 | 40 | ||
41 | CFLAGS = @CFLAGS@ | 41 | CFLAGS = @CFLAGS@ |
42 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV) | 42 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV) |
43 | CFLAGS += -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' -DBINDIR='"$(bindir)"' | 43 | CFLAGS += -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' -DBINDIR='"$(bindir)"' -DVARDIR='"/var/lib/firejail"' |
44 | MANFLAGS = $(HAVE_LTS) $(HAVE_OUTPUT) $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_USERTMPFS) $(HAVE_DBUSPROXY) $(HAVE_FIRETUNNEL) $(HAVE_GLOBALCFG) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_FILE_TRANSFER) $(HAVE_SELINUX) $(HAVE_SUID) $(HAVE_FORCE_NONEWPRIVS) | 44 | MANFLAGS = $(HAVE_LTS) $(HAVE_OUTPUT) $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_USERTMPFS) $(HAVE_DBUSPROXY) $(HAVE_FIRETUNNEL) $(HAVE_GLOBALCFG) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_FILE_TRANSFER) $(HAVE_SELINUX) $(HAVE_SUID) $(HAVE_FORCE_NONEWPRIVS) |
45 | CFLAGS += $(MANFLAGS) | 45 | CFLAGS += $(MANFLAGS) |
46 | CFLAGS += -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -Wformat -Wformat-security | 46 | CFLAGS += -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -Wformat -Wformat-security |
diff --git a/src/fids/Makefile.in b/src/fids/Makefile.in new file mode 100644 index 000000000..5530bcee2 --- /dev/null +++ b/src/fids/Makefile.in | |||
@@ -0,0 +1,18 @@ | |||
1 | .PHONY: all | ||
2 | all: fids | ||
3 | |||
4 | include ../common.mk | ||
5 | |||
6 | %.o : %.c $(H_FILE_LIST) ../include/common.h | ||
7 | $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@ | ||
8 | |||
9 | #fseccomp: $(OBJS) ../lib/common.o ../lib/errno.o ../lib/syscall.o | ||
10 | fids: $(OBJS) | ||
11 | $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) | ||
12 | |||
13 | .PHONY: clean | ||
14 | clean:; rm -fr *.o fids *.gcov *.gcda *.gcno *.plist | ||
15 | |||
16 | .PHONY: distclean | ||
17 | distclean: clean | ||
18 | rm -fr Makefile | ||
diff --git a/src/fids/blake2b.c b/src/fids/blake2b.c new file mode 100644 index 000000000..f2aa5ae66 --- /dev/null +++ b/src/fids/blake2b.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2021 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | /* A simple unkeyed BLAKE2b Implementation based on the official reference | ||
22 | * from https://github.com/BLAKE2/BLAKE2. | ||
23 | * | ||
24 | * The original code was released under CC0 1.0 Universal license (Creative Commons), | ||
25 | * a public domain license. | ||
26 | */ | ||
27 | |||
28 | #include "fids.h" | ||
29 | |||
30 | // little-endian vs big-endian is irrelevant since the checksum is calculated and checked on the same computer. | ||
31 | static inline uint64_t load64( const void *src ) { | ||
32 | uint64_t w; | ||
33 | memcpy( &w, src, sizeof( w ) ); | ||
34 | return w; | ||
35 | } | ||
36 | |||
37 | // mixing function | ||
38 | #define ROTR64(x, y) (((x) >> (y)) ^ ((x) << (64 - (y)))) | ||
39 | #define G(a, b, c, d, x, y) { \ | ||
40 | v[a] = v[a] + v[b] + x; \ | ||
41 | v[d] = ROTR64(v[d] ^ v[a], 32); \ | ||
42 | v[c] = v[c] + v[d]; \ | ||
43 | v[b] = ROTR64(v[b] ^ v[c], 24); \ | ||
44 | v[a] = v[a] + v[b] + y; \ | ||
45 | v[d] = ROTR64(v[d] ^ v[a], 16); \ | ||
46 | v[c] = v[c] + v[d]; \ | ||
47 | v[b] = ROTR64(v[b] ^ v[c], 63); } | ||
48 | |||
49 | // init vector | ||
50 | static const uint64_t iv[8] = { | ||
51 | 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, | ||
52 | 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1, | ||
53 | 0x510E527FADE682D1, 0x9B05688C2B3E6C1F, | ||
54 | 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179 | ||
55 | }; | ||
56 | |||
57 | |||
58 | const uint8_t sigma[12][16] = { | ||
59 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, | ||
60 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, | ||
61 | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, | ||
62 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, | ||
63 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, | ||
64 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, | ||
65 | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, | ||
66 | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, | ||
67 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, | ||
68 | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, | ||
69 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, | ||
70 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } | ||
71 | }; | ||
72 | |||
73 | // blake2b context | ||
74 | typedef struct { | ||
75 | uint8_t b[128]; // input buffer | ||
76 | uint64_t h[8]; // chained state | ||
77 | uint64_t t[2]; // total number of bytes | ||
78 | size_t c; // pointer for b[] | ||
79 | size_t outlen; // digest size | ||
80 | } CTX; | ||
81 | |||
82 | // compress function | ||
83 | static void compress(CTX *ctx, int last) { | ||
84 | uint64_t m[16]; | ||
85 | uint64_t v[16]; | ||
86 | size_t i; | ||
87 | |||
88 | for (i = 0; i < 16; i++) | ||
89 | m[i] = load64(&ctx->b[8 * i]); | ||
90 | |||
91 | for (i = 0; i < 8; i++) { | ||
92 | v[i] = ctx->h[i]; | ||
93 | v[i + 8] = iv[i]; | ||
94 | } | ||
95 | |||
96 | v[12] ^= ctx->t[0]; | ||
97 | v[13] ^= ctx->t[1]; | ||
98 | if (last) | ||
99 | v[14] = ~v[14]; | ||
100 | |||
101 | for (i = 0; i < 12; i++) { | ||
102 | G( 0, 4, 8, 12, m[sigma[i][ 0]], m[sigma[i][ 1]]); | ||
103 | G( 1, 5, 9, 13, m[sigma[i][ 2]], m[sigma[i][ 3]]); | ||
104 | G( 2, 6, 10, 14, m[sigma[i][ 4]], m[sigma[i][ 5]]); | ||
105 | G( 3, 7, 11, 15, m[sigma[i][ 6]], m[sigma[i][ 7]]); | ||
106 | G( 0, 5, 10, 15, m[sigma[i][ 8]], m[sigma[i][ 9]]); | ||
107 | G( 1, 6, 11, 12, m[sigma[i][10]], m[sigma[i][11]]); | ||
108 | G( 2, 7, 8, 13, m[sigma[i][12]], m[sigma[i][13]]); | ||
109 | G( 3, 4, 9, 14, m[sigma[i][14]], m[sigma[i][15]]); | ||
110 | } | ||
111 | |||
112 | for( i = 0; i < 8; ++i ) | ||
113 | ctx->h[i] ^= v[i] ^ v[i + 8]; | ||
114 | } | ||
115 | |||
116 | static int init(CTX *ctx, size_t outlen) { // (keylen=0: no key) | ||
117 | size_t i; | ||
118 | |||
119 | if (outlen == 0 || outlen > 64) | ||
120 | return -1; | ||
121 | |||
122 | for (i = 0; i < 8; i++) | ||
123 | ctx->h[i] = iv[i]; | ||
124 | ctx->h[0] ^= 0x01010000 ^ outlen; | ||
125 | |||
126 | ctx->t[0] = 0; | ||
127 | ctx->t[1] = 0; | ||
128 | ctx->c = 0; | ||
129 | ctx->outlen = outlen; | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static void update(CTX *ctx, const void *in, size_t inlen) { | ||
135 | size_t i; | ||
136 | |||
137 | for (i = 0; i < inlen; i++) { | ||
138 | if (ctx->c == 128) { | ||
139 | ctx->t[0] += ctx->c; | ||
140 | if (ctx->t[0] < ctx->c) | ||
141 | ctx->t[1]++; | ||
142 | compress(ctx, 0); | ||
143 | ctx->c = 0; | ||
144 | } | ||
145 | ctx->b[ctx->c++] = ((const uint8_t *) in)[i]; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | static void final(CTX *ctx, void *out) { | ||
150 | size_t i; | ||
151 | |||
152 | ctx->t[0] += ctx->c; | ||
153 | if (ctx->t[0] < ctx->c) | ||
154 | ctx->t[1]++; | ||
155 | |||
156 | while (ctx->c < 128) | ||
157 | ctx->b[ctx->c++] = 0; | ||
158 | compress(ctx, 1); | ||
159 | |||
160 | for (i = 0; i < ctx->outlen; i++) { | ||
161 | ((uint8_t *) out)[i] = | ||
162 | (ctx->h[i >> 3] >> (8 * (i & 7))) & 0xFF; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | // public function | ||
167 | int blake2b(void *out, size_t outlen, const void *in, size_t inlen) { | ||
168 | CTX ctx; | ||
169 | |||
170 | if (init(&ctx, outlen)) | ||
171 | return -1; | ||
172 | update(&ctx, in, inlen); | ||
173 | final(&ctx, out); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
diff --git a/src/fids/config b/src/fids/config new file mode 100644 index 000000000..c18c97260 --- /dev/null +++ b/src/fids/config | |||
@@ -0,0 +1,16 @@ | |||
1 | /bin | ||
2 | /sbin | ||
3 | /usr/bin | ||
4 | /usr/sbin | ||
5 | /usr/games | ||
6 | /opt | ||
7 | /usr/share/ca-certificates | ||
8 | |||
9 | |||
10 | /home/netblue/.bashrc | ||
11 | /home/netblue/.config/firejail | ||
12 | /home/netblue/.config/autostart | ||
13 | /home/netblue/Desktop/*.desktop | ||
14 | /home/netblue/.ssh | ||
15 | /home/netblue/.gnupg | ||
16 | |||
diff --git a/src/fids/db.c b/src/fids/db.c new file mode 100644 index 000000000..35caf7eeb --- /dev/null +++ b/src/fids/db.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2021 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #include"fids.h" | ||
21 | |||
22 | typedef struct db_t { | ||
23 | struct db_t *next; | ||
24 | char *fname; | ||
25 | char *checksum; | ||
26 | char *mode; | ||
27 | int checked; | ||
28 | } DB; | ||
29 | |||
30 | #define MAXBUF 4096 | ||
31 | static DB *database[HASH_MAX] = {NULL}; | ||
32 | |||
33 | // djb2 hash function by Dan Bernstein | ||
34 | static unsigned hash(const char *str) { | ||
35 | unsigned long hash = 5381; | ||
36 | int c; | ||
37 | |||
38 | while ((c = *str++) != '\0') | ||
39 | hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ | ||
40 | |||
41 | return hash & (HASH_MAX - 1); | ||
42 | } | ||
43 | |||
44 | #if 0 | ||
45 | // for testing the hash table | ||
46 | static void db_print(void) { | ||
47 | int i; | ||
48 | for (i = 0; i < HASH_MAX; i++) { | ||
49 | int cnt = 0; | ||
50 | DB *ptr = database[i]; | ||
51 | while (ptr) { | ||
52 | cnt++; | ||
53 | ptr = ptr->next; | ||
54 | } | ||
55 | printf("%d ", cnt); | ||
56 | fflush(0); | ||
57 | } | ||
58 | printf("\n"); | ||
59 | } | ||
60 | #endif | ||
61 | |||
62 | static void db_add(const char *fname, const char *checksum, const char *mode) { | ||
63 | DB *ptr = malloc(sizeof(DB)); | ||
64 | if (!ptr) | ||
65 | errExit("malloc"); | ||
66 | ptr->fname = strdup(fname); | ||
67 | ptr->checksum = strdup(checksum); | ||
68 | ptr->mode = strdup(mode); | ||
69 | ptr->checked = 0; | ||
70 | if (!ptr->fname || !ptr->checksum || !ptr->mode) | ||
71 | errExit("strdup"); | ||
72 | |||
73 | unsigned h = hash(fname); | ||
74 | ptr->next = database[h]; | ||
75 | database[h] = ptr; | ||
76 | } | ||
77 | |||
78 | void db_check(const char *fname, const char *checksum, const char *mode) { | ||
79 | assert(fname); | ||
80 | assert(checksum); | ||
81 | assert(mode); | ||
82 | |||
83 | unsigned h =hash(fname); | ||
84 | DB *ptr = database[h]; | ||
85 | while (ptr) { | ||
86 | if (strcmp(fname, ptr->fname) == 0) { | ||
87 | ptr->checked = 1; | ||
88 | break; | ||
89 | } | ||
90 | ptr = ptr->next; | ||
91 | } | ||
92 | |||
93 | if (ptr ) { | ||
94 | if (strcmp(checksum, ptr->checksum)) { | ||
95 | f_modified++; | ||
96 | fprintf(stderr, "\nWarning: modified %s\n", fname); | ||
97 | } | ||
98 | if (strcmp(mode, ptr->mode)) { | ||
99 | f_permissions++; | ||
100 | fprintf(stderr, "\nWarning: permissions %s: old %s, new %s\n", | ||
101 | fname, ptr->mode, mode); | ||
102 | } | ||
103 | } | ||
104 | else { | ||
105 | f_new++; | ||
106 | fprintf(stderr, "\nWarning: new file %s\n", fname); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | void db_missing(void) { | ||
111 | int i; | ||
112 | for (i = 0; i < HASH_MAX; i++) { | ||
113 | DB *ptr = database[i]; | ||
114 | while (ptr) { | ||
115 | if (!ptr->checked) { | ||
116 | f_removed++; | ||
117 | fprintf(stderr, "Warning: removed %s\n", ptr->fname); | ||
118 | } | ||
119 | ptr = ptr->next; | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | |||
124 | // return 0 if ok, 1 if error | ||
125 | int db_init(void) { | ||
126 | char buf[MAXBUF]; | ||
127 | while(fgets(buf, MAXBUF, stdin)) { | ||
128 | // split - tab separated | ||
129 | |||
130 | char *mode = buf; | ||
131 | char *ptr = strchr(buf, '\t'); | ||
132 | if (!ptr) | ||
133 | goto errexit; | ||
134 | *ptr = '\0'; | ||
135 | |||
136 | char *checksum = ptr + 1; | ||
137 | ptr = strchr(checksum, '\t'); | ||
138 | if (!ptr) | ||
139 | goto errexit; | ||
140 | *ptr = '\0'; | ||
141 | |||
142 | char *fname = ptr + 1; | ||
143 | ptr = strchr(fname, '\n'); | ||
144 | if (!ptr) | ||
145 | goto errexit; | ||
146 | *ptr = '\0'; | ||
147 | |||
148 | db_add(fname, checksum, mode); | ||
149 | } | ||
150 | // db_print(); | ||
151 | |||
152 | return 0; | ||
153 | |||
154 | errexit: | ||
155 | fprintf(stderr, "Error fids: database corrupted\n"); | ||
156 | exit(1); | ||
157 | } | ||
158 | |||
diff --git a/src/fids/db_exclude.c b/src/fids/db_exclude.c new file mode 100644 index 000000000..994e6f9df --- /dev/null +++ b/src/fids/db_exclude.c | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2021 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #include"fids.h" | ||
21 | |||
22 | typedef struct db_exclude_t { | ||
23 | struct db_exclude_t *next; | ||
24 | char *fname; | ||
25 | int len; | ||
26 | } DB_EXCLUDE; | ||
27 | static DB_EXCLUDE *database = NULL; | ||
28 | |||
29 | void db_exclude_add(const char *fname) { | ||
30 | assert(fname); | ||
31 | |||
32 | DB_EXCLUDE *ptr = malloc(sizeof(DB_EXCLUDE)); | ||
33 | if (!ptr) | ||
34 | errExit("malloc"); | ||
35 | |||
36 | ptr->fname = strdup(fname); | ||
37 | if (!ptr->fname) | ||
38 | errExit("strdup"); | ||
39 | ptr->len = strlen(fname); | ||
40 | ptr->next = database; | ||
41 | database = ptr; | ||
42 | } | ||
43 | |||
44 | int db_exclude_check(const char *fname) { | ||
45 | assert(fname); | ||
46 | |||
47 | DB_EXCLUDE *ptr = database; | ||
48 | while (ptr != NULL) { | ||
49 | if (strncmp(fname, ptr->fname, ptr->len) == 0) | ||
50 | return 1; | ||
51 | ptr = ptr->next; | ||
52 | } | ||
53 | |||
54 | return 0; | ||
55 | } | ||
56 | |||
diff --git a/src/fids/fids.h b/src/fids/fids.h new file mode 100644 index 000000000..a2e2886fe --- /dev/null +++ b/src/fids/fids.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2021 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #ifndef FIDS_H | ||
21 | #define FIDS_H | ||
22 | |||
23 | #include "../include/common.h" | ||
24 | |||
25 | // main.c | ||
26 | #define MAX_DIR_LEVEL 20 // max directory tree depth | ||
27 | #define MAX_INCLUDE_LEVEL 10 // max include level for config files | ||
28 | extern int f_scanned; | ||
29 | extern int f_modified; | ||
30 | extern int f_new; | ||
31 | extern int f_removed; | ||
32 | extern int f_permissions; | ||
33 | |||
34 | // db.c | ||
35 | #define HASH_MAX 2048 // power of 2 | ||
36 | int db_init(void); | ||
37 | void db_check(const char *fname, const char *checksum, const char *mode); | ||
38 | void db_missing(void); | ||
39 | |||
40 | // db_exclude.c | ||
41 | void db_exclude_add(const char *fname); | ||
42 | int db_exclude_check(const char *fname); | ||
43 | |||
44 | |||
45 | // blake2b.c | ||
46 | //#define KEY_SIZE 128 // key size in bytes | ||
47 | #define KEY_SIZE 256 | ||
48 | //#define KEY_SIZE 512 | ||
49 | int blake2b(void *out, size_t outlen, const void *in, size_t inlen); | ||
50 | |||
51 | #endif \ No newline at end of file | ||
diff --git a/src/fids/main.c b/src/fids/main.c new file mode 100644 index 000000000..c899b55e1 --- /dev/null +++ b/src/fids/main.c | |||
@@ -0,0 +1,371 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2021 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #include "fids.h" | ||
21 | #include <sys/types.h> | ||
22 | #include <sys/stat.h> | ||
23 | #include <unistd.h> | ||
24 | #include <fcntl.h> | ||
25 | #include <sys/mman.h> | ||
26 | #include <dirent.h> | ||
27 | #include <glob.h> | ||
28 | |||
29 | #define MAXBUF 4096 | ||
30 | |||
31 | static int dir_level = 1; | ||
32 | static int include_level = 0; | ||
33 | int arg_init = 0; | ||
34 | int arg_check = 0; | ||
35 | char *arg_homedir = NULL; | ||
36 | char *arg_dbfile = NULL; | ||
37 | |||
38 | int f_scanned = 0; | ||
39 | int f_modified = 0; | ||
40 | int f_new = 0; | ||
41 | int f_removed = 0; | ||
42 | int f_permissions = 0; | ||
43 | |||
44 | |||
45 | |||
46 | static inline int is_dir(const char *fname) { | ||
47 | assert(fname); | ||
48 | |||
49 | struct stat s; | ||
50 | if (stat(fname, &s) == 0) { | ||
51 | if (S_ISDIR(s.st_mode)) | ||
52 | return 1; | ||
53 | } | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static inline int is_link(const char *fname) { | ||
58 | assert(fname); | ||
59 | |||
60 | char c; | ||
61 | ssize_t rv = readlink(fname, &c, 1); | ||
62 | return (rv != -1); | ||
63 | } | ||
64 | |||
65 | // mode is an array of 10 chars or more | ||
66 | static inline void file_mode(const char *fname, char *mode) { | ||
67 | assert(fname); | ||
68 | assert(mode); | ||
69 | |||
70 | struct stat s; | ||
71 | if (stat(fname, &s)) { | ||
72 | *mode = '\0'; | ||
73 | return; | ||
74 | } | ||
75 | |||
76 | sprintf(mode, (s.st_mode & S_IRUSR) ? "r" : "-"); | ||
77 | sprintf(mode + 1, (s.st_mode & S_IWUSR) ? "w" : "-"); | ||
78 | sprintf(mode + 2, (s.st_mode & S_IXUSR) ? "x" : "-"); | ||
79 | sprintf(mode + 3, (s.st_mode & S_IRGRP) ? "r" : "-"); | ||
80 | sprintf(mode + 4, (s.st_mode & S_IWGRP) ? "w" : "-"); | ||
81 | sprintf(mode + 5, (s.st_mode & S_IXGRP) ? "x" : "-"); | ||
82 | sprintf(mode + 6, (s.st_mode & S_IROTH) ? "r" : "-"); | ||
83 | sprintf(mode + 7, (s.st_mode & S_IWOTH) ? "w" : "-"); | ||
84 | sprintf(mode + 8, (s.st_mode & S_IXOTH) ? "x" : "-"); | ||
85 | } | ||
86 | |||
87 | |||
88 | static void file_checksum(const char *fname) { | ||
89 | assert(fname); | ||
90 | |||
91 | int fd = open(fname, O_RDONLY); | ||
92 | if (fd == -1) | ||
93 | return; | ||
94 | |||
95 | off_t size = lseek(fd, 0, SEEK_END); | ||
96 | if (size < 0) { | ||
97 | close(fd); | ||
98 | return; | ||
99 | } | ||
100 | |||
101 | char *content = "empty"; | ||
102 | int mmapped = 0; | ||
103 | if (size == 0) { | ||
104 | // empty files don't mmap - use "empty" string as the file content | ||
105 | size = 6; // strlen("empty") + 1 | ||
106 | } | ||
107 | else { | ||
108 | content = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); | ||
109 | close(fd); | ||
110 | mmapped = 1; | ||
111 | } | ||
112 | |||
113 | unsigned char checksum[KEY_SIZE / 8]; | ||
114 | blake2b(checksum, sizeof(checksum), content, size); | ||
115 | if (mmapped) | ||
116 | munmap(content, size); | ||
117 | |||
118 | // calculate blake2 checksum | ||
119 | char str_checksum[(KEY_SIZE / 8) * 2 + 1]; | ||
120 | int long unsigned i; | ||
121 | char *ptr = str_checksum; | ||
122 | for (i = 0; i < sizeof(checksum); i++, ptr += 2) | ||
123 | sprintf(ptr, "%02x", (unsigned char ) checksum[i]); | ||
124 | |||
125 | // build permissions string | ||
126 | char mode[10]; | ||
127 | file_mode(fname, mode); | ||
128 | |||
129 | if (arg_init) | ||
130 | printf("%s\t%s\t%s\n", mode, str_checksum, fname); | ||
131 | else if (arg_check) | ||
132 | db_check(fname, str_checksum, mode); | ||
133 | else | ||
134 | assert(0); | ||
135 | |||
136 | f_scanned++; | ||
137 | if (f_scanned % 500 == 0) | ||
138 | fprintf(stderr, "%d ", f_scanned); | ||
139 | fflush(0); | ||
140 | } | ||
141 | |||
142 | void list_directory(const char *fname) { | ||
143 | assert(fname); | ||
144 | if (dir_level > MAX_DIR_LEVEL) { | ||
145 | fprintf(stderr, "Warning fids: maximum depth level exceeded for %s\n", fname); | ||
146 | return; | ||
147 | } | ||
148 | |||
149 | if (db_exclude_check(fname)) | ||
150 | return; | ||
151 | |||
152 | if (is_link(fname)) | ||
153 | return; | ||
154 | |||
155 | if (!is_dir(fname)) { | ||
156 | file_checksum(fname); | ||
157 | return; | ||
158 | } | ||
159 | |||
160 | DIR *dir; | ||
161 | struct dirent *entry; | ||
162 | |||
163 | if (!(dir = opendir(fname))) | ||
164 | return; | ||
165 | |||
166 | dir_level++; | ||
167 | while ((entry = readdir(dir)) != NULL) { | ||
168 | if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) | ||
169 | continue; | ||
170 | char *path; | ||
171 | if (asprintf(&path, "%s/%s", fname, entry->d_name) == -1) | ||
172 | errExit("asprintf"); | ||
173 | list_directory(path); | ||
174 | free(path); | ||
175 | } | ||
176 | closedir(dir); | ||
177 | dir_level--; | ||
178 | } | ||
179 | |||
180 | void globbing(const char *fname) { | ||
181 | assert(fname); | ||
182 | |||
183 | // filter top directory | ||
184 | if (strcmp(fname, "/") == 0) | ||
185 | return; | ||
186 | |||
187 | glob_t globbuf; | ||
188 | int globerr = glob(fname, GLOB_NOCHECK | GLOB_NOSORT | GLOB_PERIOD, NULL, &globbuf); | ||
189 | if (globerr) { | ||
190 | fprintf(stderr, "Error fids: failed to glob pattern %s\n", fname); | ||
191 | exit(1); | ||
192 | } | ||
193 | |||
194 | long unsigned i; | ||
195 | for (i = 0; i < globbuf.gl_pathc; i++) { | ||
196 | char *path = globbuf.gl_pathv[i]; | ||
197 | assert(path); | ||
198 | |||
199 | list_directory(path); | ||
200 | } | ||
201 | |||
202 | globfree(&globbuf); | ||
203 | } | ||
204 | |||
205 | static void process_config(const char *fname) { | ||
206 | assert(fname); | ||
207 | |||
208 | if (++include_level >= MAX_INCLUDE_LEVEL) { | ||
209 | fprintf(stderr, "Error ids: maximum include level for config files exceeded\n"); | ||
210 | exit(1); | ||
211 | } | ||
212 | |||
213 | // make sure the file is owned by root | ||
214 | struct stat s; | ||
215 | if (stat(fname, &s)) { | ||
216 | if (include_level == 1) { | ||
217 | fprintf(stderr, "Error ids: config file not found\n"); | ||
218 | exit(1); | ||
219 | } | ||
220 | return; | ||
221 | } | ||
222 | if (s.st_uid || s.st_gid) { | ||
223 | fprintf(stderr, "Error ids: config file not owned by root\n"); | ||
224 | exit(1); | ||
225 | } | ||
226 | |||
227 | fprintf(stderr, "Loading %s config file\n", fname); | ||
228 | FILE *fp = fopen(fname, "r"); | ||
229 | if (!fp) { | ||
230 | fprintf(stderr, "Error fids: cannot open config file %s\n", fname); | ||
231 | exit(1); | ||
232 | } | ||
233 | |||
234 | char buf[MAXBUF]; | ||
235 | int line = 0; | ||
236 | while (fgets(buf, MAXBUF, fp)) { | ||
237 | line++; | ||
238 | |||
239 | // trim \n | ||
240 | char *ptr = strchr(buf, '\n'); | ||
241 | if (ptr) | ||
242 | *ptr = '\0'; | ||
243 | |||
244 | // comments | ||
245 | ptr = strchr(buf, '#'); | ||
246 | if (ptr) | ||
247 | *ptr = '\0'; | ||
248 | |||
249 | // empty space | ||
250 | ptr = buf; | ||
251 | while (*ptr == ' ' || *ptr == '\t') | ||
252 | ptr++; | ||
253 | char *start = ptr; | ||
254 | |||
255 | // empty line | ||
256 | if (*start == '\0') | ||
257 | continue; | ||
258 | |||
259 | // trailing spaces | ||
260 | ptr = start + strlen(start); | ||
261 | ptr--; | ||
262 | while (*ptr == ' ' || *ptr == '\t') | ||
263 | *ptr-- = '\0'; | ||
264 | |||
265 | // replace ${HOME} | ||
266 | if (strncmp(start, "include", 7) == 0) { | ||
267 | ptr = start + 7; | ||
268 | if ((*ptr != ' ' && *ptr != '\t') || *ptr == '\0') { | ||
269 | fprintf(stderr, "Error fids: invalid line %d in %s\n", line, fname); | ||
270 | exit(1); | ||
271 | } | ||
272 | while (*ptr == ' ' || *ptr == '\t') | ||
273 | ptr++; | ||
274 | |||
275 | if (*ptr == '/') | ||
276 | process_config(ptr); | ||
277 | else { | ||
278 | // assume the file is in /etc/firejail | ||
279 | char *tmp; | ||
280 | if (asprintf(&tmp, "/etc/firejail/%s", ptr) == -1) | ||
281 | errExit("asprintf"); | ||
282 | process_config(tmp); | ||
283 | free(tmp); | ||
284 | } | ||
285 | } | ||
286 | else if (*start == '!') { | ||
287 | // exclude file or dir | ||
288 | start++; | ||
289 | if (strncmp(start, "${HOME}", 7)) | ||
290 | db_exclude_add(start); | ||
291 | else { | ||
292 | char *fname; | ||
293 | if (asprintf(&fname, "%s%s", arg_homedir, start + 7) == -1) | ||
294 | errExit("asprintf"); | ||
295 | db_exclude_add(fname); | ||
296 | free(fname); | ||
297 | } | ||
298 | } | ||
299 | else if (strncmp(start, "${HOME}", 7)) | ||
300 | globbing(start); | ||
301 | else { | ||
302 | char *fname; | ||
303 | if (asprintf(&fname, "%s%s", arg_homedir, start + 7) == -1) | ||
304 | errExit("asprintf"); | ||
305 | globbing(fname); | ||
306 | free(fname); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | fclose(fp); | ||
311 | include_level--; | ||
312 | } | ||
313 | |||
314 | |||
315 | |||
316 | void usage(void) { | ||
317 | printf("Usage: fids [--help|-h|-?] --init|--check homedir\n"); | ||
318 | } | ||
319 | |||
320 | int main(int argc, char **argv) { | ||
321 | int i; | ||
322 | for (i = 1; i < argc; i++) { | ||
323 | if (strcmp(argv[i], "-h") == 0 || | ||
324 | strcmp(argv[i], "-?") == 0 || | ||
325 | strcmp(argv[i], "--help") == 0) { | ||
326 | usage(); | ||
327 | return 0; | ||
328 | } | ||
329 | else if (strcmp(argv[i], "--init") == 0) | ||
330 | arg_init = 1; | ||
331 | else if (strcmp(argv[i], "--check") == 0) | ||
332 | arg_check = 1; | ||
333 | else if (strncmp(argv[i], "--", 2) == 0) { | ||
334 | fprintf(stderr, "Error fids: invalid argument %s\n", argv[i]); | ||
335 | exit(1); | ||
336 | } | ||
337 | } | ||
338 | |||
339 | if (argc != 3) { | ||
340 | fprintf(stderr, "Error fids: invalid number of arguments\n"); | ||
341 | exit(1); | ||
342 | } | ||
343 | arg_homedir = argv[2]; | ||
344 | |||
345 | int op = arg_check + arg_init; | ||
346 | if (op == 0 || op == 2) { | ||
347 | fprintf(stderr, "Error fids: use either --init or --check\n"); | ||
348 | exit(1); | ||
349 | } | ||
350 | |||
351 | if (arg_init) { | ||
352 | process_config(SYSCONFDIR"/ids.config"); | ||
353 | fprintf(stderr, "\n%d files scanned\n", f_scanned); | ||
354 | fprintf(stderr, "IDS database initialized\n"); | ||
355 | } | ||
356 | else if (arg_check) { | ||
357 | if (db_init()) { | ||
358 | fprintf(stderr, "Error: IDS database not initialized, please run \"firejail --ids-init\"\n"); | ||
359 | exit(1); | ||
360 | } | ||
361 | |||
362 | process_config(SYSCONFDIR"/ids.config"); | ||
363 | fprintf(stderr, "\n%d files scanned: modified %d, permissions %d, new %d, removed %d\n", | ||
364 | f_scanned, f_modified, f_permissions, f_new, f_removed); | ||
365 | db_missing(); | ||
366 | } | ||
367 | else | ||
368 | assert(0); | ||
369 | |||
370 | return 0; | ||
371 | } | ||
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config index 3b0ad0aed..046cb209a 100644 --- a/src/firecfg/firecfg.config +++ b/src/firecfg/firecfg.config | |||
@@ -567,6 +567,7 @@ mypaint | |||
567 | mypaint-ora-thumbnailer | 567 | mypaint-ora-thumbnailer |
568 | natron | 568 | natron |
569 | ncdu | 569 | ncdu |
570 | ncdu2 | ||
570 | neochat | 571 | neochat |
571 | neomutt | 572 | neomutt |
572 | netactview | 573 | netactview |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 545573c08..2a7d88575 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -835,7 +835,6 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc, | |||
835 | #define PATH_FNET_MAIN (LIBDIR "/firejail/fnet") // when called from main thread | 835 | #define PATH_FNET_MAIN (LIBDIR "/firejail/fnet") // when called from main thread |
836 | #define PATH_FNET (RUN_FIREJAIL_LIB_DIR "/fnet") // when called from sandbox thread | 836 | #define PATH_FNET (RUN_FIREJAIL_LIB_DIR "/fnet") // when called from sandbox thread |
837 | 837 | ||
838 | //#define PATH_FNETFILTER (LIBDIR "/firejail/fnetfilter") | ||
839 | #define PATH_FNETFILTER (RUN_FIREJAIL_LIB_DIR "/fnetfilter") | 838 | #define PATH_FNETFILTER (RUN_FIREJAIL_LIB_DIR "/fnetfilter") |
840 | 839 | ||
841 | #define PATH_FIREMON (PREFIX "/bin/firemon") | 840 | #define PATH_FIREMON (PREFIX "/bin/firemon") |
@@ -848,17 +847,16 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc, | |||
848 | // it is also run from inside the sandbox by --debug; in this case we do an access(filename, X_OK) test first | 847 | // it is also run from inside the sandbox by --debug; in this case we do an access(filename, X_OK) test first |
849 | #define PATH_FSEC_PRINT (LIBDIR "/firejail/fsec-print") | 848 | #define PATH_FSEC_PRINT (LIBDIR "/firejail/fsec-print") |
850 | 849 | ||
851 | //#define PATH_FSEC_OPTIMIZE (LIBDIR "/firejail/fsec-optimize") | ||
852 | #define PATH_FSEC_OPTIMIZE (RUN_FIREJAIL_LIB_DIR "/fsec-optimize") | 850 | #define PATH_FSEC_OPTIMIZE (RUN_FIREJAIL_LIB_DIR "/fsec-optimize") |
853 | 851 | ||
854 | //#define PATH_FCOPY (LIBDIR "/firejail/fcopy") | ||
855 | #define PATH_FCOPY (RUN_FIREJAIL_LIB_DIR "/fcopy") | 852 | #define PATH_FCOPY (RUN_FIREJAIL_LIB_DIR "/fcopy") |
856 | 853 | ||
857 | #define SBOX_STDIN_FILE "/run/firejail/mnt/sbox_stdin" | 854 | #define SBOX_STDIN_FILE "/run/firejail/mnt/sbox_stdin" |
858 | 855 | ||
859 | //#define PATH_FLDD (LIBDIR "/firejail/fldd") | ||
860 | #define PATH_FLDD (RUN_FIREJAIL_LIB_DIR "/fldd") | 856 | #define PATH_FLDD (RUN_FIREJAIL_LIB_DIR "/fldd") |
861 | 857 | ||
858 | #define PATH_FIDS (LIBDIR "/firejail/fids") | ||
859 | |||
862 | // bitmapped filters for sbox_run | 860 | // bitmapped filters for sbox_run |
863 | #define SBOX_ROOT (1 << 0) // run the sandbox as root | 861 | #define SBOX_ROOT (1 << 0) // run the sandbox as root |
864 | #define SBOX_USER (1 << 1) // run the sandbox as a regular user | 862 | #define SBOX_USER (1 << 1) // run the sandbox as a regular user |
@@ -903,4 +901,7 @@ void dhcp_start(void); | |||
903 | // selinux.c | 901 | // selinux.c |
904 | void selinux_relabel_path(const char *path, const char *inside_path); | 902 | void selinux_relabel_path(const char *path, const char *inside_path); |
905 | 903 | ||
904 | // ids.c | ||
905 | void run_ids(int argc, char **argv); | ||
906 | |||
906 | #endif | 907 | #endif |
diff --git a/src/firejail/ids.c b/src/firejail/ids.c new file mode 100644 index 000000000..59acdb1fe --- /dev/null +++ b/src/firejail/ids.c | |||
@@ -0,0 +1,89 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2021 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #include "firejail.h" | ||
21 | #include <sys/types.h> | ||
22 | #include <sys/stat.h> | ||
23 | #include <fcntl.h> | ||
24 | |||
25 | |||
26 | static void ids_init(void) { | ||
27 | // store checksums as root in /var/lib/firejail/${USERNAME}.ids | ||
28 | char *fname; | ||
29 | if (asprintf(&fname, VARDIR"/%s.ids", cfg.username) == -1) | ||
30 | errExit("asprintf"); | ||
31 | |||
32 | int rv = unlink(fname); | ||
33 | (void) rv; | ||
34 | int fd = open(fname, O_CREAT | O_TRUNC | O_WRONLY, 0600); | ||
35 | if (fd < 0) { | ||
36 | fprintf(stderr, "Error: cannot create %s\n", fname); | ||
37 | exit(1); | ||
38 | } | ||
39 | |||
40 | // redirect output | ||
41 | close(STDOUT_FILENO); | ||
42 | if (dup(fd) != STDOUT_FILENO) | ||
43 | errExit("dup"); | ||
44 | close(fd); | ||
45 | |||
46 | sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FIDS, "--init", cfg.homedir); | ||
47 | } | ||
48 | |||
49 | static void ids_check(void) { | ||
50 | // store checksums as root in /var/lib/firejail/${USERNAME}.ids | ||
51 | char *fname; | ||
52 | if (asprintf(&fname, VARDIR"/%s.ids", cfg.username) == -1) | ||
53 | errExit("asprintf"); | ||
54 | |||
55 | int fd = open(fname, O_RDONLY); | ||
56 | if (fd < 0) { | ||
57 | fprintf(stderr, "Error: cannot open %s\n", fname); | ||
58 | exit(1); | ||
59 | } | ||
60 | |||
61 | // redirect input | ||
62 | close(STDIN_FILENO); | ||
63 | if (dup(fd) != STDIN_FILENO) | ||
64 | errExit("dup"); | ||
65 | close(fd); | ||
66 | |||
67 | sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP| SBOX_ALLOW_STDIN, 3, PATH_FIDS, "--check", cfg.homedir); | ||
68 | } | ||
69 | |||
70 | void run_ids(int argc, char **argv) { | ||
71 | if (argc != 2) { | ||
72 | fprintf(stderr, "Error: only one IDS command expected\n"); | ||
73 | exit(1); | ||
74 | } | ||
75 | |||
76 | EUID_ROOT(); | ||
77 | struct stat s; | ||
78 | if (stat(VARDIR, &s)) // /var/lib/firejail | ||
79 | create_empty_dir_as_root(VARDIR, 0700); | ||
80 | |||
81 | if (strcmp(argv[1], "--ids-init") == 0) | ||
82 | ids_init(); | ||
83 | else if (strcmp(argv[1], "--ids-check") == 0) | ||
84 | ids_check(); | ||
85 | else | ||
86 | fprintf(stderr, "Error: unrecognized IDS command\n"); | ||
87 | |||
88 | exit(0); | ||
89 | } \ No newline at end of file | ||
diff --git a/src/firejail/main.c b/src/firejail/main.c index 655e6e9d0..ef3bf8bf5 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -1068,6 +1068,10 @@ int main(int argc, char **argv, char **envp) { | |||
1068 | if (check_arg(argc, argv, "--build", 0)) // supports both --build and --build=filename | 1068 | if (check_arg(argc, argv, "--build", 0)) // supports both --build and --build=filename |
1069 | run_builder(argc, argv); // this function will not return | 1069 | run_builder(argc, argv); // this function will not return |
1070 | 1070 | ||
1071 | // intrusion detection system | ||
1072 | if (check_arg(argc, argv, "--ids-", 0)) // supports both --ids-init and --ids-check | ||
1073 | run_ids(argc, argv); // this function will not return | ||
1074 | |||
1071 | EUID_ROOT(); | 1075 | EUID_ROOT(); |
1072 | #ifndef HAVE_SUID | 1076 | #ifndef HAVE_SUID |
1073 | if (geteuid() != 0) { | 1077 | if (geteuid() != 0) { |
diff --git a/src/firejail/usage.c b/src/firejail/usage.c index b4f3021c7..d843c74ae 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c | |||
@@ -98,6 +98,8 @@ static char *usage_str = | |||
98 | " --help, -? - this help screen.\n" | 98 | " --help, -? - this help screen.\n" |
99 | " --hostname=name - set sandbox hostname.\n" | 99 | " --hostname=name - set sandbox hostname.\n" |
100 | " --hosts-file=file - use file as /etc/hosts.\n" | 100 | " --hosts-file=file - use file as /etc/hosts.\n" |
101 | " --ids-check - verify file system.\n" | ||
102 | " --ids-init - initialize IDS database.\n" | ||
101 | " --ignore=command - ignore command in profile files.\n" | 103 | " --ignore=command - ignore command in profile files.\n" |
102 | #ifdef HAVE_NETWORK | 104 | #ifdef HAVE_NETWORK |
103 | " --interface=name - move interface in sandbox.\n" | 105 | " --interface=name - move interface in sandbox.\n" |
diff --git a/src/tools/profcleaner.sh b/src/tools/profcleaner.sh index 709008e08..96402aed6 100755 --- a/src/tools/profcleaner.sh +++ b/src/tools/profcleaner.sh | |||
@@ -38,8 +38,8 @@ else | |||
38 | fi | 38 | fi |
39 | 39 | ||
40 | sed -i -E \ | 40 | sed -i -E \ |
41 | -e "s/^(# |#)?blacklist/\1deny/" \ | 41 | -e "s/^(# |#)?(ignore )?blacklist/\1\2deny/" \ |
42 | -e "s/^(# |#)?noblacklist/\1nodeny/" \ | 42 | -e "s/^(# |#)?(ignore )?noblacklist/\1\2nodeny/" \ |
43 | -e "s/^(# |#)?whitelist/\1allow/" \ | 43 | -e "s/^(# |#)?(ignore )?whitelist/\1\2allow/" \ |
44 | -e "s/^(# |#)?nowhitelist/\1noallow/" \ | 44 | -e "s/^(# |#)?(ignore )?nowhitelist/\1\2noallow/" \ |
45 | "${profiles[@]}" | 45 | "${profiles[@]}" |