diff options
Diffstat (limited to 'src/fseccomp/seccomp.c')
-rw-r--r-- | src/fseccomp/seccomp.c | 143 |
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 | ||
27 | static void add_default_list(int fd, int allow_debuggers) { | 27 | static 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 |
49 | void seccomp_default(const char *fname, int allow_debuggers) { | 49 | void 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 |
69 | void seccomp_drop(const char *fname1, const char *fname2, char *list, int allow_debuggers) { | 69 | void 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 |
121 | void seccomp_default_drop(const char *fname1, const char *fname2, char *list, int allow_debuggers) { | 121 | void 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 | ||
174 | void seccomp_keep(const char *fname1, const char *fname2, char *list) { | 174 | void 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 | ||
221 | void memory_deny_write_execute(const char *fname) { | 236 | void 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 | |||
307 | void 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 | } | ||