aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile.in4
-rwxr-xr-xconfigure3
-rw-r--r--configure.ac2
-rw-r--r--src/firejail/firejail.h1
-rw-r--r--src/firejail/seccomp.c20
-rw-r--r--src/fsec-print/Makefile.in45
-rw-r--r--src/fsec-print/fsec_print.h32
-rw-r--r--src/fsec-print/main.c81
-rw-r--r--src/fsec-print/print.c334
-rw-r--r--src/fsec-print/syscall_list.c47
-rw-r--r--src/fseccomp/main.c3
-rw-r--r--src/fseccomp/seccomp_print.c183
-rw-r--r--src/include/seccomp.h14
14 files changed, 571 insertions, 199 deletions
diff --git a/.gitignore b/.gitignore
index 52a2718ee..d87f8663d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,7 @@ src/tags
23src/faudit/faudit 23src/faudit/faudit
24src/fnet/fnet 24src/fnet/fnet
25src/fnetfilter/fnetfilter 25src/fnetfilter/fnetfilter
26src/fsec-print/fsec-print
26src/fseccomp/fseccomp 27src/fseccomp/fseccomp
27src/fcopy/fcopy 28src/fcopy/fcopy
28src/fldd/fldd 29src/fldd/fldd
diff --git a/Makefile.in b/Makefile.in
index d11d537bc..81907022b 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/fnetfilter src/libtrace src/libtracelog src/ftee src/faudit src/fnet src/fseccomp src/fbuilder src/fcopy src/fldd src/libpostexecseccomp 3APPS = src/firejail src/firemon src/fsec-print src/firecfg src/fnetfilter src/libtrace src/libtracelog src/ftee src/faudit src/fnet src/fseccomp src/fbuilder 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.debug seccomp.32 seccomp.64 seccomp.block_secondary seccomp.mdwx 5SECCOMP_FILTERS = seccomp seccomp.debug seccomp.32 seccomp.64 seccomp.block_secondary seccomp.mdwx
6 6
@@ -102,6 +102,7 @@ endif
102 install -c -m 0755 src/fldd/fldd $(DESTDIR)/$(libdir)/firejail/. 102 install -c -m 0755 src/fldd/fldd $(DESTDIR)/$(libdir)/firejail/.
103 install -c -m 0755 src/fbuilder/fbuilder $(DESTDIR)/$(libdir)/firejail/. 103 install -c -m 0755 src/fbuilder/fbuilder $(DESTDIR)/$(libdir)/firejail/.
104ifeq ($(HAVE_SECCOMP),-DHAVE_SECCOMP) 104ifeq ($(HAVE_SECCOMP),-DHAVE_SECCOMP)
105 install -c -m 0755 src/fsec-print/fsec-print $(DESTDIR)/$(libdir)/firejail/.
105 install -c -m 0755 src/fseccomp/fseccomp $(DESTDIR)/$(libdir)/firejail/. 106 install -c -m 0755 src/fseccomp/fseccomp $(DESTDIR)/$(libdir)/firejail/.
106 install -c -m 0644 seccomp $(DESTDIR)/$(libdir)/firejail/. 107 install -c -m 0644 seccomp $(DESTDIR)/$(libdir)/firejail/.
107 install -c -m 0644 seccomp.debug $(DESTDIR)/$(libdir)/firejail/. 108 install -c -m 0644 seccomp.debug $(DESTDIR)/$(libdir)/firejail/.
@@ -170,6 +171,7 @@ install-strip: all
170 strip src/fnet/fnet 171 strip src/fnet/fnet
171 strip src/fnetfilter/fnetfilter 172 strip src/fnetfilter/fnetfilter
172 strip src/fseccomp/fseccomp 173 strip src/fseccomp/fseccomp
174 strip src/fsec-print/fsec-print
173 strip src/fcopy/fcopy 175 strip src/fcopy/fcopy
174 strip src/fldd/fldd 176 strip src/fldd/fldd
175 strip src/fbuilder/fbuilder 177 strip src/fbuilder/fbuilder
diff --git a/configure b/configure
index d38487aaa..f556f44b5 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/fnetfilter/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile" 3826ac_config_files="$ac_config_files Makefile 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/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
@@ -4543,6 +4543,7 @@ do
4543 "src/libtracelog/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtracelog/Makefile" ;; 4543 "src/libtracelog/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtracelog/Makefile" ;;
4544 "src/firecfg/Makefile") CONFIG_FILES="$CONFIG_FILES src/firecfg/Makefile" ;; 4544 "src/firecfg/Makefile") CONFIG_FILES="$CONFIG_FILES src/firecfg/Makefile" ;;
4545 "src/fbuilder/Makefile") CONFIG_FILES="$CONFIG_FILES src/fbuilder/Makefile" ;; 4545 "src/fbuilder/Makefile") CONFIG_FILES="$CONFIG_FILES src/fbuilder/Makefile" ;;
4546 "src/fsec-print/Makefile") CONFIG_FILES="$CONFIG_FILES src/fsec-print/Makefile" ;;
4546 "src/ftee/Makefile") CONFIG_FILES="$CONFIG_FILES src/ftee/Makefile" ;; 4547 "src/ftee/Makefile") CONFIG_FILES="$CONFIG_FILES src/ftee/Makefile" ;;
4547 "src/faudit/Makefile") CONFIG_FILES="$CONFIG_FILES src/faudit/Makefile" ;; 4548 "src/faudit/Makefile") CONFIG_FILES="$CONFIG_FILES src/faudit/Makefile" ;;
4548 "src/fseccomp/Makefile") CONFIG_FILES="$CONFIG_FILES src/fseccomp/Makefile" ;; 4549 "src/fseccomp/Makefile") CONFIG_FILES="$CONFIG_FILES src/fseccomp/Makefile" ;;
diff --git a/configure.ac b/configure.ac
index cc70a4ded..4633ea35c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -176,7 +176,7 @@ if test "$prefix" = /usr; then
176fi 176fi
177 177
178AC_OUTPUT(Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/fnetfilter/Makefile \ 178AC_OUTPUT(Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/fnetfilter/Makefile \
179src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile \ 179src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/fsec-print/Makefile \
180src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile) 180src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile)
181 181
182echo 182echo
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 3df6af7b6..a009c4e65 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -771,6 +771,7 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc,
771#define PATH_FIREMON (PREFIX "/bin/firemon") 771#define PATH_FIREMON (PREFIX "/bin/firemon")
772#define PATH_FIREJAIL (PREFIX "/bin/firejail") 772#define PATH_FIREJAIL (PREFIX "/bin/firejail")
773#define PATH_FSECCOMP (LIBDIR "/firejail/fseccomp") 773#define PATH_FSECCOMP (LIBDIR "/firejail/fseccomp")
774#define PATH_FSEC_PRINT (LIBDIR "/firejail/fsec-print")
774#define PATH_FCOPY (LIBDIR "/firejail/fcopy") 775#define PATH_FCOPY (LIBDIR "/firejail/fcopy")
775#define SBOX_STDIN_FILE "/run/firejail/mnt/sbox_stdin" 776#define SBOX_STDIN_FILE "/run/firejail/mnt/sbox_stdin"
776#define PATH_FLDD (LIBDIR "/firejail/fldd") 777#define PATH_FLDD (LIBDIR "/firejail/fldd")
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c
index e75863c3a..9c32f2169 100644
--- a/src/firejail/seccomp.c
+++ b/src/firejail/seccomp.c
@@ -126,9 +126,9 @@ int seccomp_load(const char *fname) {
126 errExit("strdup"); 126 errExit("strdup");
127 filter_list_head = fl; 127 filter_list_head = fl;
128 128
129 if (arg_debug && access(PATH_FSECCOMP, X_OK) == 0) { 129 if (arg_debug && access(PATH_FSEC_PRINT, X_OK) == 0) {
130 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3, 130 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2,
131 PATH_FSECCOMP, "print", fname); 131 PATH_FSEC_PRINT, fname);
132 } 132 }
133 133
134 return 0; 134 return 0;
@@ -240,12 +240,12 @@ int seccomp_filter_drop(void) {
240 printf("seccomp filter configured\n"); 240 printf("seccomp filter configured\n");
241 } 241 }
242 242
243 if (arg_debug && access(PATH_FSECCOMP, X_OK) == 0) { 243 if (arg_debug && access(PATH_FSEC_PRINT, X_OK) == 0) {
244 struct stat st; 244 struct stat st;
245 if (stat(RUN_SECCOMP_POSTEXEC, &st) != -1 && st.st_size != 0) { 245 if (stat(RUN_SECCOMP_POSTEXEC, &st) != -1 && st.st_size != 0) {
246 printf("configuring postexec seccomp filter in %s\n", RUN_SECCOMP_POSTEXEC); 246 printf("configuring postexec seccomp filter in %s\n", RUN_SECCOMP_POSTEXEC);
247 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3, 247 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2,
248 PATH_FSECCOMP, "print", RUN_SECCOMP_POSTEXEC); 248 PATH_FSEC_PRINT, RUN_SECCOMP_POSTEXEC);
249 } 249 }
250 } 250 }
251 251
@@ -280,12 +280,12 @@ int seccomp_filter_keep(void) {
280 printf("seccomp filter configured\n"); 280 printf("seccomp filter configured\n");
281 } 281 }
282 282
283 if (arg_debug && access(PATH_FSECCOMP, X_OK) == 0) { 283 if (arg_debug && access(PATH_FSEC_PRINT, X_OK) == 0) {
284 struct stat st; 284 struct stat st;
285 if (stat(RUN_SECCOMP_POSTEXEC, &st) != -1 && st.st_size != 0) { 285 if (stat(RUN_SECCOMP_POSTEXEC, &st) != -1 && st.st_size != 0) {
286 printf("configuring postexec seccomp filter in %s\n", RUN_SECCOMP_POSTEXEC); 286 printf("configuring postexec seccomp filter in %s\n", RUN_SECCOMP_POSTEXEC);
287 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3, 287 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2,
288 PATH_FSECCOMP, "print", RUN_SECCOMP_POSTEXEC); 288 PATH_FSEC_PRINT, RUN_SECCOMP_POSTEXEC);
289 } 289 }
290 } 290 }
291 291
@@ -332,7 +332,7 @@ void seccomp_print_filter(pid_t pid) {
332 } 332 }
333 333
334 // read and print the filter - run this as root, the user doesn't have access 334 // read and print the filter - run this as root, the user doesn't have access
335 sbox_run(SBOX_ROOT | SBOX_SECCOMP, 3, PATH_FSECCOMP, "print", fname); 335 sbox_run(SBOX_ROOT | SBOX_SECCOMP, 2, PATH_FSEC_PRINT, fname);
336 free(fname); 336 free(fname);
337 337
338 exit(0); 338 exit(0);
diff --git a/src/fsec-print/Makefile.in b/src/fsec-print/Makefile.in
new file mode 100644
index 000000000..5d23382f7
--- /dev/null
+++ b/src/fsec-print/Makefile.in
@@ -0,0 +1,45 @@
1all: fsec-print
2
3CC=@CC@
4prefix=@prefix@
5exec_prefix=@exec_prefix@
6libdir=@libdir@
7sysconfdir=@sysconfdir@
8
9VERSION=@PACKAGE_VERSION@
10NAME=@PACKAGE_NAME@
11HAVE_SECCOMP_H=@HAVE_SECCOMP_H@
12HAVE_SECCOMP=@HAVE_SECCOMP@
13HAVE_CHROOT=@HAVE_CHROOT@
14HAVE_BIND=@HAVE_BIND@
15HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@
16HAVE_NETWORK=@HAVE_NETWORK@
17HAVE_USERNS=@HAVE_USERNS@
18HAVE_X11=@HAVE_X11@
19HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@
20HAVE_WHITELIST=@HAVE_WHITELIST@
21HAVE_GLOBALCFG=@HAVE_GLOBALCFG@
22HAVE_APPARMOR=@HAVE_APPARMOR@
23HAVE_OVERLAYFS=@HAVE_OVERLAYFS@
24HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@
25EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
26HAVE_GCOV=@HAVE_GCOV@
27EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
28
29H_FILE_LIST = $(sort $(wildcard *.[h]))
30C_FILE_LIST = $(sort $(wildcard *.c))
31OBJS = $(C_FILE_LIST:.c=.o)
32BINOBJS = $(foreach file, $(OBJS), $file)
33CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV) -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
34LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
35
36%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/seccomp.h ../include/syscall.h
37 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
38
39fsec-print: $(OBJS) ../lib/libnetlink.o
40 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
41
42clean:; rm -f *.o fsec-print *.gcov *.gcda *.gcno
43
44distclean: clean
45 rm -fr Makefile
diff --git a/src/fsec-print/fsec_print.h b/src/fsec-print/fsec_print.h
new file mode 100644
index 000000000..d3f4a4df9
--- /dev/null
+++ b/src/fsec-print/fsec_print.h
@@ -0,0 +1,32 @@
1/*
2 * Copyright (C) 2014-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 FSEC_PRINT_H
21#define FSEC_PRINT_H
22#include "../include/common.h"
23#include "../include/seccomp.h"
24#include <sys/mman.h>
25
26// print.c
27void print(struct sock_filter *filter, int entries);
28
29// syscall_list.c
30const char *syscall_find_nr(int nr);
31
32#endif \ No newline at end of file
diff --git a/src/fsec-print/main.c b/src/fsec-print/main.c
new file mode 100644
index 000000000..e8639b822
--- /dev/null
+++ b/src/fsec-print/main.c
@@ -0,0 +1,81 @@
1/*
2 * Copyright (C) 2014-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 "fsec_print.h"
21
22static void usage(void) {
23 printf("Usage:\n");
24 printf("\tfsec-print file - disassemble seccomp filter\n");
25}
26
27int main(int argc, char **argv) {
28#if 0
29{
30//system("cat /proc/self/status");
31int i;
32for (i = 0; i < argc; i++)
33 printf("*%s* ", argv[i]);
34printf("\n");
35}
36#endif
37 if (argc != 2) {
38 usage();
39 return 1;
40 }
41
42 if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) {
43 usage();
44 return 0;
45 }
46
47 char *fname = argv[1];
48
49 // open input file
50 int fd = open(fname, O_RDONLY);
51 if (fd == -1)
52 goto errexit;
53
54 // calculate the number of entries
55 int size = lseek(fd, 0, SEEK_END);
56 if (size == -1) // todo: check maximum size of seccomp filter (4KB?)
57 goto errexit;
58 unsigned short entries = (unsigned short) size / (unsigned short) sizeof(struct sock_filter);
59
60 // read filter
61 struct sock_filter *filter = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
62 if (filter == MAP_FAILED)
63 goto errexit;
64
65
66 // print filter
67 print(filter, entries);
68
69 // free mapped memory
70 if (munmap(filter, size) == -1)
71 perror("Error un-mmapping the file");
72
73 // close file
74 close(fd);
75 return 0;
76errexit:
77 close(fd);
78 fprintf(stderr, "Error: cannot read %s\n", fname);
79 exit(1);
80
81}
diff --git a/src/fsec-print/print.c b/src/fsec-print/print.c
new file mode 100644
index 000000000..964a3a8a9
--- /dev/null
+++ b/src/fsec-print/print.c
@@ -0,0 +1,334 @@
1/*
2 * Copyright (C) 2014-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 *
21 *
22 * Parts of this code was lifted from libseccomp project, license LGPV 2.1.
23 * This is the original copyright notice in libseccomp code:
24 *
25 *
26 *
27 * BPF Disassembler
28 *
29 * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
30 * Author: Paul Moore <paul@paul-moore.com>
31 *
32 * This library is free software; you can redistribute it and/or modify it
33 * under the terms of version 2.1 of the GNU Lesser General Public License as
34 * published by the Free Software Foundation.
35 *
36 * This library is distributed in the hope that it will be useful, but WITHOUT
37 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
38 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
39 * for more details.
40 *
41 * You should have received a copy of the GNU Lesser General Public License
42 * along with this library; if not, see <http://www.gnu.org/licenses>.
43 */
44
45#include "fsec_print.h"
46
47// From /usr/include/linux/filter.h
48//struct sock_filter { /* Filter block */
49// __u16 code; /* Actual filter code */
50// __u8 jt; /* Jump true */
51// __u8 jf; /* Jump false */
52// __u32 k; /* Generic multiuse field */
53//};
54
55
56static const char *bpf_decode_op(const struct sock_filter *bpf) {
57 switch (bpf->code) {
58 case BPF_LD+BPF_W+BPF_IMM:
59 case BPF_LD+BPF_W+BPF_ABS:
60 case BPF_LD+BPF_W+BPF_IND:
61 case BPF_LD+BPF_W+BPF_MEM:
62 case BPF_LD+BPF_W+BPF_LEN:
63 case BPF_LD+BPF_W+BPF_MSH:
64 return "ld";
65 case BPF_LD+BPF_H+BPF_IMM:
66 case BPF_LD+BPF_H+BPF_ABS:
67 case BPF_LD+BPF_H+BPF_IND:
68 case BPF_LD+BPF_H+BPF_MEM:
69 case BPF_LD+BPF_H+BPF_LEN:
70 case BPF_LD+BPF_H+BPF_MSH:
71 return "ldh";
72 case BPF_LD+BPF_B+BPF_IMM:
73 case BPF_LD+BPF_B+BPF_ABS:
74 case BPF_LD+BPF_B+BPF_IND:
75 case BPF_LD+BPF_B+BPF_MEM:
76 case BPF_LD+BPF_B+BPF_LEN:
77 case BPF_LD+BPF_B+BPF_MSH:
78 return "ldb";
79 case BPF_LDX+BPF_W+BPF_IMM:
80 case BPF_LDX+BPF_W+BPF_ABS:
81 case BPF_LDX+BPF_W+BPF_IND:
82 case BPF_LDX+BPF_W+BPF_MEM:
83 case BPF_LDX+BPF_W+BPF_LEN:
84 case BPF_LDX+BPF_W+BPF_MSH:
85 case BPF_LDX+BPF_H+BPF_IMM:
86 case BPF_LDX+BPF_H+BPF_ABS:
87 case BPF_LDX+BPF_H+BPF_IND:
88 case BPF_LDX+BPF_H+BPF_MEM:
89 case BPF_LDX+BPF_H+BPF_LEN:
90 case BPF_LDX+BPF_H+BPF_MSH:
91 case BPF_LDX+BPF_B+BPF_IMM:
92 case BPF_LDX+BPF_B+BPF_ABS:
93 case BPF_LDX+BPF_B+BPF_IND:
94 case BPF_LDX+BPF_B+BPF_MEM:
95 case BPF_LDX+BPF_B+BPF_LEN:
96 case BPF_LDX+BPF_B+BPF_MSH:
97 return "ldx";
98 case BPF_ST:
99 return "st";
100 case BPF_STX:
101 return "stx";
102 case BPF_ALU+BPF_ADD+BPF_K:
103 case BPF_ALU+BPF_ADD+BPF_X:
104 return "add";
105 case BPF_ALU+BPF_SUB+BPF_K:
106 case BPF_ALU+BPF_SUB+BPF_X:
107 return "sub";
108 case BPF_ALU+BPF_MUL+BPF_K:
109 case BPF_ALU+BPF_MUL+BPF_X:
110 return "mul";
111 case BPF_ALU+BPF_DIV+BPF_K:
112 case BPF_ALU+BPF_DIV+BPF_X:
113 return "div";
114 case BPF_ALU+BPF_OR+BPF_K:
115 case BPF_ALU+BPF_OR+BPF_X:
116 return "or";
117 case BPF_ALU+BPF_AND+BPF_K:
118 case BPF_ALU+BPF_AND+BPF_X:
119 return "and";
120 case BPF_ALU+BPF_LSH+BPF_K:
121 case BPF_ALU+BPF_LSH+BPF_X:
122 return "lsh";
123 case BPF_ALU+BPF_RSH+BPF_K:
124 case BPF_ALU+BPF_RSH+BPF_X:
125 return "rsh";
126 case BPF_ALU+BPF_NEG+BPF_K:
127 case BPF_ALU+BPF_NEG+BPF_X:
128 return "neg";
129 case BPF_ALU+BPF_MOD+BPF_K:
130 case BPF_ALU+BPF_MOD+BPF_X:
131 return "mod";
132 case BPF_ALU+BPF_XOR+BPF_K:
133 case BPF_ALU+BPF_XOR+BPF_X:
134 return "xor";
135 case BPF_JMP+BPF_JA+BPF_K:
136 case BPF_JMP+BPF_JA+BPF_X:
137 return "jmp";
138 case BPF_JMP+BPF_JEQ+BPF_K:
139 case BPF_JMP+BPF_JEQ+BPF_X:
140 return "jeq";
141 case BPF_JMP+BPF_JGT+BPF_K:
142 case BPF_JMP+BPF_JGT+BPF_X:
143 return "jgt";
144 case BPF_JMP+BPF_JGE+BPF_K:
145 case BPF_JMP+BPF_JGE+BPF_X:
146 return "jge";
147 case BPF_JMP+BPF_JSET+BPF_K:
148 case BPF_JMP+BPF_JSET+BPF_X:
149 return "jset";
150 case BPF_RET+BPF_K:
151 case BPF_RET+BPF_X:
152 case BPF_RET+BPF_A:
153 return "ret";
154 case BPF_MISC+BPF_TAX:
155 return "tax";
156 case BPF_MISC+BPF_TXA:
157 return "txa";
158 }
159 return "???";
160}
161
162static void bpf_decode_action(uint32_t k) {
163 uint32_t act = k & SECCOMP_RET_ACTION;
164 uint32_t data = k & SECCOMP_RET_DATA;
165
166 switch (act) {
167 case SECCOMP_RET_KILL:
168 printf("KILL");
169 break;
170 case SECCOMP_RET_TRAP:
171 printf("TRAP");
172 break;
173 case SECCOMP_RET_ERRNO:
174 printf("ERRNO(%u)", data);
175 break;
176 case SECCOMP_RET_TRACE:
177 printf("TRACE(%u)", data);
178 break;
179 case SECCOMP_RET_LOG:
180 printf("LOG");
181 break;
182 case SECCOMP_RET_ALLOW:
183 printf("ALLOW");
184 break;
185 default:
186 printf("0x%.8x", k);
187 }
188}
189
190
191// implementing a simple state machine around accumulator
192// in order to translate the syscall number
193int syscall_loaded = 0;
194int native_arch = 0;
195
196static void bpf_decode_args(const struct sock_filter *bpf, unsigned int line) {
197 switch (BPF_CLASS(bpf->code)) {
198 case BPF_LD:
199 case BPF_LDX:
200 switch (BPF_MODE(bpf->code)) {
201 case BPF_ABS:
202 syscall_loaded = 0;
203 if (bpf->k == offsetof(struct seccomp_data, arch))
204 printf("data.architecture");
205 else if (bpf->k == offsetof(struct seccomp_data, nr)) {
206 printf("data.syscall-number");
207 syscall_loaded = 1;
208 }
209 else if (bpf->k == offsetof(struct seccomp_data, nr))
210 printf("data.instruction_pointer");
211 else {
212 int index = bpf->k - offsetof(struct seccomp_data, args);
213 printf("data.args[%x]", index);
214 }
215 break;
216 case BPF_MEM:
217 printf("$temp[%u]", bpf->k);
218 break;
219 case BPF_IMM:
220 printf("%x", bpf->k);
221 break;
222 case BPF_IND:
223 printf("$data[X + %x]", bpf->k);
224 break;
225 case BPF_LEN:
226 printf("len($data)");
227 break;
228 case BPF_MSH:
229 printf("4 * $data[%x] & 0x0f", bpf->k);
230 break;
231 }
232 break;
233 case BPF_ST:
234 case BPF_STX:
235 printf("$temp[%u]", bpf->k);
236 break;
237 case BPF_ALU:
238 if (BPF_SRC(bpf->code) == BPF_K) {
239 switch (BPF_OP(bpf->code)) {
240 case BPF_OR:
241 case BPF_AND:
242 printf("%.8x", bpf->k);
243 break;
244 default:
245 printf("%x", bpf->k);
246 }
247 }
248 else
249 printf("%u", bpf->k);
250 break;
251 case BPF_JMP:
252 if (BPF_OP(bpf->code) == BPF_JA) {
253 printf("%.4u", (line + 1) + bpf->k);
254 }
255 else {
256 const char *name = NULL;
257 if (syscall_loaded && native_arch)
258 name = syscall_find_nr(bpf->k);
259 if (bpf->k == ARCH_32) {
260 printf("ARCH_32 %.4x (false %.4x)",
261 (line + 1) + bpf->jt,
262 (line + 1) + bpf->jf);
263 native_arch = (ARCH_NR == ARCH_32)? 1: 0;
264 }
265 else if (bpf->k == ARCH_64) {
266 printf("ARCH_64 %.4x (false %.4x)",
267 (line + 1) + bpf->jt,
268 (line + 1) + bpf->jf);
269 native_arch = (ARCH_NR == ARCH_64)? 1: 0;
270 }
271 else if (bpf->k == X32_SYSCALL_BIT)
272 printf("X32_ABI true:%.4x (false %.4x)",
273 (line + 1) + bpf->jt,
274 (line + 1) + bpf->jf);
275 else if (name)
276 printf("%s %.4x (false %.4x)",
277 name,
278 (line + 1) + bpf->jt,
279 (line + 1) + bpf->jf);
280 else
281 printf("%x %.4x (false %.4x)",
282 bpf->k,
283 (line + 1) + bpf->jt,
284 (line + 1) + bpf->jf);
285 }
286 break;
287 case BPF_RET:
288 if (BPF_RVAL(bpf->code) == BPF_A) {
289 /* XXX - accumulator? */
290 printf("$acc");
291 }
292 else if (BPF_SRC(bpf->code) == BPF_K) {
293 bpf_decode_action(bpf->k);
294 }
295 else if (BPF_SRC(bpf->code) == BPF_X) {
296 /* XXX - any idea? */
297 printf("???");
298 }
299 break;
300 case BPF_MISC:
301 break;
302 default:
303 printf("???");
304 }
305}
306
307void print(struct sock_filter *filter, int entries) {
308 unsigned int line = 0;
309 int i;
310
311 /* header */
312 printf(" line OP JT JF K\n");
313 printf("=================================\n");
314 struct sock_filter *bpf = filter;
315 for (i = 0; i < entries; i++, bpf++) {
316
317 /* convert the bpf statement */
318// bpf.code = ttoh16(arch, bpf.code);
319// bpf.k = ttoh32(arch, bpf.k);
320
321 /* display a hex dump */
322 printf(" %.4x: %.2x %.2x %.2x %.8x",
323 i, bpf->code, bpf->jt, bpf->jf, bpf->k);
324
325 /* display the assembler statements */
326 printf(" ");
327 printf("%-3s", bpf_decode_op(bpf));
328 printf(" ");
329 bpf_decode_args(bpf, i);
330
331 printf("\n");
332 }
333}
334
diff --git a/src/fsec-print/syscall_list.c b/src/fsec-print/syscall_list.c
new file mode 100644
index 000000000..410956de5
--- /dev/null
+++ b/src/fsec-print/syscall_list.c
@@ -0,0 +1,47 @@
1/*
2 * Copyright (C) 2014-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 "fsec_print.h"
21#include <sys/syscall.h>
22
23typedef struct {
24 const char * const name;
25 int nr;
26} SyscallEntry;
27
28static const SyscallEntry syslist[] = {
29//
30// code generated using tools/extract-syscall
31//
32#include "../include/syscall.h"
33//
34// end of generated code
35//
36}; // end of syslist
37
38const char *syscall_find_nr(int nr) {
39 int i;
40 int elems = sizeof(syslist) / sizeof(syslist[0]);
41 for (i = 0; i < elems; i++) {
42 if (nr == syslist[i].nr)
43 return syslist[i].name;
44 }
45
46 return NULL;
47}
diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c
index ae0ae64ef..030eaf90b 100644
--- a/src/fseccomp/main.c
+++ b/src/fseccomp/main.c
@@ -37,7 +37,6 @@ static void usage(void) {
37 printf("\tfseccomp default drop file1 file2 list allow-debuggers\n"); 37 printf("\tfseccomp default drop file1 file2 list allow-debuggers\n");
38 printf("\tfseccomp keep file1 file2 list\n"); 38 printf("\tfseccomp keep file1 file2 list\n");
39 printf("\tfseccomp memory-deny-write-execute file\n"); 39 printf("\tfseccomp memory-deny-write-execute file\n");
40 printf("\tfseccomp print file\n");
41} 40}
42 41
43int main(int argc, char **argv) { 42int main(int argc, char **argv) {
@@ -93,8 +92,6 @@ printf("\n");
93 seccomp_keep(argv[2], argv[3], argv[4]); 92 seccomp_keep(argv[2], argv[3], argv[4]);
94 else if (argc == 3 && strcmp(argv[1], "memory-deny-write-execute") == 0) 93 else if (argc == 3 && strcmp(argv[1], "memory-deny-write-execute") == 0)
95 memory_deny_write_execute(argv[2]); 94 memory_deny_write_execute(argv[2]);
96 else if (argc == 3 && strcmp(argv[1], "print") == 0)
97 filter_print(argv[2]);
98 else { 95 else {
99 fprintf(stderr, "Error fseccomp: invalid arguments\n"); 96 fprintf(stderr, "Error fseccomp: invalid arguments\n");
100 return 1; 97 return 1;
diff --git a/src/fseccomp/seccomp_print.c b/src/fseccomp/seccomp_print.c
deleted file mode 100644
index ffc65e7c3..000000000
--- a/src/fseccomp/seccomp_print.c
+++ /dev/null
@@ -1,183 +0,0 @@
1/*
2 * Copyright (C) 2014-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 "fseccomp.h"
21#include "../include/seccomp.h"
22#include <sys/syscall.h>
23
24static struct sock_filter *filter = NULL;
25static int filter_cnt = 0;
26
27static void load_seccomp(const char *fname) {
28 assert(fname);
29
30 // open filter file
31 int fd = open(fname, O_RDONLY);
32 if (fd == -1)
33 goto errexit;
34
35 // calculate the number of entries
36 int size = lseek(fd, 0, SEEK_END);
37 if (size == -1)
38 goto errexit;
39 if (lseek(fd, 0 , SEEK_SET) == -1)
40 goto errexit;
41 unsigned short entries = (unsigned short) size / (unsigned short) sizeof(struct sock_filter);
42 filter_cnt = entries;
43
44 // read filter
45 filter = malloc(size);
46 if (filter == NULL)
47 goto errexit;
48 memset(filter, 0, size);
49 int rd = 0;
50 while (rd < size) {
51 int rv = read(fd, (unsigned char *) filter + rd, size - rd);
52 if (rv == -1)
53 goto errexit;
54 rd += rv;
55 }
56
57 // close file
58 close(fd);
59 return;
60
61errexit:
62 fprintf(stderr, "Error fseccomp: cannot read %s\n", fname);
63 exit(1);
64}
65
66static int detect_filter_type(void) {
67 // the filter ishould already be load in filter variable
68 assert(filter);
69
70 printf("SECCOMP Filter\n");
71
72 // testing for main seccomp filter, protocol, mdwe - platform architecture
73 const struct sock_filter start_main[] = {
74 VALIDATE_ARCHITECTURE,
75#if defined(__x86_64__)
76 EXAMINE_SYSCALL,
77 HANDLE_X32
78#else
79 EXAMINE_SYSCALL
80#endif
81 };
82
83 if (memcmp(&start_main[0], filter, sizeof(start_main)) == 0) {
84 printf(" VALIDATE_ARCHITECTURE\n");
85 printf(" EXAMINE_SYSCALL\n");
86#if defined(__x86_64__)
87 printf(" HANDLE_X32\n");
88#endif
89 return sizeof(start_main) / sizeof(struct sock_filter);
90 }
91
92
93 // testing for secondary 64 bit filter
94 const struct sock_filter start_secondary_64[] = {
95 VALIDATE_ARCHITECTURE_64,
96 EXAMINE_SYSCALL,
97 };
98
99 if (memcmp(&start_secondary_64[0], filter, sizeof(start_secondary_64)) == 0) {
100 printf(" VALIDATE_ARCHITECTURE_64\n");
101 printf(" EXAMINE_SYSCALL\n");
102 return sizeof(start_secondary_64) / sizeof(struct sock_filter);
103 }
104
105 // testing for secondary 32 bit filter
106 const struct sock_filter start_secondary_32[] = {
107 VALIDATE_ARCHITECTURE_32,
108 EXAMINE_SYSCALL,
109 };
110
111 if (memcmp(&start_secondary_32[0], filter, sizeof(start_secondary_32)) == 0) {
112 printf(" VALIDATE_ARCHITECTURE_32\n");
113 printf(" EXAMINE_SYSCALL\n");
114 return sizeof(start_secondary_32) / sizeof(struct sock_filter);
115 }
116
117 const struct sock_filter start_secondary_block[] = {
118 VALIDATE_ARCHITECTURE_KILL,
119#if defined(__x86_64__)
120 EXAMINE_SYSCALL,
121 HANDLE_X32_KILL,
122#else
123 EXAMINE_SYSCALL
124#endif
125 };
126
127 if (memcmp(&start_secondary_block[0], filter, sizeof(start_secondary_block)) == 0) {
128 printf(" VALIDATE_ARCHITECTURE_KILL\n");
129 printf(" EXAMINE_SYSCALL\n");
130#if defined(__x86_64__)
131 printf(" HANDLE_X32_KILL\n");
132#endif
133 return sizeof(start_secondary_block) / sizeof(struct sock_filter);
134 }
135
136 return 0; // filter unrecognized
137}
138
139// debug filter
140void filter_print(const char *fname) {
141 assert(fname);
142 load_seccomp(fname);
143
144 int i = detect_filter_type();
145 if (i == 0) {
146 printf("Invalid seccomp filter %s\n", fname);
147 return;
148 }
149
150 // loop trough the rest of commands
151 while (i < filter_cnt) {
152 // minimal parsing!
153 struct sock_filter *s = (struct sock_filter *) &filter[i];
154 if (s->code == BPF_JMP+BPF_JEQ+BPF_K && (s + 1)->code == BPF_RET+BPF_K && (s + 1)->k == SECCOMP_RET_ALLOW ) {
155 printf(" WHITELIST %d %s\n", s->k, syscall_find_nr(s->k));
156 i += 2;
157 }
158 else if (s->code == BPF_JMP+BPF_JEQ+BPF_K && (s + 1)->code == BPF_RET+BPF_K && (s + 1)->k == SECCOMP_RET_KILL ) {
159 printf(" BLACKLIST %d %s\n", s->k, syscall_find_nr(s->k));
160 i += 2;
161 }
162 else if (s->code == BPF_JMP+BPF_JEQ+BPF_K && (s + 1)->code == BPF_RET+BPF_K && ((s + 1)->k & ~SECCOMP_RET_DATA) == SECCOMP_RET_ERRNO) {
163 printf(" BLACKLIST_ERRNO %d %s %d %s\n", s->k, syscall_find_nr(s->k), (s + 1)->k & SECCOMP_RET_DATA, errno_find_nr((s + 1)->k & SECCOMP_RET_DATA));
164 i += 2;
165 }
166 else if (s->code == BPF_RET+BPF_K && (s->k & ~SECCOMP_RET_DATA) == SECCOMP_RET_ERRNO) {
167 printf(" RETURN_ERRNO %d %s\n", s->k & SECCOMP_RET_DATA, errno_find_nr(s->k & SECCOMP_RET_DATA));
168 i++;
169 }
170 else if (s->code == BPF_RET+BPF_K && s->k == SECCOMP_RET_KILL) {
171 printf(" KILL_PROCESS\n");
172 i++;
173 }
174 else if (s->code == BPF_RET+BPF_K && s->k == SECCOMP_RET_ALLOW) {
175 printf(" RETURN_ALLOW\n");
176 i++;
177 }
178 else {
179 printf(" UNKNOWN ENTRY %x!\n", s->code);
180 i++;
181 }
182 }
183}
diff --git a/src/include/seccomp.h b/src/include/seccomp.h
index b8bfce96b..6d8983b39 100644
--- a/src/include/seccomp.h
+++ b/src/include/seccomp.h
@@ -67,6 +67,14 @@
67#include <sys/stat.h> 67#include <sys/stat.h>
68#include <fcntl.h> 68#include <fcntl.h>
69 69
70// From /usr/include/linux/filter.h
71//struct sock_filter { /* Filter block */
72// __u16 code; /* Actual filter code */
73// __u8 jt; /* Jump true */
74// __u8 jf; /* Jump false */
75// __u32 k; /* Generic multiuse field */
76//};
77
70#include <sys/prctl.h> 78#include <sys/prctl.h>
71#ifndef PR_SET_NO_NEW_PRIVS 79#ifndef PR_SET_NO_NEW_PRIVS
72# define PR_SET_NO_NEW_PRIVS 38 80# define PR_SET_NO_NEW_PRIVS 38
@@ -81,6 +89,7 @@
81#define SECCOMP_RET_ALLOW 0x7fff0000U 89#define SECCOMP_RET_ALLOW 0x7fff0000U
82#define SECCOMP_RET_ERRNO 0x00050000U 90#define SECCOMP_RET_ERRNO 0x00050000U
83#define SECCOMP_RET_DATA 0x0000ffffU 91#define SECCOMP_RET_DATA 0x0000ffffU
92
84struct seccomp_data { 93struct seccomp_data {
85 int nr; 94 int nr;
86 __u32 arch; 95 __u32 arch;
@@ -89,6 +98,11 @@ struct seccomp_data {
89}; 98};
90#endif 99#endif
91 100
101#ifndef SECCOMP_RET_LOG
102#define SECCOMP_RET_LOG 0x7ffc0000U
103#endif
104
105
92#if defined(__i386__) 106#if defined(__i386__)
93# define ARCH_NR AUDIT_ARCH_I386 107# define ARCH_NR AUDIT_ARCH_I386
94# define ARCH_32 AUDIT_ARCH_I386 108# define ARCH_32 AUDIT_ARCH_I386