aboutsummaryrefslogtreecommitdiffstats
path: root/src/fseccomp/seccomp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fseccomp/seccomp.c')
-rw-r--r--src/fseccomp/seccomp.c143
1 files changed, 115 insertions, 28 deletions
diff --git a/src/fseccomp/seccomp.c b/src/fseccomp/seccomp.c
index 29aa2f2f5..0db7b5954 100644
--- a/src/fseccomp/seccomp.c
+++ b/src/fseccomp/seccomp.c
@@ -24,12 +24,12 @@
24#include <sys/syscall.h> 24#include <sys/syscall.h>
25#include <sys/types.h> 25#include <sys/types.h>
26 26
27static void add_default_list(int fd, int allow_debuggers) { 27static void add_default_list(int fd, int allow_debuggers, bool native) {
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, NULL); 30 r = syscall_check_list("@default-nodebuggers", filter_add_blacklist, fd, 0, NULL, native);
31 else 31 else
32 r = syscall_check_list("@default", filter_add_blacklist, fd, 0, NULL); 32 r = syscall_check_list("@default", filter_add_blacklist, fd, 0, NULL, native);
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
@@ -46,7 +46,7 @@ static void add_default_list(int fd, int allow_debuggers) {
46} 46}
47 47
48// default list 48// default list
49void seccomp_default(const char *fname, int allow_debuggers) { 49void seccomp_default(const char *fname, int allow_debuggers, bool native) {
50 assert(fname); 50 assert(fname);
51 51
52 // open file 52 // open file
@@ -57,8 +57,8 @@ void seccomp_default(const char *fname, int allow_debuggers) {
57 } 57 }
58 58
59 // build filter (no post-exec filter needed because default list is fine for us) 59 // build filter (no post-exec filter needed because default list is fine for us)
60 filter_init(fd); 60 filter_init(fd, native);
61 add_default_list(fd, allow_debuggers); 61 add_default_list(fd, allow_debuggers, native);
62 filter_end_blacklist(fd); 62 filter_end_blacklist(fd);
63 63
64 // close file 64 // close file
@@ -66,7 +66,7 @@ void seccomp_default(const char *fname, int allow_debuggers) {
66} 66}
67 67
68// drop list 68// drop list
69void seccomp_drop(const char *fname1, const char *fname2, char *list, int allow_debuggers) { 69void seccomp_drop(const char *fname1, const char *fname2, char *list, int allow_debuggers, bool native) {
70 assert(fname1); 70 assert(fname1);
71 assert(fname2); 71 assert(fname2);
72 (void) allow_debuggers; // todo: to implemnet it 72 (void) allow_debuggers; // todo: to implemnet it
@@ -79,15 +79,15 @@ void seccomp_drop(const char *fname1, const char *fname2, char *list, int allow_
79 } 79 }
80 80
81 // build pre-exec filter: don't blacklist any syscalls in @default-keep 81 // build pre-exec filter: don't blacklist any syscalls in @default-keep
82 filter_init(fd); 82 filter_init(fd, native);
83 83
84 // allow exceptions in form of !syscall 84 // allow exceptions in form of !syscall
85 syscall_check_list(list, filter_add_whitelist_for_excluded, fd, 0, NULL); 85 syscall_check_list(list, filter_add_whitelist_for_excluded, fd, 0, NULL, native);
86 86
87 char *prelist, *postlist; 87 char *prelist, *postlist;
88 syscalls_in_list(list, "@default-keep", fd, &prelist, &postlist); 88 syscalls_in_list(list, "@default-keep", fd, &prelist, &postlist, native);
89 if (prelist) 89 if (prelist)
90 if (syscall_check_list(prelist, filter_add_blacklist, fd, 0, NULL)) { 90 if (syscall_check_list(prelist, filter_add_blacklist, fd, 0, NULL, native)) {
91 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n"); 91 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n");
92 exit(1); 92 exit(1);
93 } 93 }
@@ -106,8 +106,8 @@ void seccomp_drop(const char *fname1, const char *fname2, char *list, int allow_
106 } 106 }
107 107
108 // build post-exec filter: blacklist remaining syscalls 108 // build post-exec filter: blacklist remaining syscalls
109 filter_init(fd); 109 filter_init(fd, native);
110 if (syscall_check_list(postlist, filter_add_blacklist, fd, 0, NULL)) { 110 if (syscall_check_list(postlist, filter_add_blacklist, fd, 0, NULL, native)) {
111 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n"); 111 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n");
112 exit(1); 112 exit(1);
113 } 113 }
@@ -118,7 +118,7 @@ void seccomp_drop(const char *fname1, const char *fname2, char *list, int allow_
118} 118}
119 119
120// default+drop 120// default+drop
121void seccomp_default_drop(const char *fname1, const char *fname2, char *list, int allow_debuggers) { 121void seccomp_default_drop(const char *fname1, const char *fname2, char *list, int allow_debuggers, bool native) {
122 assert(fname1); 122 assert(fname1);
123 assert(fname2); 123 assert(fname2);
124 124
@@ -131,16 +131,16 @@ void seccomp_default_drop(const char *fname1, const char *fname2, char *list, in
131 131
132 // build pre-exec filter: blacklist @default, don't blacklist 132 // build pre-exec filter: blacklist @default, don't blacklist
133 // any listed syscalls in @default-keep 133 // any listed syscalls in @default-keep
134 filter_init(fd); 134 filter_init(fd, native);
135 135
136 // allow exceptions in form of !syscall 136 // allow exceptions in form of !syscall
137 syscall_check_list(list, filter_add_whitelist_for_excluded, fd, 0, NULL); 137 syscall_check_list(list, filter_add_whitelist_for_excluded, fd, 0, NULL, native);
138 138
139 add_default_list(fd, allow_debuggers); 139 add_default_list(fd, allow_debuggers, native);
140 char *prelist, *postlist; 140 char *prelist, *postlist;
141 syscalls_in_list(list, "@default-keep", fd, &prelist, &postlist); 141 syscalls_in_list(list, "@default-keep", fd, &prelist, &postlist, native);
142 if (prelist) 142 if (prelist)
143 if (syscall_check_list(prelist, filter_add_blacklist, fd, 0, NULL)) { 143 if (syscall_check_list(prelist, filter_add_blacklist, fd, 0, NULL, native)) {
144 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n"); 144 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n");
145 exit(1); 145 exit(1);
146 } 146 }
@@ -160,8 +160,8 @@ void seccomp_default_drop(const char *fname1, const char *fname2, char *list, in
160 } 160 }
161 161
162 // build post-exec filter: blacklist remaining syscalls 162 // build post-exec filter: blacklist remaining syscalls
163 filter_init(fd); 163 filter_init(fd, native);
164 if (syscall_check_list(postlist, filter_add_blacklist, fd, 0, NULL)) { 164 if (syscall_check_list(postlist, filter_add_blacklist, fd, 0, NULL, native)) {
165 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n"); 165 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n");
166 exit(1); 166 exit(1);
167 } 167 }
@@ -171,7 +171,7 @@ void seccomp_default_drop(const char *fname1, const char *fname2, char *list, in
171 close(fd); 171 close(fd);
172} 172}
173 173
174void seccomp_keep(const char *fname1, const char *fname2, char *list) { 174void seccomp_keep(const char *fname1, const char *fname2, char *list, bool native) {
175 (void) fname2; 175 (void) fname2;
176 176
177 // open file for pre-exec filter 177 // open file for pre-exec filter
@@ -182,17 +182,17 @@ void seccomp_keep(const char *fname1, const char *fname2, char *list) {
182 } 182 }
183 183
184 // build pre-exec filter: whitelist also @default-keep 184 // build pre-exec filter: whitelist also @default-keep
185 filter_init(fd); 185 filter_init(fd, native);
186 186
187 // allow exceptions in form of !syscall 187 // allow exceptions in form of !syscall
188 syscall_check_list(list, filter_add_blacklist_for_excluded, fd, 0, NULL); 188 syscall_check_list(list, filter_add_blacklist_for_excluded, fd, 0, NULL, native);
189 189
190 // these syscalls are used by firejail after the seccomp filter is initialized 190 // these syscalls are used by firejail after the seccomp filter is initialized
191 int r; 191 int r;
192 r = syscall_check_list("@default-keep", filter_add_whitelist, fd, 0, NULL); 192 r = syscall_check_list("@default-keep", filter_add_whitelist, fd, 0, NULL, native);
193 assert(r == 0); 193 assert(r == 0);
194 194
195 if (syscall_check_list(list, filter_add_whitelist, fd, 0, NULL)) { 195 if (syscall_check_list(list, filter_add_whitelist, fd, 0, NULL, native)) {
196 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n"); 196 fprintf(stderr, "Error fseccomp: cannot build seccomp filter\n");
197 exit(1); 197 exit(1);
198 } 198 }
@@ -206,6 +206,15 @@ void seccomp_keep(const char *fname1, const char *fname2, char *list) {
206#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) 206#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__)
207# define filter_syscall SYS_mmap 207# define filter_syscall SYS_mmap
208# undef block_syscall 208# undef block_syscall
209#if defined(__x86_64__)
210// i386 syscalls
211# define filter_syscall_32 192
212# define block_syscall_32 90
213# define mprotect_32 125
214# define pkey_mprotect_32 380
215# define shmat_32 397
216# define memfd_create_32 356
217#endif
209#elif defined(__i386__) 218#elif defined(__i386__)
210# define filter_syscall SYS_mmap2 219# define filter_syscall SYS_mmap2
211# define block_syscall SYS_mmap 220# define block_syscall SYS_mmap
@@ -216,6 +225,12 @@ void seccomp_keep(const char *fname1, const char *fname2, char *list) {
216# warning "Platform does not support seccomp memory-deny-write-execute filter yet" 225# warning "Platform does not support seccomp memory-deny-write-execute filter yet"
217# undef filter_syscall 226# undef filter_syscall
218# undef block_syscall 227# undef block_syscall
228# undef filter_syscall_32
229# undef block_syscall_32
230# undef mprotect_32
231# undef pkey_mprotect_32
232# undef shmat_32
233# undef memfd_create_32
219#endif 234#endif
220 235
221void memory_deny_write_execute(const char *fname) { 236void memory_deny_write_execute(const char *fname) {
@@ -226,10 +241,10 @@ void memory_deny_write_execute(const char *fname) {
226 exit(1); 241 exit(1);
227 } 242 }
228 243
229 filter_init(fd); 244 filter_init(fd, true);
230 245
231 // build filter 246 // build filter
232 static const struct sock_filter filter[] = { 247 struct sock_filter filter[] = {
233#ifdef block_syscall 248#ifdef block_syscall
234 // block old multiplexing mmap syscall for i386 249 // block old multiplexing mmap syscall for i386
235 BLACKLIST(block_syscall), 250 BLACKLIST(block_syscall),
@@ -288,3 +303,75 @@ void memory_deny_write_execute(const char *fname) {
288 // close file 303 // close file
289 close(fd); 304 close(fd);
290} 305}
306
307void memory_deny_write_execute_32(const char *fname) {
308 // open file
309 int fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
310 if (fd < 0) {
311 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname);
312 exit(1);
313 }
314
315 filter_init(fd, false);
316
317 // build filter
318 struct sock_filter filter[] = {
319#if defined(__x86_64__)
320#ifdef block_syscall_32
321 // block old multiplexing mmap syscall for i386
322 BLACKLIST(block_syscall_32),
323#endif
324#ifdef filter_syscall_32
325 // block mmap(,,x|PROT_WRITE|PROT_EXEC) so W&X memory can't be created
326 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, filter_syscall_32, 0, 5),
327 EXAMINE_ARGUMENT(2),
328 BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_WRITE|PROT_EXEC),
329 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_WRITE|PROT_EXEC, 0, 1),
330 KILL_PROCESS,
331 RETURN_ALLOW,
332#endif
333#ifdef mprotect_32
334 // block mprotect(,,PROT_EXEC) so writable memory can't be turned into executable
335 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, mprotect_32, 0, 5),
336 EXAMINE_ARGUMENT(2),
337 BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC),
338 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1),
339 KILL_PROCESS,
340 RETURN_ALLOW,
341#endif
342#ifdef pkey_mprotect_32
343 // same for pkey_mprotect(,,PROT_EXEC), where available
344 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, pkey_mprotect_32, 0, 5),
345 EXAMINE_ARGUMENT(2),
346 BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC),
347 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1),
348 KILL_PROCESS,
349 RETURN_ALLOW,
350#endif
351
352#ifdef shmat_32
353 // block shmat(,,x|SHM_EXEC) so W&X shared memory can't be created
354 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, shmat_32, 0, 5),
355 EXAMINE_ARGUMENT(2),
356 BPF_STMT(BPF_ALU+BPF_AND+BPF_K, SHM_EXEC),
357 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SHM_EXEC, 0, 1),
358 KILL_PROCESS,
359 RETURN_ALLOW,
360#endif
361#ifdef memfd_create_32
362 // block memfd_create as it can be used to create
363 // arbitrary memory contents which can be later mapped
364 // as executable
365 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, memfd_create_32, 0, 1),
366 KILL_PROCESS,
367#endif
368#endif
369 RETURN_ALLOW
370 };
371 write_to_file(fd, filter, sizeof(filter));
372
373 filter_end_blacklist(fd);
374
375 // close file
376 close(fd);
377}