summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Topi Miettinen <toiwoton@gmail.com>2017-08-13 14:07:31 +0300
committerLibravatar Topi Miettinen <toiwoton@gmail.com>2017-08-13 17:31:07 +0300
commit63e9d849f662d1a494c6396d4a439cd4c91dfa7e (patch)
tree703cc8c9c0eb5b9e528f025961df7f322f797737
parentmerges (diff)
downloadfirejail-63e9d849f662d1a494c6396d4a439cd4c91dfa7e.tar.gz
firejail-63e9d849f662d1a494c6396d4a439cd4c91dfa7e.tar.zst
firejail-63e9d849f662d1a494c6396d4a439cd4c91dfa7e.zip
Allow any syscall to be blacklisted (#1447)
Allow any syscall to be blacklisted with aid of LD_PRELOAD library, libpostexecseccomp.so. Closes: #1447
-rw-r--r--Makefile.in5
-rwxr-xr-xconfigure3
-rw-r--r--configure.ac2
-rw-r--r--src/firejail/firejail.h4
-rw-r--r--src/firejail/fs_trace.c5
-rw-r--r--src/firejail/main.c1
-rw-r--r--src/firejail/preproc.c5
-rw-r--r--src/firejail/sandbox.c13
-rw-r--r--src/firejail/seccomp.c34
-rw-r--r--src/fseccomp/fseccomp.h15
-rw-r--r--src/fseccomp/main.c30
-rw-r--r--src/fseccomp/seccomp.c118
-rw-r--r--src/fseccomp/seccomp_file.c9
-rw-r--r--src/fseccomp/syscall.c64
-rw-r--r--src/libpostexecseccomp/Makefile.in26
-rw-r--r--src/libpostexecseccomp/libpostexecseccomp.c59
-rw-r--r--src/libpostexecseccomp/libpostexecseccomp.h25
-rw-r--r--src/man/firejail.txt26
18 files changed, 369 insertions, 75 deletions
diff --git a/Makefile.in b/Makefile.in
index 6d8bf5f72..d9d7bcd37 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,6 +1,6 @@
1all: apps man filters 1all: apps man filters
2MYLIBS = src/lib 2MYLIBS = src/lib
3APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/fnet src/fseccomp src/fcopy src/fldd 3APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/fnet src/fseccomp src/fcopy src/fldd src/libpostexecseccomp
4MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 4MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5
5SECCOMP_FILTERS = seccomp seccomp.i386 seccomp.amd64 5SECCOMP_FILTERS = seccomp seccomp.i386 seccomp.amd64
6 6
@@ -85,6 +85,7 @@ realinstall:
85 install -m 0755 -d $(DESTDIR)/$(libdir)/firejail 85 install -m 0755 -d $(DESTDIR)/$(libdir)/firejail
86 install -c -m 0644 src/libtrace/libtrace.so $(DESTDIR)/$(libdir)/firejail/. 86 install -c -m 0644 src/libtrace/libtrace.so $(DESTDIR)/$(libdir)/firejail/.
87 install -c -m 0644 src/libtracelog/libtracelog.so $(DESTDIR)/$(libdir)/firejail/. 87 install -c -m 0644 src/libtracelog/libtracelog.so $(DESTDIR)/$(libdir)/firejail/.
88 install -c -m 0644 src/libpostexecseccomp/libpostexecseccomp.so $(DESTDIR)/$(libdir)/firejail/.
88 install -c -m 0755 src/ftee/ftee $(DESTDIR)/$(libdir)/firejail/. 89 install -c -m 0755 src/ftee/ftee $(DESTDIR)/$(libdir)/firejail/.
89 install -c -m 0755 src/fshaper/fshaper.sh $(DESTDIR)/$(libdir)/firejail/. 90 install -c -m 0755 src/fshaper/fshaper.sh $(DESTDIR)/$(libdir)/firejail/.
90ifeq ($(HAVE_GIT_INSTALL),-DHAVE_GIT_INSTALL) 91ifeq ($(HAVE_GIT_INSTALL),-DHAVE_GIT_INSTALL)
@@ -159,11 +160,13 @@ install-strip: all
159 strip src/firecfg/firecfg 160 strip src/firecfg/firecfg
160 strip src/libtrace/libtrace.so 161 strip src/libtrace/libtrace.so
161 strip src/libtracelog/libtracelog.so 162 strip src/libtracelog/libtracelog.so
163 strip src/libpostexecseccomp/libpostexecseccomp.so
162 strip src/ftee/ftee 164 strip src/ftee/ftee
163 strip src/faudit/faudit 165 strip src/faudit/faudit
164 strip src/fnet/fnet 166 strip src/fnet/fnet
165 strip src/fseccomp/fseccomp 167 strip src/fseccomp/fseccomp
166 strip src/fcopy/fcopy 168 strip src/fcopy/fcopy
169 strip src/fldd/fldd
167 $(MAKE) realinstall 170 $(MAKE) realinstall
168 171
169uninstall: 172uninstall:
diff --git a/configure b/configure
index 3dda0918e..2d2059779 100755
--- a/configure
+++ b/configure
@@ -3823,7 +3823,7 @@ if test "$prefix" = /usr; then
3823 sysconfdir="/etc" 3823 sysconfdir="/etc"
3824fi 3824fi
3825 3825
3826ac_config_files="$ac_config_files Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile" 3826ac_config_files="$ac_config_files Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile"
3827 3827
3828cat >confcache <<\_ACEOF 3828cat >confcache <<\_ACEOF
3829# This file is a shell script that caches the results of configure 3829# This file is a shell script that caches the results of configure
@@ -4545,6 +4545,7 @@ do
4545 "src/faudit/Makefile") CONFIG_FILES="$CONFIG_FILES src/faudit/Makefile" ;; 4545 "src/faudit/Makefile") CONFIG_FILES="$CONFIG_FILES src/faudit/Makefile" ;;
4546 "src/fseccomp/Makefile") CONFIG_FILES="$CONFIG_FILES src/fseccomp/Makefile" ;; 4546 "src/fseccomp/Makefile") CONFIG_FILES="$CONFIG_FILES src/fseccomp/Makefile" ;;
4547 "src/fldd/Makefile") CONFIG_FILES="$CONFIG_FILES src/fldd/Makefile" ;; 4547 "src/fldd/Makefile") CONFIG_FILES="$CONFIG_FILES src/fldd/Makefile" ;;
4548 "src/libpostexecseccomp/Makefile") CONFIG_FILES="$CONFIG_FILES src/libpostexecseccomp/Makefile" ;;
4548 4549
4549 *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; 4550 *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
4550 esac 4551 esac
diff --git a/configure.ac b/configure.ac
index 09fc3f587..8552c48eb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -177,7 +177,7 @@ fi
177 177
178AC_OUTPUT(Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile \ 178AC_OUTPUT(Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile \
179src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile \ 179src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile \
180src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile) 180src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile)
181 181
182echo 182echo
183echo "Configuration options:" 183echo "Configuration options:"
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index b19aded44..5f16d1a5d 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -57,6 +57,7 @@
57#define RUN_SECCOMP_AMD64 "/run/firejail/mnt/seccomp.amd64" // amd64 filter installed on i386 architectures 57#define RUN_SECCOMP_AMD64 "/run/firejail/mnt/seccomp.amd64" // amd64 filter installed on i386 architectures
58#define RUN_SECCOMP_I386 "/run/firejail/mnt/seccomp.i386" // i386 filter installed on amd64 architectures 58#define RUN_SECCOMP_I386 "/run/firejail/mnt/seccomp.i386" // i386 filter installed on amd64 architectures
59#define RUN_SECCOMP_MDWX "/run/firejail/mnt/seccomp.mdwx" // filter for memory-deny-write-execute 59#define RUN_SECCOMP_MDWX "/run/firejail/mnt/seccomp.mdwx" // filter for memory-deny-write-execute
60#define RUN_SECCOMP_POSTEXEC "/run/firejail/mnt/seccomp.postexec" // filter for post-exec library
60#define PATH_SECCOMP_DEFAULT (LIBDIR "/firejail/seccomp") // default filter built during make 61#define PATH_SECCOMP_DEFAULT (LIBDIR "/firejail/seccomp") // default filter built during make
61#define PATH_SECCOMP_DEFAULT_DEBUG (LIBDIR "/firejail/seccomp.debug") // default filter built during make 62#define PATH_SECCOMP_DEFAULT_DEBUG (LIBDIR "/firejail/seccomp.debug") // default filter built during make
62#define PATH_SECCOMP_AMD64 (LIBDIR "/firejail/seccomp.amd64") // amd64 filter built during make 63#define PATH_SECCOMP_AMD64 (LIBDIR "/firejail/seccomp.amd64") // amd64 filter built during make
@@ -305,6 +306,7 @@ extern int arg_overlay_keep; // place overlay diff in a known directory
305extern int arg_overlay_reuse; // allow the reuse of overlays 306extern int arg_overlay_reuse; // allow the reuse of overlays
306 307
307extern int arg_seccomp; // enable default seccomp filter 308extern int arg_seccomp; // enable default seccomp filter
309extern int arg_seccomp_postexec; // need postexec ld.preload library?
308 310
309extern int arg_caps_default_filter; // enable default capabilities filter 311extern int arg_caps_default_filter; // enable default capabilities filter
310extern int arg_caps_drop; // drop list 312extern int arg_caps_drop; // drop list
@@ -553,8 +555,6 @@ void caps_drop_dac_override(void);
553 555
554// syscall.c 556// syscall.c
555const char *syscall_find_nr(int nr); 557const char *syscall_find_nr(int nr);
556// return -1 if error, 0 if no error
557int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg), int arg);
558 558
559// fs_trace.c 559// fs_trace.c
560void fs_trace_preload(void); 560void fs_trace_preload(void);
diff --git a/src/firejail/fs_trace.c b/src/firejail/fs_trace.c
index df76f4fe1..c87d29b5c 100644
--- a/src/firejail/fs_trace.c
+++ b/src/firejail/fs_trace.c
@@ -63,6 +63,11 @@ void fs_trace(void) {
63 if (!arg_quiet) 63 if (!arg_quiet)
64 printf("Blacklist violations are logged to syslog\n"); 64 printf("Blacklist violations are logged to syslog\n");
65 } 65 }
66 if (arg_seccomp_postexec) {
67 fprintf(fp, "%s/libpostexecseccomp.so\n", prefix);
68 if (!arg_quiet)
69 printf("Post-exec seccomp protector enabled\n");
70 }
66 71
67 SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); 72 SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH);
68 fclose(fp); 73 fclose(fp);
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 407902676..9726c0b8a 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -56,6 +56,7 @@ int arg_overlay_keep = 0; // place overlay diff in a known directory
56int arg_overlay_reuse = 0; // allow the reuse of overlays 56int arg_overlay_reuse = 0; // allow the reuse of overlays
57 57
58int arg_seccomp = 0; // enable default seccomp filter 58int arg_seccomp = 0; // enable default seccomp filter
59int arg_seccomp_postexec = 0; // need postexec ld.preload library?
59 60
60int arg_caps_default_filter = 0; // enable default capabilities filter 61int arg_caps_default_filter = 0; // enable default capabilities filter
61int arg_caps_drop = 0; // drop list 62int arg_caps_drop = 0; // drop list
diff --git a/src/firejail/preproc.c b/src/firejail/preproc.c
index 9c474415d..583cc4610 100644
--- a/src/firejail/preproc.c
+++ b/src/firejail/preproc.c
@@ -85,9 +85,12 @@ void preproc_mount_mnt_dir(void) {
85 85
86 if (arg_memory_deny_write_execute) 86 if (arg_memory_deny_write_execute)
87 copy_file(PATH_SECCOMP_MDWX, RUN_SECCOMP_MDWX, getuid(), getgid(), 0644); // root needed 87 copy_file(PATH_SECCOMP_MDWX, RUN_SECCOMP_MDWX, getuid(), getgid(), 0644); // root needed
88 // as root, create an empty RUN_SECCOMP_PROTOCOL file 88 // as root, create empty RUN_SECCOMP_PROTOCOL and RUN_SECCOMP_POSTEXEC files
89 create_empty_file_as_root(RUN_SECCOMP_PROTOCOL, 0644); 89 create_empty_file_as_root(RUN_SECCOMP_PROTOCOL, 0644);
90 if (set_perms(RUN_SECCOMP_PROTOCOL, getuid(), getgid(), 0644)) 90 if (set_perms(RUN_SECCOMP_PROTOCOL, getuid(), getgid(), 0644))
91 errExit("set_perms"); 91 errExit("set_perms");
92 create_empty_file_as_root(RUN_SECCOMP_POSTEXEC, 0644);
93 if (set_perms(RUN_SECCOMP_POSTEXEC, getuid(), getgid(), 0644))
94 errExit("set_perms");
92 } 95 }
93} 96}
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 472f09355..568549cbf 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -664,10 +664,15 @@ int sandbox(void* sandbox_arg) {
664 if (rv) 664 if (rv)
665 exit(rv); 665 exit(rv);
666 } 666 }
667 if (arg_seccomp && (cfg.seccomp_list || cfg.seccomp_list_drop || cfg.seccomp_list_keep))
668 arg_seccomp_postexec = 1;
667#endif 669#endif
668 670
671 // need ld.so.preload if tracing or seccomp with any non-default lists
672 bool need_preload = arg_trace || arg_tracelog || arg_seccomp_postexec;
673
669 // trace pre-install 674 // trace pre-install
670 if (arg_trace || arg_tracelog) 675 if (need_preload)
671 fs_trace_preload(); 676 fs_trace_preload();
672 677
673 // store hosts file 678 // store hosts file
@@ -704,7 +709,7 @@ int sandbox(void* sandbox_arg) {
704 //**************************** 709 //****************************
705 // trace pre-install, this time inside chroot 710 // trace pre-install, this time inside chroot
706 //**************************** 711 //****************************
707 if (arg_trace || arg_tracelog) 712 if (need_preload)
708 fs_trace_preload(); 713 fs_trace_preload();
709 } 714 }
710 else 715 else
@@ -767,7 +772,7 @@ int sandbox(void* sandbox_arg) {
767 else { 772 else {
768 fs_private_dir_list("/etc", RUN_ETC_DIR, cfg.etc_private_keep); 773 fs_private_dir_list("/etc", RUN_ETC_DIR, cfg.etc_private_keep);
769 // create /etc/ld.so.preload file again 774 // create /etc/ld.so.preload file again
770 if (arg_trace || arg_tracelog) 775 if (need_preload)
771 fs_trace_preload(); 776 fs_trace_preload();
772 } 777 }
773 } 778 }
@@ -903,7 +908,7 @@ int sandbox(void* sandbox_arg) {
903 //**************************** 908 //****************************
904 // install trace 909 // install trace
905 //**************************** 910 //****************************
906 if (arg_trace || arg_tracelog) 911 if (need_preload)
907 fs_trace(); 912 fs_trace();
908 913
909 //**************************** 914 //****************************
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c
index 7cbd79d6b..516c97fa0 100644
--- a/src/firejail/seccomp.c
+++ b/src/firejail/seccomp.c
@@ -145,11 +145,11 @@ int seccomp_filter_drop(int enforce_seccomp) {
145 // build the seccomp filter as a regular user 145 // build the seccomp filter as a regular user
146 int rv; 146 int rv;
147 if (arg_allow_debuggers) 147 if (arg_allow_debuggers)
148 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 6, 148 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 7,
149 PATH_FSECCOMP, "default", "drop", RUN_SECCOMP_CFG, cfg.seccomp_list, "allow-debuggers"); 149 PATH_FSECCOMP, "default", "drop", RUN_SECCOMP_CFG, RUN_SECCOMP_POSTEXEC, cfg.seccomp_list, "allow-debuggers");
150 else 150 else
151 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 5, 151 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 6,
152 PATH_FSECCOMP, "default", "drop", RUN_SECCOMP_CFG, cfg.seccomp_list); 152 PATH_FSECCOMP, "default", "drop", RUN_SECCOMP_CFG, RUN_SECCOMP_POSTEXEC, cfg.seccomp_list);
153 if (rv) 153 if (rv)
154 exit(rv); 154 exit(rv);
155 } 155 }
@@ -163,11 +163,11 @@ int seccomp_filter_drop(int enforce_seccomp) {
163 // build the seccomp filter as a regular user 163 // build the seccomp filter as a regular user
164 int rv; 164 int rv;
165 if (arg_allow_debuggers) 165 if (arg_allow_debuggers)
166 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 5, 166 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 6,
167 PATH_FSECCOMP, "drop", RUN_SECCOMP_CFG, cfg.seccomp_list_drop, "allow-debuggers"); 167 PATH_FSECCOMP, "drop", RUN_SECCOMP_CFG, RUN_SECCOMP_POSTEXEC, cfg.seccomp_list_drop, "allow-debuggers");
168 else 168 else
169 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4, 169 rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 5,
170 PATH_FSECCOMP, "drop", RUN_SECCOMP_CFG, cfg.seccomp_list_drop); 170 PATH_FSECCOMP, "drop", RUN_SECCOMP_CFG, RUN_SECCOMP_POSTEXEC, cfg.seccomp_list_drop);
171 171
172 if (rv) 172 if (rv)
173 exit(rv); 173 exit(rv);
@@ -183,9 +183,14 @@ int seccomp_filter_drop(int enforce_seccomp) {
183 exit(1); 183 exit(1);
184 } 184 }
185 185
186 if (arg_debug && access(PATH_FSECCOMP, X_OK) == 0) 186 if (arg_debug && access(PATH_FSECCOMP, X_OK) == 0) {
187 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3, 187 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3,
188 PATH_FSECCOMP, "print", RUN_SECCOMP_CFG); 188 PATH_FSECCOMP, "print", RUN_SECCOMP_CFG);
189 struct stat st;
190 if (stat(RUN_SECCOMP_POSTEXEC, &st) != -1 && st.st_size != 0)
191 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3,
192 PATH_FSECCOMP, "print", RUN_SECCOMP_POSTEXEC);
193 }
189 194
190 return 0; 195 return 0;
191} 196}
@@ -196,14 +201,19 @@ int seccomp_filter_keep(void) {
196 printf("Build drop seccomp filter\n"); 201 printf("Build drop seccomp filter\n");
197 202
198 // build the seccomp filter as a regular user 203 // build the seccomp filter as a regular user
199 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4, 204 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 5,
200 PATH_FSECCOMP, "keep", RUN_SECCOMP_CFG, cfg.seccomp_list_keep); 205 PATH_FSECCOMP, "keep", RUN_SECCOMP_CFG, RUN_SECCOMP_POSTEXEC, cfg.seccomp_list_keep);
201 if (arg_debug) 206 if (arg_debug)
202 printf("seccomp filter configured\n"); 207 printf("seccomp filter configured\n");
203 208
204 209
205 if (arg_debug && access(PATH_FSECCOMP, X_OK) == 0) 210 if (arg_debug && access(PATH_FSECCOMP, X_OK) == 0) {
206 sbox_run(SBOX_ROOT | SBOX_SECCOMP, 3, PATH_FSECCOMP, "print", RUN_SECCOMP_CFG); 211 sbox_run(SBOX_ROOT | SBOX_SECCOMP, 3, PATH_FSECCOMP, "print", RUN_SECCOMP_CFG);
212 struct stat st;
213 if (stat(RUN_SECCOMP_POSTEXEC, &st) != -1 && st.st_size != 0)
214 sbox_run(SBOX_ROOT | SBOX_SECCOMP, 3, PATH_FSECCOMP, "print", RUN_SECCOMP_POSTEXEC);
215 }
216
207 return seccomp_load(RUN_SECCOMP_CFG); 217 return seccomp_load(RUN_SECCOMP_CFG);
208} 218}
209 219
diff --git a/src/fseccomp/fseccomp.h b/src/fseccomp/fseccomp.h
index 0db670380..144b612ae 100644
--- a/src/fseccomp/fseccomp.h
+++ b/src/fseccomp/fseccomp.h
@@ -30,8 +30,9 @@ extern int arg_quiet;
30 30
31// syscall.c 31// syscall.c
32void syscall_print(void); 32void syscall_print(void);
33int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int arg), int fd, int arg); 33int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int arg, void *ptrarg), int fd, int arg, void *ptrarg);
34const char *syscall_find_nr(int nr); 34const char *syscall_find_nr(int nr);
35void syscalls_in_list(const char *list, const char *slist, int fd, char **prelist, char **postlist);
35 36
36// errno.c 37// errno.c
37void errno_print(void); 38void errno_print(void);
@@ -49,9 +50,9 @@ void seccomp_secondary_32(const char *fname);
49// seccomp_file.c 50// seccomp_file.c
50void write_to_file(int fd, const void *data, int size); 51void write_to_file(int fd, const void *data, int size);
51void filter_init(int fd); 52void filter_init(int fd);
52void filter_add_whitelist(int fd, int syscall, int arg); 53void filter_add_whitelist(int fd, int syscall, int arg, void *ptrarg);
53void filter_add_blacklist(int fd, int syscall, int arg); 54void filter_add_blacklist(int fd, int syscall, int arg, void *ptrarg);
54void filter_add_errno(int fd, int syscall, int arg); 55void filter_add_errno(int fd, int syscall, int arg, void *ptrarg);
55void filter_end_blacklist(int fd); 56void filter_end_blacklist(int fd);
56void filter_end_whitelist(int fd); 57void filter_end_whitelist(int fd);
57 58
@@ -59,11 +60,11 @@ void filter_end_whitelist(int fd);
59// default list 60// default list
60void seccomp_default(const char *fname, int allow_debuggers); 61void seccomp_default(const char *fname, int allow_debuggers);
61// drop list 62// drop list
62void seccomp_drop(const char *fname, char *list, int allow_debuggers); 63void seccomp_drop(const char *fname1, const char *fname2, char *list, int allow_debuggers);
63// default+drop list 64// default+drop list
64void seccomp_default_drop(const char *fname, char *list, int allow_debuggers); 65void seccomp_default_drop(const char *fname1, const char *fname2, char *list, int allow_debuggers);
65// whitelisted filter 66// whitelisted filter
66void seccomp_keep(const char *fname, char *list); 67void seccomp_keep(const char *fname1, const char *fname2, char *list);
67// block writable and executable memory 68// block writable and executable memory
68void memory_deny_write_execute(const char *fname); 69void memory_deny_write_execute(const char *fname);
69 70
diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c
index 3d95d5bb2..3bf7de0fa 100644
--- a/src/fseccomp/main.c
+++ b/src/fseccomp/main.c
@@ -30,11 +30,11 @@ static void usage(void) {
30 printf("\tfseccomp secondary 32 file\n"); 30 printf("\tfseccomp secondary 32 file\n");
31 printf("\tfseccomp default file\n"); 31 printf("\tfseccomp default file\n");
32 printf("\tfseccomp default file allow-debuggers\n"); 32 printf("\tfseccomp default file allow-debuggers\n");
33 printf("\tfseccomp drop file list\n"); 33 printf("\tfseccomp drop file1 file2 list\n");
34 printf("\tfseccomp drop file list allow-debuggers\n"); 34 printf("\tfseccomp drop file1 file2 list allow-debuggers\n");
35 printf("\tfseccomp default drop file list\n"); 35 printf("\tfseccomp default drop file1 file2 list\n");
36 printf("\tfseccomp default drop file list allow-debuggers\n"); 36 printf("\tfseccomp default drop file1 file2 list allow-debuggers\n");
37 printf("\tfseccomp keep file list\n"); 37 printf("\tfseccomp keep file1 file2 list\n");
38 printf("\tfseccomp memory-deny-write-execute file\n"); 38 printf("\tfseccomp memory-deny-write-execute file\n");
39 printf("\tfseccomp print file\n"); 39 printf("\tfseccomp print file\n");
40} 40}
@@ -78,16 +78,16 @@ printf("\n");
78 seccomp_default(argv[2], 0); 78 seccomp_default(argv[2], 0);
79 else if (argc == 4 && strcmp(argv[1], "default") == 0 && strcmp(argv[3], "allow-debuggers") == 0) 79 else if (argc == 4 && strcmp(argv[1], "default") == 0 && strcmp(argv[3], "allow-debuggers") == 0)
80 seccomp_default(argv[2], 1); 80 seccomp_default(argv[2], 1);
81 else if (argc == 4 && strcmp(argv[1], "drop") == 0) 81 else if (argc == 5 && strcmp(argv[1], "drop") == 0)
82 seccomp_drop(argv[2], argv[3], 0); 82 seccomp_drop(argv[2], argv[3], argv[4], 0);
83 else if (argc == 5 && strcmp(argv[1], "drop") == 0 && strcmp(argv[4], "allow-debuggers") == 0) 83 else if (argc == 6 && strcmp(argv[1], "drop") == 0 && strcmp(argv[5], "allow-debuggers") == 0)
84 seccomp_drop(argv[2], argv[3], 1); 84 seccomp_drop(argv[2], argv[3], argv[4], 1);
85 else if (argc == 5 && strcmp(argv[1], "default") == 0 && strcmp(argv[2], "drop") == 0) 85 else if (argc == 6 && strcmp(argv[1], "default") == 0 && strcmp(argv[2], "drop") == 0)
86 seccomp_default_drop(argv[3], argv[4], 0); 86 seccomp_default_drop(argv[3], argv[4], argv[5], 0);
87 else if (argc == 6 && strcmp(argv[1], "default") == 0 && strcmp(argv[2], "drop") == 0 && strcmp(argv[5], "allow-debuggers") == 0) 87 else if (argc == 7 && strcmp(argv[1], "default") == 0 && strcmp(argv[2], "drop") == 0 && strcmp(argv[6], "allow-debuggers") == 0)
88 seccomp_default_drop(argv[3], argv[4], 1); 88 seccomp_default_drop(argv[3], argv[4], argv[5], 1);
89 else if (argc == 4 && strcmp(argv[1], "keep") == 0) 89 else if (argc == 5 && strcmp(argv[1], "keep") == 0)
90 seccomp_keep(argv[2], argv[3]); 90 seccomp_keep(argv[2], argv[3], argv[4]);
91 else if (argc == 3 && strcmp(argv[1], "memory-deny-write-execute") == 0) 91 else if (argc == 3 && strcmp(argv[1], "memory-deny-write-execute") == 0)
92 memory_deny_write_execute(argv[2]); 92 memory_deny_write_execute(argv[2]);
93 else if (argc == 3 && strcmp(argv[1], "print") == 0) 93 else if (argc == 3 && strcmp(argv[1], "print") == 0)
diff --git a/src/fseccomp/seccomp.c b/src/fseccomp/seccomp.c
index a3db46aad..577f3fdc9 100644
--- a/src/fseccomp/seccomp.c
+++ b/src/fseccomp/seccomp.c
@@ -27,9 +27,9 @@
27static void add_default_list(int fd, int allow_debuggers) { 27static void add_default_list(int fd, int allow_debuggers) {
28 int r; 28 int r;
29 if (!allow_debuggers) 29 if (!allow_debuggers)
30 r = syscall_check_list("@default-nodebuggers", filter_add_blacklist, fd, 0); 30 r = syscall_check_list("@default-nodebuggers", filter_add_blacklist, fd, 0, NULL);
31 else 31 else
32 r = syscall_check_list("@default", filter_add_blacklist, fd, 0); 32 r = syscall_check_list("@default", filter_add_blacklist, fd, 0, NULL);
33 33
34 assert(r == 0); 34 assert(r == 0);
35//#ifdef SYS_mknod - emoved in 0.9.29 - it breaks Zotero extension 35//#ifdef SYS_mknod - emoved in 0.9.29 - it breaks Zotero extension
@@ -56,7 +56,7 @@ void seccomp_default(const char *fname, int allow_debuggers) {
56 exit(1); 56 exit(1);
57 } 57 }
58 58
59 // build filter 59 // build filter (no post-exec filter needed because default list is fine for us)
60 filter_init(fd); 60 filter_init(fd);
61 add_default_list(fd, allow_debuggers); 61 add_default_list(fd, allow_debuggers);
62 filter_end_blacklist(fd); 62 filter_end_blacklist(fd);
@@ -66,44 +66,94 @@ void seccomp_default(const char *fname, int allow_debuggers) {
66} 66}
67 67
68// drop list 68// drop list
69void seccomp_drop(const char *fname, char *list, int allow_debuggers) { 69void seccomp_drop(const char *fname1, const char *fname2, char *list, int allow_debuggers) {
70 assert(fname); 70 assert(fname1);
71 assert(fname2);
71 (void) allow_debuggers; // todo: to implemnet it 72 (void) allow_debuggers; // todo: to implemnet it
72 73
73 // open file 74 // open file for pre-exec filter
74 int fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 75 int fd = open(fname1, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
75 if (fd < 0) { 76 if (fd < 0) {
76 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname); 77 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname1);
77 exit(1); 78 exit(1);
78 } 79 }
79 80
80 // build filter 81 // build pre-exec filter: don't blacklist any syscalls in @default-keep
82 filter_init(fd);
83 char *prelist, *postlist;
84 syscalls_in_list(list, "@default-keep", fd, &prelist, &postlist);
85 if (prelist)
86 if (syscall_check_list(prelist, filter_add_blacklist, fd, 0, NULL)) {
87 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n");
88 exit(1);
89 }
90 filter_end_whitelist(fd);
91 // close file
92 close(fd);
93
94 if (!postlist)
95 return;
96
97 // open file for post-exec filter
98 fd = open(fname2, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
99 if (fd < 0) {
100 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname2);
101 exit(1);
102 }
103
104 // build post-exec filter: blacklist remaining syscalls
81 filter_init(fd); 105 filter_init(fd);
82 if (syscall_check_list(list, filter_add_blacklist, fd, 0)) { 106 if (syscall_check_list(postlist, filter_add_blacklist, fd, 0, NULL)) {
83 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n"); 107 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n");
84 exit(1); 108 exit(1);
85 } 109 }
86 filter_end_blacklist(fd); 110 filter_end_whitelist(fd);
87 111
88 // close file 112 // close file
89 close(fd); 113 close(fd);
90} 114}
91 115
92// default+drop 116// default+drop
93void seccomp_default_drop(const char *fname, char *list, int allow_debuggers) { 117void seccomp_default_drop(const char *fname1, const char *fname2, char *list, int allow_debuggers) {
94 assert(fname); 118 assert(fname1);
119 assert(fname2);
95 120
96 // open file 121 // open file
97 int fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 122 int fd = open(fname1, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
98 if (fd < 0) { 123 if (fd < 0) {
99 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname); 124 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname1);
100 exit(1); 125 exit(1);
101 } 126 }
102 127
103 // build filter 128 // build pre-exec filter: blacklist @default, don't blacklist
129 // any listed syscalls in @default-keep
104 filter_init(fd); 130 filter_init(fd);
105 add_default_list(fd, allow_debuggers); 131 add_default_list(fd, allow_debuggers);
106 if (syscall_check_list(list, filter_add_blacklist, fd, 0)) { 132 char *prelist, *postlist;
133 syscalls_in_list(list, "@default-keep", fd, &prelist, &postlist);
134 if (prelist)
135 if (syscall_check_list(prelist, filter_add_blacklist, fd, 0, NULL)) {
136 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n");
137 exit(1);
138 }
139 filter_end_blacklist(fd);
140
141 // close file
142 close(fd);
143
144 if (!postlist)
145 return;
146
147 // open file for post-exec filter
148 fd = open(fname2, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
149 if (fd < 0) {
150 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname2);
151 exit(1);
152 }
153
154 // build post-exec filter: blacklist remaining syscalls
155 filter_init(fd);
156 if (syscall_check_list(postlist, filter_add_blacklist, fd, 0, NULL)) {
107 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n"); 157 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n");
108 exit(1); 158 exit(1);
109 } 159 }
@@ -113,22 +163,42 @@ void seccomp_default_drop(const char *fname, char *list, int allow_debuggers) {
113 close(fd); 163 close(fd);
114} 164}
115 165
116void seccomp_keep(const char *fname, char *list) { 166void seccomp_keep(const char *fname1, const char *fname2, char *list) {
117 // open file 167 // open file for pre-exec filter
118 int fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 168 int fd = open(fname1, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
119 if (fd < 0) { 169 if (fd < 0) {
120 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname); 170 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname1);
121 exit(1); 171 exit(1);
122 } 172 }
123 173
124 // build filter 174 // build pre-exec filter: whitelist also @default-keep
125 filter_init(fd); 175 filter_init(fd);
126 // these syscalls are used by firejail after the seccomp filter is initialized 176 // these syscalls are used by firejail after the seccomp filter is initialized
127 int r; 177 int r;
128 r = syscall_check_list("@default-keep", filter_add_whitelist, fd, 0); 178 r = syscall_check_list("@default-keep", filter_add_whitelist, fd, 0, NULL);
129 assert(r == 0); 179 assert(r == 0);
130 180
131 if (syscall_check_list(list, filter_add_whitelist, fd, 0)) { 181 if (syscall_check_list(list, filter_add_whitelist, fd, 0, NULL)) {
182 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n");
183 exit(1);
184 }
185
186 filter_end_whitelist(fd);
187
188 // close file
189 close(fd);
190
191 // open file for post-exec filter
192 fd = open(fname2, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
193 if (fd < 0) {
194 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname2);
195 exit(1);
196 }
197
198 // build post-exec filter: whitelist without @default-keep
199 filter_init(fd);
200
201 if (syscall_check_list(list, filter_add_whitelist, fd, 0, NULL)) {
132 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n"); 202 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n");
133 exit(1); 203 exit(1);
134 } 204 }
diff --git a/src/fseccomp/seccomp_file.c b/src/fseccomp/seccomp_file.c
index 16ffd5302..2d5ee115d 100644
--- a/src/fseccomp/seccomp_file.c
+++ b/src/fseccomp/seccomp_file.c
@@ -60,8 +60,9 @@ void filter_init(int fd) {
60 write_to_file(fd, filter, sizeof(filter)); 60 write_to_file(fd, filter, sizeof(filter));
61} 61}
62 62
63void filter_add_whitelist(int fd, int syscall, int arg) { 63void filter_add_whitelist(int fd, int syscall, int arg, void *ptrarg) {
64 (void) arg; 64 (void) arg;
65 (void) ptrarg;
65 66
66 struct sock_filter filter[] = { 67 struct sock_filter filter[] = {
67 WHITELIST(syscall) 68 WHITELIST(syscall)
@@ -69,8 +70,9 @@ void filter_add_whitelist(int fd, int syscall, int arg) {
69 write_to_file(fd, filter, sizeof(filter)); 70 write_to_file(fd, filter, sizeof(filter));
70} 71}
71 72
72void filter_add_blacklist(int fd, int syscall, int arg) { 73void filter_add_blacklist(int fd, int syscall, int arg, void *ptrarg) {
73 (void) arg; 74 (void) arg;
75 (void) ptrarg;
74 76
75 struct sock_filter filter[] = { 77 struct sock_filter filter[] = {
76 BLACKLIST(syscall) 78 BLACKLIST(syscall)
@@ -78,7 +80,8 @@ void filter_add_blacklist(int fd, int syscall, int arg) {
78 write_to_file(fd, filter, sizeof(filter)); 80 write_to_file(fd, filter, sizeof(filter));
79} 81}
80 82
81void filter_add_errno(int fd, int syscall, int arg) { 83void filter_add_errno(int fd, int syscall, int arg, void *ptrarg) {
84 (void) ptrarg;
82 struct sock_filter filter[] = { 85 struct sock_filter filter[] = {
83 BLACKLIST_ERRNO(syscall, arg) 86 BLACKLIST_ERRNO(syscall, arg)
84 }; 87 };
diff --git a/src/fseccomp/syscall.c b/src/fseccomp/syscall.c
index 5893a2ea8..b9e6d995b 100644
--- a/src/fseccomp/syscall.c
+++ b/src/fseccomp/syscall.c
@@ -17,7 +17,9 @@
17 * with this program; if not, write to the Free Software Foundation, Inc., 17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/ 19*/
20#define _GNU_SOURCE
20#include "fseccomp.h" 21#include "fseccomp.h"
22#include <stdio.h>
21#include <sys/syscall.h> 23#include <sys/syscall.h>
22 24
23typedef struct { 25typedef struct {
@@ -30,6 +32,13 @@ typedef struct {
30 const char * const list; 32 const char * const list;
31} SyscallGroupList; 33} SyscallGroupList;
32 34
35typedef struct {
36 const char *slist;
37 char *prelist, *postlist;
38 bool found;
39 int syscall;
40} SyscallCheckList;
41
33static const SyscallEntry syslist[] = { 42static const SyscallEntry syslist[] = {
34// 43//
35// code generated using tools/extract-syscall 44// code generated using tools/extract-syscall
@@ -174,6 +183,7 @@ static const SyscallGroupList sysgroups[] = {
174 }, 183 },
175 { .name = "@default-keep", .list = 184 { .name = "@default-keep", .list =
176 "dup," 185 "dup,"
186 "execve,"
177 "prctl," 187 "prctl,"
178 "setgid," 188 "setgid,"
179 "setgroups," 189 "setgroups,"
@@ -449,7 +459,7 @@ error:
449} 459}
450 460
451// return 1 if error, 0 if OK 461// return 1 if error, 0 if OK
452int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int arg), int fd, int arg) { 462int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int arg, void *ptrarg), int fd, int arg, void *ptrarg) {
453 // don't allow empty lists 463 // don't allow empty lists
454 if (slist == NULL || *slist == '\0') { 464 if (slist == NULL || *slist == '\0') {
455 fprintf(stderr, "Error fseccomp: empty syscall lists are not allowed\n"); 465 fprintf(stderr, "Error fseccomp: empty syscall lists are not allowed\n");
@@ -477,7 +487,7 @@ int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall,
477 fprintf(stderr, "Error fseccomp: unknown syscall group %s\n", ptr); 487 fprintf(stderr, "Error fseccomp: unknown syscall group %s\n", ptr);
478 exit(1); 488 exit(1);
479 } 489 }
480 syscall_check_list(new_list, callback, fd, arg); 490 syscall_check_list(new_list, callback, fd, arg, ptrarg);
481 } 491 }
482 else { 492 else {
483 syscall_process_name(ptr, &syscall_nr, &error_nr); 493 syscall_process_name(ptr, &syscall_nr, &error_nr);
@@ -487,9 +497,9 @@ int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall,
487 } 497 }
488 else if (callback != NULL) { 498 else if (callback != NULL) {
489 if (error_nr != -1) 499 if (error_nr != -1)
490 filter_add_errno(fd, syscall_nr, error_nr); 500 filter_add_errno(fd, syscall_nr, error_nr, ptrarg);
491 else 501 else
492 callback(fd, syscall_nr, arg); 502 callback(fd, syscall_nr, arg, ptrarg);
493 } 503 }
494 } 504 }
495 ptr = strtok_r(NULL, ",", &saveptr); 505 ptr = strtok_r(NULL, ",", &saveptr);
@@ -498,3 +508,49 @@ int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall,
498 free(str); 508 free(str);
499 return 0; 509 return 0;
500} 510}
511
512static void find_syscall(int fd, int syscall, int arg, void *ptrarg) {
513 (void)fd;
514 SyscallCheckList *ptr = ptrarg;
515 if (syscall == ptr->syscall)
516 ptr->found = true;
517}
518
519// go through list2 and find matches for problem syscall
520static void syscall_in_list(int fd, int syscall, int arg, void *ptrarg) {
521 (void)arg;
522 SyscallCheckList *ptr = ptrarg;
523 SyscallCheckList sl;
524 sl.found = false;
525 sl.syscall = syscall;
526 syscall_check_list(ptr->slist, find_syscall, fd, 0, &sl);
527 // if found in the problem list, add to post-exec list
528 if (sl.found)
529 if (ptr->postlist) {
530 if (asprintf(&ptr->postlist, "%s,%s", ptr->postlist, syscall_find_nr(syscall)) == -1)
531 errExit("asprintf");
532 }
533 else
534 ptr->postlist = strdup(syscall_find_nr(syscall));
535 else // no problem, add to pre-exec list
536 if (ptr->prelist) {
537 if (asprintf(&ptr->prelist, "%s,%s", ptr->prelist, syscall_find_nr(syscall)) == -1)
538 errExit("asprintf");
539 }
540 else
541 ptr->prelist = strdup(syscall_find_nr(syscall));
542}
543
544// go through list and find matches for syscalls in list @default-keep
545void syscalls_in_list(const char *list, const char *slist, int fd, char **prelist, char **postlist) {
546 SyscallCheckList sl;
547 // these syscalls are used by firejail after the seccomp filter is initialized
548 sl.slist = slist;
549 sl.prelist = NULL;
550 sl.postlist = NULL;
551 syscall_check_list(list, syscall_in_list, 0, 0, &sl);
552 if (!arg_quiet)
553 printf("list in: %s, check list: %s prelist: %s, postlist: %s\n", list, sl.slist, sl.prelist, sl.postlist);
554 *prelist = sl.prelist;
555 *postlist = sl.postlist;
556}
diff --git a/src/libpostexecseccomp/Makefile.in b/src/libpostexecseccomp/Makefile.in
new file mode 100644
index 000000000..92803342c
--- /dev/null
+++ b/src/libpostexecseccomp/Makefile.in
@@ -0,0 +1,26 @@
1CC=@CC@
2PREFIX=@prefix@
3VERSION=@PACKAGE_VERSION@
4NAME=@PACKAGE_NAME@
5HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@
6
7H_FILE_LIST = $(sort $(wildcard *.[h]))
8C_FILE_LIST = $(sort $(wildcard *.c))
9OBJS = $(C_FILE_LIST:.c=.o)
10BINOBJS = $(foreach file, $(OBJS), $file)
11CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security
12LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now
13
14all: libpostexecseccomp.so
15
16%.o : %.c $(H_FILE_LIST)
17 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
18
19libpostexecseccomp.so: $(OBJS)
20 $(CC) $(LDFLAGS) -shared -fPIC -z relro -o $@ $(OBJS) -ldl
21
22
23clean:; rm -f $(OBJS) libpostexecseccomp.so
24
25distclean: clean
26 rm -fr Makefile
diff --git a/src/libpostexecseccomp/libpostexecseccomp.c b/src/libpostexecseccomp/libpostexecseccomp.c
new file mode 100644
index 000000000..801f968a6
--- /dev/null
+++ b/src/libpostexecseccomp/libpostexecseccomp.c
@@ -0,0 +1,59 @@
1/*
2 * Copyright (C) 2017 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "libpostexecseccomp.h"
21#include <fcntl.h>
22#include <linux/audit.h>
23#include <linux/bpf.h>
24#include <linux/filter.h>
25#include <linux/seccomp.h>
26#include <sys/mman.h>
27#include <sys/prctl.h>
28#include <sys/ptrace.h>
29#include <sys/stat.h>
30#include <sys/types.h>
31#include <unistd.h>
32
33__attribute__((constructor))
34static void load_seccomp(void) {
35 int fd = open(RUN_SECCOMP_POSTEXEC, O_RDONLY);
36 if (fd == -1)
37 return;
38
39 int size = lseek(fd, 0, SEEK_END);
40 unsigned short entries = (unsigned short) size / (unsigned short) sizeof(struct sock_filter);
41 struct sock_filter *filter = MAP_FAILED;
42 if (size != 0)
43 filter = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
44
45 close(fd);
46
47 if (size == 0 || filter == MAP_FAILED)
48 return;
49
50 // install filter
51 struct sock_fprog prog = {
52 .len = entries,
53 .filter = filter,
54 };
55
56 prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
57 prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
58 munmap(filter, size);
59}
diff --git a/src/libpostexecseccomp/libpostexecseccomp.h b/src/libpostexecseccomp/libpostexecseccomp.h
new file mode 100644
index 000000000..c4aca540a
--- /dev/null
+++ b/src/libpostexecseccomp/libpostexecseccomp.h
@@ -0,0 +1,25 @@
1/*
2 * Copyright (C) 2017 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#ifndef LIBPOSTEXECSECCOMP_H
21#define LIBPOSTEXECSECCOMP_H
22
23#define RUN_SECCOMP_POSTEXEC "/run/firejail/mnt/seccomp.postexec"
24
25#endif
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index 2c8dca09a..be73429bc 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -1578,6 +1578,32 @@ $ rm testfile
1578rm: cannot remove `testfile': Operation not permitted 1578rm: cannot remove `testfile': Operation not permitted
1579.br 1579.br
1580 1580
1581.br
1582If the blocked system calls would also block Firejail from operating,
1583they are handled by adding a preloaded library which performs seccomp
1584system calls later.
1585.br
1586
1587.br
1588Example:
1589.br
1590
1591.br
1592$ firejail \-\-noprofile \-\-shell=none \-\-seccomp=execve bash
1593.br
1594Parent pid 32751, child pid 32752
1595.br
1596Post-exec seccomp protector enabled
1597.br
1598list in: execve, check list: @default-keep prelist: (null), postlist: execve
1599.br
1600Child process initialized in 46.44 ms
1601.br
1602$ ls
1603.br
1604Bad system call
1605.br
1606
1581.TP 1607.TP
1582\fB\-\-seccomp.drop=syscall,syscall,syscall 1608\fB\-\-seccomp.drop=syscall,syscall,syscall
1583Enable seccomp filter, and blacklist the syscalls specified by the command. 1609Enable seccomp filter, and blacklist the syscalls specified by the command.