aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile.in4
-rw-r--r--README.md32
-rw-r--r--RELNOTES3
-rwxr-xr-xconfigure3
-rw-r--r--configure.ac2
-rw-r--r--etc/ids.config142
-rw-r--r--etc/inc/disable-programs.inc1
-rw-r--r--etc/profile-a-l/chromium-common-hardened.inc.profile3
-rw-r--r--etc/profile-a-l/code.profile39
-rw-r--r--etc/profile-a-l/firefox.profile2
-rw-r--r--etc/profile-a-l/kodi.profile6
-rw-r--r--etc/profile-m-z/minitube.profile2
-rw-r--r--etc/profile-m-z/ncdu2.profile11
-rw-r--r--etc/profile-m-z/telegram.profile1
-rw-r--r--etc/templates/syscalls.txt30
-rw-r--r--src/common.mk.in2
-rw-r--r--src/fids/Makefile.in18
-rw-r--r--src/fids/blake2b.c176
-rw-r--r--src/fids/config16
-rw-r--r--src/fids/db.c158
-rw-r--r--src/fids/db_exclude.c56
-rw-r--r--src/fids/fids.h51
-rw-r--r--src/fids/main.c371
-rw-r--r--src/firecfg/firecfg.config1
-rw-r--r--src/firejail/firejail.h9
-rw-r--r--src/firejail/ids.c89
-rw-r--r--src/firejail/main.c4
-rw-r--r--src/firejail/usage.c2
-rwxr-xr-xsrc/tools/profcleaner.sh8
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
22firejail.1 22firejail.1
23firemon.1 23firemon.1
24firecfg.1 24firecfg.1
25jailcheck.5 25jailcheck.1
26mkdeb.sh 26mkdeb.sh
27src/firejail/firejail 27src/firejail/firejail
28src/firemon/firemon 28src/firemon/firemon
29src/firecfg/firecfg 29src/firecfg/firecfg
30src/ftee/ftee 30src/ftee/ftee
31src/fids/fids
31src/tags 32src/tags
32src/faudit/faudit 33src/faudit/faudit
33src/fnet/fnet 34src/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
27all: all_items mydirs $(MAN_TARGET) filters 27all: all_items mydirs $(MAN_TARGET) filters
28APPS = src/firecfg/firecfg src/firejail/firejail src/firemon/firemon src/profstats/profstats src/jailcheck/jailcheck 28APPS = src/firecfg/firecfg src/firejail/firejail src/firemon/firemon src/profstats/profstats src/jailcheck/jailcheck
29SBOX_APPS = src/fbuilder/fbuilder src/ftee/ftee 29SBOX_APPS = src/fbuilder/fbuilder src/ftee/ftee src/fids/fids
30SBOX_APPS_NON_DUMPABLE = src/fcopy/fcopy src/fldd/fldd src/fnet/fnet src/fnetfilter/fnetfilter 30SBOX_APPS_NON_DUMPABLE = src/fcopy/fcopy src/fldd/fldd src/fnet/fnet src/fnetfilter/fnetfilter
31MYDIRS = src/lib $(MAN_SRC) $(COMPLETIONDIRS) 31MYDIRS = src/lib $(MAN_SRC) $(COMPLETIONDIRS)
32MYLIBS = src/libpostexecseccomp/libpostexecseccomp.so src/libtrace/libtrace.so src/libtracelog/libtracelog.so 32MYLIBS = 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;"
140ifeq ($(BUSYBOX_WORKAROUND),yes) 140ifeq ($(BUSYBOX_WORKAROUND),yes)
141 ./mketc.sh $(DESTDIR)$(sysconfdir)/firejail/disable-common.inc 141 ./mketc.sh $(DESTDIR)$(sysconfdir)/firejail/disable-common.inc
diff --git a/README.md b/README.md
index 2fd8e3009..98968a606 100644
--- a/README.md
+++ b/README.md
@@ -202,6 +202,36 @@ The old whitelist/blacklist will remain as aliasses for the next one or two rele
202in order to give users a chance to switch their local profiles. 202in order to give users a chance to switch their local profiles.
203The latest discussion on this issue is here: https://github.com/netblue30/firejail/issues/4379 203The latest discussion on this issue is here: https://github.com/netblue30/firejail/issues/4379
204 204
205### Intrusion Detection System ###
206
207We 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),
208and we generate a [BLAKE2](https://en.wikipedia.org/wiki/BLAKE_%28hash_function%29) checksum in /var/lib/firejail/username.ids.
209The program runs as regular user, each user has his own file in /var/lib/firejail.
210
211Initialize the database:
212`````
213$ firejail --ids-init
214Loading /etc/firejail/ids.config config file
215500 1000 1500 2000
2162457 files scanned
217IDS database initialized
218`````
219
220Later, we check it:
221`````
222$ firejail --ids-check
223Loading /etc/firejail/ids.config config file
224500 1000 1500
225Warning: modified /home/netblue/.bashrc
2262000
2272457 files scanned: modified 1, permissions 0, new 0, removed 0
228`````
229The program will print the files that have been modified since the database was created, or the files with different access permissions.
230New files and deleted files are also flagged.
231
232Currently while scanning the file system symbolic links are not followed, and files the user doesn't have read access to are silently dropped.
233The program can also be run as root (sudo firejail --ids-init/--ids-check).
234
205### Profile Statistics 235### Profile Statistics
206 236
207A small tool to print profile statistics. Compile as usual and run in /etc/profiles: 237A 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
240clion-eap, lifeograph, io.github.lainsce.Notejot, rednotebook, zim, microsoft-edge-beta 270clion-eap, lifeograph, io.github.lainsce.Notejot, rednotebook, zim, microsoft-edge-beta, ncdu2
diff --git a/RELNOTES b/RELNOTES
index 49b88ac08..405888cc4 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -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
8firejail (0.9.66) baseline; urgency=low 9firejail (0.9.66) baseline; urgency=low
diff --git a/configure b/configure
index 9e883191a..f78bbaded 100755
--- a/configure
+++ b/configure
@@ -4350,7 +4350,7 @@ fi
4350 4350
4351ac_config_files="$ac_config_files mkdeb.sh" 4351ac_config_files="$ac_config_files mkdeb.sh"
4352 4352
4353ac_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" 4353ac_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
4355cat >confcache <<\_ACEOF 4355cat >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/
300src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/fsec-print/Makefile \ 300src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/fsec-print/Makefile \
301src/ftee/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile src/fsec-optimize/Makefile \ 301src/ftee/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile src/fsec-optimize/Makefile \
302src/profstats/Makefile src/man/Makefile src/zsh_completion/Makefile src/bash_completion/Makefile test/Makefile \ 302src/profstats/Makefile src/man/Makefile src/zsh_completion/Makefile src/bash_completion/Makefile test/Makefile \
303src/jailcheck/Makefile]) 303src/jailcheck/Makefile src/fids/Makefile])
304AC_OUTPUT 304AC_OUTPUT
305 305
306cat <<EOF 306cat <<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.
4include 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
1103blacklist ${HOME}/.cache/yandex-browser-beta 1103blacklist ${HOME}/.cache/yandex-browser-beta
1104blacklist ${HOME}/.cache/youtube-dl 1104blacklist ${HOME}/.cache/youtube-dl
1105blacklist ${HOME}/.cache/youtube-viewer 1105blacklist ${HOME}/.cache/youtube-viewer
1106blacklist ${RUNUSER}/*firefox*
1106blacklist ${HOME}/.cache/zim 1107blacklist ${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
6nonewprivs 6nonewprivs
7noroot 7noroot
8protocol unix,inet,inet6,netlink 8protocol unix,inet,inet6,netlink
9# kcmp is required for ozone-platform=wayland, see #3783. 9seccomp !chroot
10seccomp !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
6include globals.local 6include globals.local
7 7
8# Disabled until someone reported positive feedback
9ignore include disable-devel.inc
10ignore include disable-exec.inc
11ignore include disable-interpreters.inc
12ignore include disable-xdg.inc
13ignore whitelist ${DOWNLOADS}
14ignore include whitelist-common.inc
15ignore include whitelist-runuser-common.inc
16ignore include whitelist-usr-share-common.inc
17ignore include whitelist-var-common.inc
18ignore apparmor
19ignore disable-mnt
20ignore dbus-user none
21ignore dbus-system none
22
8noblacklist ${HOME}/.config/Code 23noblacklist ${HOME}/.config/Code
9noblacklist ${HOME}/.config/Code - OSS 24noblacklist ${HOME}/.config/Code - OSS
10noblacklist ${HOME}/.vscode 25noblacklist ${HOME}/.vscode
@@ -13,31 +28,13 @@ noblacklist ${HOME}/.vscode-oss
13# Allows files commonly used by IDEs 28# Allows files commonly used by IDEs
14include allow-common-devel.inc 29include allow-common-devel.inc
15 30
16include disable-common.inc
17include disable-passwdmgr.inc
18include disable-programs.inc
19
20caps.drop all
21netfilter
22nodvd
23nogroups
24noinput
25nonewprivs
26noroot
27nosound 31nosound
28notv
29nou2f
30novideo
31protocol unix,inet,inet6,netlink
32seccomp
33shell none
34
35private-cache
36private-dev
37private-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}
43noexec /tmp 37noexec /tmp
38
39# Redirect
40include 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
17noblacklist ${HOME}/.cache/mozilla 17noblacklist ${HOME}/.cache/mozilla
18noblacklist ${HOME}/.mozilla 18noblacklist ${HOME}/.mozilla
19noblacklist ${RUNUSER}/*firefox*
19 20
20blacklist /usr/libexec 21blacklist /usr/libexec
21 22
@@ -35,6 +36,7 @@ whitelist /usr/share/gnome-shell/search-providers/firefox-search-provider.ini
35whitelist /usr/share/gtk-doc/html 36whitelist /usr/share/gtk-doc/html
36whitelist /usr/share/mozilla 37whitelist /usr/share/mozilla
37whitelist /usr/share/webext 38whitelist /usr/share/webext
39whitelist ${RUNUSER}/*firefox*
38include whitelist-usr-share-common.inc 40include 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
16noblacklist ${HOME}/.kodi 22noblacklist ${HOME}/.kodi
17noblacklist ${MUSIC} 23noblacklist ${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
47nou2f 47nou2f
48novideo 48novideo
49protocol unix,inet,inet6,netlink 49protocol unix,inet,inet6,netlink
50seccomp !kcmp 50seccomp
51shell none 51shell none
52tracelog 52tracelog
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
5include ncdu2.local
6# Persistent global definitions
7# added by included profile
8#include globals.local
9
10# Redirect
11include 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.
48private-tmp 48private-tmp
49 49
50dbus-user filter 50dbus-user filter
51dbus-user.own org.telegram.desktop.*
51dbus-user.talk org.freedesktop.Notifications 52dbus-user.talk org.freedesktop.Notifications
52dbus-user.talk org.kde.StatusNotifierWatcher 53dbus-user.talk org.kde.StatusNotifierWatcher
53dbus-user.talk org.gnome.Mutter.IdleMonitor 54dbus-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
89What to do if seccomp breaks a program 89What to do if seccomp breaks a program
90-------------------------------------- 90--------------------------------------
91 91
92Start `journalctl --grep=SECCOMP --follow` in a terminal and run
93`firejail --seccomp-error-action=log /path/to/program` in a second terminal.
94Now switch back to the first terminal (where `journalctl` is running) and look
95for the numbers of the blocked syscall(s) (`syscall=<NUMBER>`). As soon as you
96have found them, you can stop `journalctl` (^C) and execute
97`firejail --debug-syscalls | grep NUMBER` to get the name of the syscall.
98In the particular case that it is a 32bit syscall on a 64bit system, use `ausyscall i386 NUMBER`.
99Now you can add a seccomp exception using `seccomp !NAME`.
100
101If the blocked syscall is ptrace, consider to add allow-debuggers to the profile.
102
92``` 103```
93$ journalctl --grep=syscall --follow 104term1$ journalctl --grep=SECCOMP --follow
94<...> audit[…]: SECCOMP <...> syscall=161 <...> 105term2$ firejail --seccomp-error-action=log /usr/bin/signal-desktop
95$ firejail --debug-syscalls | grep 161 106term1$ (journalctl --grep=SECCOMP --follow)
96161 - chroot 107audit[1234]: SECCOMP ... comm="signal-desktop" exe="/usr/bin/signal-desktop" sig=31 arch=c000003e syscall=161 ...
108^C
109term1$ firejail --debug-syscalls | grep "^161[[:space:]]"
110161 - chroot
97``` 111```
98Profile: `seccomp -> seccomp !chroot` 112Profile: `seccomp -> seccomp !chroot`
99
100Start `journalctl --grep=syscall --follow` in a terminal, then start the broken
101program. Now you see one or more long lines containing `syscall=NUMBER` somewhere.
102Stop journalctl (^C) and execute `firejail --debug-syscalls | grep NUMBER`. You
103will see something like `NUMBER - NAME`, because you now know the name of the
104syscall, you can add an exception to seccomp by putting `!NAME` to seccomp.
105
106If 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
41CFLAGS = @CFLAGS@ 41CFLAGS = @CFLAGS@
42CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV) 42CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV)
43CFLAGS += -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' -DBINDIR='"$(bindir)"' 43CFLAGS += -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' -DBINDIR='"$(bindir)"' -DVARDIR='"/var/lib/firejail"'
44MANFLAGS = $(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) 44MANFLAGS = $(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)
45CFLAGS += $(MANFLAGS) 45CFLAGS += $(MANFLAGS)
46CFLAGS += -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -Wformat -Wformat-security 46CFLAGS += -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
2all: fids
3
4include ../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
10fids: $(OBJS)
11 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
12
13.PHONY: clean
14clean:; rm -fr *.o fids *.gcov *.gcda *.gcno *.plist
15
16.PHONY: distclean
17distclean: 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.
31static 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
50static const uint64_t iv[8] = {
51 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B,
52 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1,
53 0x510E527FADE682D1, 0x9B05688C2B3E6C1F,
54 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179
55};
56
57
58const 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
74typedef 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
83static 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
116static 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
134static 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
149static 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
167int 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
22typedef 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
31static DB *database[HASH_MAX] = {NULL};
32
33// djb2 hash function by Dan Bernstein
34static 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
46static 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
62static 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
78void 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
110void 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
125int 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
154errexit:
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
22typedef struct db_exclude_t {
23 struct db_exclude_t *next;
24 char *fname;
25 int len;
26} DB_EXCLUDE;
27static DB_EXCLUDE *database = NULL;
28
29void 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
44int 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
28extern int f_scanned;
29extern int f_modified;
30extern int f_new;
31extern int f_removed;
32extern int f_permissions;
33
34// db.c
35#define HASH_MAX 2048 // power of 2
36int db_init(void);
37void db_check(const char *fname, const char *checksum, const char *mode);
38void db_missing(void);
39
40// db_exclude.c
41void db_exclude_add(const char *fname);
42int 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
49int 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
31static int dir_level = 1;
32static int include_level = 0;
33int arg_init = 0;
34int arg_check = 0;
35char *arg_homedir = NULL;
36char *arg_dbfile = NULL;
37
38int f_scanned = 0;
39int f_modified = 0;
40int f_new = 0;
41int f_removed = 0;
42int f_permissions = 0;
43
44
45
46static 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
57static 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
66static 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
88static 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
142void 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
180void 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
205static 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
316void usage(void) {
317 printf("Usage: fids [--help|-h|-?] --init|--check homedir\n");
318}
319
320int 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
567mypaint-ora-thumbnailer 567mypaint-ora-thumbnailer
568natron 568natron
569ncdu 569ncdu
570ncdu2
570neochat 571neochat
571neomutt 572neomutt
572netactview 573netactview
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
904void selinux_relabel_path(const char *path, const char *inside_path); 902void selinux_relabel_path(const char *path, const char *inside_path);
905 903
904// ids.c
905void 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
26static 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
49static 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
70void 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
38fi 38fi
39 39
40sed -i -E \ 40sed -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[@]}"