diff options
author | Topi Miettinen <toiwoton@gmail.com> | 2017-08-13 14:07:31 +0300 |
---|---|---|
committer | Topi Miettinen <toiwoton@gmail.com> | 2017-08-13 17:31:07 +0300 |
commit | 63e9d849f662d1a494c6396d4a439cd4c91dfa7e (patch) | |
tree | 703cc8c9c0eb5b9e528f025961df7f322f797737 /src/fseccomp/syscall.c | |
parent | merges (diff) | |
download | firejail-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
Diffstat (limited to 'src/fseccomp/syscall.c')
-rw-r--r-- | src/fseccomp/syscall.c | 64 |
1 files changed, 60 insertions, 4 deletions
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 | ||
23 | typedef struct { | 25 | typedef struct { |
@@ -30,6 +32,13 @@ typedef struct { | |||
30 | const char * const list; | 32 | const char * const list; |
31 | } SyscallGroupList; | 33 | } SyscallGroupList; |
32 | 34 | ||
35 | typedef struct { | ||
36 | const char *slist; | ||
37 | char *prelist, *postlist; | ||
38 | bool found; | ||
39 | int syscall; | ||
40 | } SyscallCheckList; | ||
41 | |||
33 | static const SyscallEntry syslist[] = { | 42 | static 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 |
452 | int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int arg), int fd, int arg) { | 462 | int 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 | |||
512 | static 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 | ||
520 | static 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 | ||
545 | void 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 | } | ||