summaryrefslogtreecommitdiffstats
path: root/src/fsec-print
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2017-12-28 12:28:08 -0500
committerLibravatar netblue30 <netblue30@yahoo.com>2017-12-28 12:28:08 -0500
commitf9c60d5a3aaecc11b1dbb933bca45c461b03ca83 (patch)
tree4538785f5889ee8836afadb36f29308a4ccf7ccb /src/fsec-print
parentAdd netlink and noblacklist openssl to teamspeak3 profile - potential fix for... (diff)
downloadfirejail-f9c60d5a3aaecc11b1dbb933bca45c461b03ca83.tar.gz
firejail-f9c60d5a3aaecc11b1dbb933bca45c461b03ca83.tar.zst
firejail-f9c60d5a3aaecc11b1dbb933bca45c461b03ca83.zip
replacing seccomp printing with a seccomp disassembler
Diffstat (limited to 'src/fsec-print')
-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
5 files changed, 539 insertions, 0 deletions
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}