diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/firejail.h | 3 | ||||
-rw-r--r-- | src/firejail/main.c | 7 | ||||
-rw-r--r-- | src/firejail/preproc.c | 2 | ||||
-rw-r--r-- | src/firejail/profile.c | 11 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 5 | ||||
-rw-r--r-- | src/fseccomp/fseccomp.h | 3 | ||||
-rw-r--r-- | src/fseccomp/main.c | 3 | ||||
-rw-r--r-- | src/fseccomp/seccomp.c | 54 | ||||
-rw-r--r-- | src/fseccomp/seccomp_file.c | 2 | ||||
-rw-r--r-- | src/man/firejail.txt | 6 |
10 files changed, 95 insertions, 1 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 37e4aeb30..1a26396a7 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -54,10 +54,12 @@ | |||
54 | #define RUN_SECCOMP_CFG "/run/firejail/mnt/seccomp" // configured filter | 54 | #define RUN_SECCOMP_CFG "/run/firejail/mnt/seccomp" // configured filter |
55 | #define RUN_SECCOMP_AMD64 "/run/firejail/mnt/seccomp.amd64" // amd64 filter installed on i386 architectures | 55 | #define RUN_SECCOMP_AMD64 "/run/firejail/mnt/seccomp.amd64" // amd64 filter installed on i386 architectures |
56 | #define RUN_SECCOMP_I386 "/run/firejail/mnt/seccomp.i386" // i386 filter installed on amd64 architectures | 56 | #define RUN_SECCOMP_I386 "/run/firejail/mnt/seccomp.i386" // i386 filter installed on amd64 architectures |
57 | #define RUN_SECCOMP_MDWX "/run/firejail/mnt/seccomp.mdwx" // filter for memory-deny-write-execute | ||
57 | #define PATH_SECCOMP_DEFAULT (LIBDIR "/firejail/seccomp") // default filter built during make | 58 | #define PATH_SECCOMP_DEFAULT (LIBDIR "/firejail/seccomp") // default filter built during make |
58 | #define PATH_SECCOMP_DEFAULT_DEBUG (LIBDIR "/firejail/seccomp.debug") // default filter built during make | 59 | #define PATH_SECCOMP_DEFAULT_DEBUG (LIBDIR "/firejail/seccomp.debug") // default filter built during make |
59 | #define PATH_SECCOMP_AMD64 (LIBDIR "/firejail/seccomp.amd64") // amd64 filter built during make | 60 | #define PATH_SECCOMP_AMD64 (LIBDIR "/firejail/seccomp.amd64") // amd64 filter built during make |
60 | #define PATH_SECCOMP_I386 (LIBDIR "/firejail/seccomp.i386") // i386 filter built during make | 61 | #define PATH_SECCOMP_I386 (LIBDIR "/firejail/seccomp.i386") // i386 filter built during make |
62 | #define PATH_SECCOMP_MDWX (LIBDIR "/firejail/seccomp.mdwx") // filter for memory-deny-write-execute built during make | ||
61 | 63 | ||
62 | 64 | ||
63 | #define RUN_DEV_DIR "/run/firejail/mnt/dev" | 65 | #define RUN_DEV_DIR "/run/firejail/mnt/dev" |
@@ -355,6 +357,7 @@ extern int arg_allusers; // all user home directories visible | |||
355 | extern int arg_machineid; // preserve /etc/machine-id | 357 | extern int arg_machineid; // preserve /etc/machine-id |
356 | extern int arg_disable_mnt; // disable /mnt and /media | 358 | extern int arg_disable_mnt; // disable /mnt and /media |
357 | extern int arg_noprofile; // use default.profile if none other found/specified | 359 | extern int arg_noprofile; // use default.profile if none other found/specified |
360 | extern int arg_memory_deny_write_execute; // block writable and executable memory | ||
358 | 361 | ||
359 | extern int login_shell; | 362 | extern int login_shell; |
360 | extern int parent_to_child_fds[2]; | 363 | extern int parent_to_child_fds[2]; |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 4ed8e30c9..561a14f5a 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -111,6 +111,7 @@ int arg_allow_private_blacklist = 0; // blacklist things in private directorie | |||
111 | int arg_writable_var_log = 0; // writable /var/log | 111 | int arg_writable_var_log = 0; // writable /var/log |
112 | int arg_disable_mnt = 0; // disable /mnt and /media | 112 | int arg_disable_mnt = 0; // disable /mnt and /media |
113 | int arg_noprofile = 0; // use default.profile if none other found/specified | 113 | int arg_noprofile = 0; // use default.profile if none other found/specified |
114 | int arg_memory_deny_write_execute = 0; // block writable and executable memory | ||
114 | 115 | ||
115 | int login_shell = 0; | 116 | int login_shell = 0; |
116 | 117 | ||
@@ -1145,6 +1146,12 @@ int main(int argc, char **argv) { | |||
1145 | else | 1146 | else |
1146 | exit_err_feature("seccomp"); | 1147 | exit_err_feature("seccomp"); |
1147 | } | 1148 | } |
1149 | else if (strcmp(argv[i], "--memory-deny-write-execute") == 0) { | ||
1150 | if (checkcfg(CFG_SECCOMP)) | ||
1151 | arg_memory_deny_write_execute = 1; | ||
1152 | else | ||
1153 | exit_err_feature("seccomp"); | ||
1154 | } | ||
1148 | #endif | 1155 | #endif |
1149 | else if (strcmp(argv[i], "--caps") == 0) | 1156 | else if (strcmp(argv[i], "--caps") == 0) |
1150 | arg_caps_default_filter = 1; | 1157 | arg_caps_default_filter = 1; |
diff --git a/src/firejail/preproc.c b/src/firejail/preproc.c index ef93368bf..9c474415d 100644 --- a/src/firejail/preproc.c +++ b/src/firejail/preproc.c | |||
@@ -83,6 +83,8 @@ void preproc_mount_mnt_dir(void) { | |||
83 | else | 83 | else |
84 | copy_file(PATH_SECCOMP_DEFAULT, RUN_SECCOMP_CFG, getuid(), getgid(), 0644); // root needed | 84 | copy_file(PATH_SECCOMP_DEFAULT, RUN_SECCOMP_CFG, getuid(), getgid(), 0644); // root needed |
85 | 85 | ||
86 | if (arg_memory_deny_write_execute) | ||
87 | copy_file(PATH_SECCOMP_MDWX, RUN_SECCOMP_MDWX, getuid(), getgid(), 0644); // root needed | ||
86 | // as root, create an empty RUN_SECCOMP_PROTOCOL file | 88 | // as root, create an empty RUN_SECCOMP_PROTOCOL file |
87 | create_empty_file_as_root(RUN_SECCOMP_PROTOCOL, 0644); | 89 | create_empty_file_as_root(RUN_SECCOMP_PROTOCOL, 0644); |
88 | if (set_perms(RUN_SECCOMP_PROTOCOL, getuid(), getgid(), 0644)) | 90 | if (set_perms(RUN_SECCOMP_PROTOCOL, getuid(), getgid(), 0644)) |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index f084edaad..6d5ee349c 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -595,6 +595,17 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
595 | return 0; | 595 | return 0; |
596 | } | 596 | } |
597 | 597 | ||
598 | // memory deny write&execute | ||
599 | if (strncmp(ptr, "memory-deny-write-execute ", sizeof("memory-deny-write-execute ") - 1) == 0) { | ||
600 | #ifdef HAVE_SECCOMP | ||
601 | if (checkcfg(CFG_SECCOMP)) | ||
602 | arg_memory_deny_write_execute = 1; | ||
603 | else | ||
604 | warning_feature_disabled("seccomp"); | ||
605 | #endif | ||
606 | return 0; | ||
607 | } | ||
608 | |||
598 | // caps drop list | 609 | // caps drop list |
599 | if (strncmp(ptr, "caps.drop ", 10) == 0) { | 610 | if (strncmp(ptr, "caps.drop ", 10) == 0) { |
600 | arg_caps_drop = 1; | 611 | arg_caps_drop = 1; |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 4b30cb991..6c0fdebe3 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -1001,6 +1001,11 @@ int sandbox(void* sandbox_arg) { | |||
1001 | else | 1001 | else |
1002 | seccomp_filter_drop(enforce_seccomp); | 1002 | seccomp_filter_drop(enforce_seccomp); |
1003 | } | 1003 | } |
1004 | if (arg_memory_deny_write_execute) { | ||
1005 | if (arg_debug) | ||
1006 | printf("Install memory write&execute filter\n"); | ||
1007 | seccomp_load(RUN_SECCOMP_MDWX); // install filter | ||
1008 | } | ||
1004 | #endif | 1009 | #endif |
1005 | 1010 | ||
1006 | //**************************************** | 1011 | //**************************************** |
diff --git a/src/fseccomp/fseccomp.h b/src/fseccomp/fseccomp.h index 1e4881e9c..157b71011 100644 --- a/src/fseccomp/fseccomp.h +++ b/src/fseccomp/fseccomp.h | |||
@@ -48,6 +48,7 @@ void seccomp_secondary_64(const char *fname); | |||
48 | void seccomp_secondary_32(const char *fname); | 48 | void seccomp_secondary_32(const char *fname); |
49 | 49 | ||
50 | // seccomp_file.c | 50 | // seccomp_file.c |
51 | void write_to_file(int fd, const void *data, int size); | ||
51 | void filter_init(int fd); | 52 | void filter_init(int fd); |
52 | void filter_add_whitelist(int fd, int syscall, int arg); | 53 | void filter_add_whitelist(int fd, int syscall, int arg); |
53 | void filter_add_blacklist(int fd, int syscall, int arg); | 54 | void filter_add_blacklist(int fd, int syscall, int arg); |
@@ -64,6 +65,8 @@ void seccomp_drop(const char *fname, char *list, int allow_debuggers); | |||
64 | void seccomp_default_drop(const char *fname, char *list, int allow_debuggers); | 65 | void seccomp_default_drop(const char *fname, char *list, int allow_debuggers); |
65 | // whitelisted filter | 66 | // whitelisted filter |
66 | void seccomp_keep(const char *fname, char *list); | 67 | void seccomp_keep(const char *fname, char *list); |
68 | // block writable and executable memory | ||
69 | void memory_deny_write_execute(const char *fname); | ||
67 | 70 | ||
68 | // seccomp_print | 71 | // seccomp_print |
69 | void filter_print(const char *fname); | 72 | void filter_print(const char *fname); |
diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c index e322b5bbb..3d95d5bb2 100644 --- a/src/fseccomp/main.c +++ b/src/fseccomp/main.c | |||
@@ -35,6 +35,7 @@ static void usage(void) { | |||
35 | printf("\tfseccomp default drop file list\n"); | 35 | printf("\tfseccomp default drop file list\n"); |
36 | printf("\tfseccomp default drop file list allow-debuggers\n"); | 36 | printf("\tfseccomp default drop file list allow-debuggers\n"); |
37 | printf("\tfseccomp keep file list\n"); | 37 | printf("\tfseccomp keep file list\n"); |
38 | printf("\tfseccomp memory-deny-write-execute file\n"); | ||
38 | printf("\tfseccomp print file\n"); | 39 | printf("\tfseccomp print file\n"); |
39 | } | 40 | } |
40 | 41 | ||
@@ -87,6 +88,8 @@ printf("\n"); | |||
87 | seccomp_default_drop(argv[3], argv[4], 1); | 88 | seccomp_default_drop(argv[3], argv[4], 1); |
88 | else if (argc == 4 && strcmp(argv[1], "keep") == 0) | 89 | else if (argc == 4 && strcmp(argv[1], "keep") == 0) |
89 | seccomp_keep(argv[2], argv[3]); | 90 | seccomp_keep(argv[2], argv[3]); |
91 | else if (argc == 3 && strcmp(argv[1], "memory-deny-write-execute") == 0) | ||
92 | memory_deny_write_execute(argv[2]); | ||
90 | else if (argc == 3 && strcmp(argv[1], "print") == 0) | 93 | else if (argc == 3 && strcmp(argv[1], "print") == 0) |
91 | filter_print(argv[2]); | 94 | filter_print(argv[2]); |
92 | else { | 95 | else { |
diff --git a/src/fseccomp/seccomp.c b/src/fseccomp/seccomp.c index 4f8de8c5e..7d2ccbbce 100644 --- a/src/fseccomp/seccomp.c +++ b/src/fseccomp/seccomp.c | |||
@@ -19,7 +19,10 @@ | |||
19 | */ | 19 | */ |
20 | #include "fseccomp.h" | 20 | #include "fseccomp.h" |
21 | #include "../include/seccomp.h" | 21 | #include "../include/seccomp.h" |
22 | #include <sys/mman.h> | ||
23 | #include <sys/shm.h> | ||
22 | #include <sys/syscall.h> | 24 | #include <sys/syscall.h> |
25 | #include <sys/types.h> | ||
23 | 26 | ||
24 | static void add_default_list(int fd, int allow_debuggers) { | 27 | static void add_default_list(int fd, int allow_debuggers) { |
25 | #ifdef SYS_mount | 28 | #ifdef SYS_mount |
@@ -428,3 +431,54 @@ void seccomp_keep(const char *fname, char *list) { | |||
428 | // close file | 431 | // close file |
429 | close(fd); | 432 | close(fd); |
430 | } | 433 | } |
434 | |||
435 | void memory_deny_write_execute(const char *fname) { | ||
436 | // open file | ||
437 | int fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | ||
438 | if (fd < 0) { | ||
439 | fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname); | ||
440 | exit(1); | ||
441 | } | ||
442 | |||
443 | filter_init(fd); | ||
444 | |||
445 | // build filter | ||
446 | static const struct sock_filter filter[] = { | ||
447 | #ifndef __x86_64__ | ||
448 | // block old multiplexing mmap syscall for i386 | ||
449 | BLACKLIST(SYS_mmap), | ||
450 | #endif | ||
451 | // block mmap(,,x|PROT_WRITE|PROT_EXEC) so W&X memory can't be created | ||
452 | #ifndef __x86_64__ | ||
453 | // mmap2 is used for mmap on i386 these days | ||
454 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_mmap2, 0, 5), | ||
455 | #else | ||
456 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_mmap, 0, 5), | ||
457 | #endif | ||
458 | EXAMINE_ARGUMENT(2), | ||
459 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_WRITE|PROT_EXEC), | ||
460 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_WRITE|PROT_EXEC, 0, 1), | ||
461 | KILL_PROCESS, | ||
462 | RETURN_ALLOW, | ||
463 | // block mprotect(,,PROT_EXEC) so writable memory can't be turned into executable | ||
464 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_mprotect, 0, 5), | ||
465 | EXAMINE_ARGUMENT(2), | ||
466 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC), | ||
467 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1), | ||
468 | KILL_PROCESS, | ||
469 | RETURN_ALLOW, | ||
470 | // block shmat(,,x|SHM_EXEC) so W&X shared memory can't be created | ||
471 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_shmat, 0, 5), | ||
472 | EXAMINE_ARGUMENT(2), | ||
473 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, SHM_EXEC), | ||
474 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SHM_EXEC, 0, 1), | ||
475 | KILL_PROCESS, | ||
476 | RETURN_ALLOW | ||
477 | }; | ||
478 | write_to_file(fd, filter, sizeof(filter)); | ||
479 | |||
480 | filter_end_blacklist(fd); | ||
481 | |||
482 | // close file | ||
483 | close(fd); | ||
484 | } | ||
diff --git a/src/fseccomp/seccomp_file.c b/src/fseccomp/seccomp_file.c index c74de9faf..16ffd5302 100644 --- a/src/fseccomp/seccomp_file.c +++ b/src/fseccomp/seccomp_file.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include "../include/seccomp.h" | 21 | #include "../include/seccomp.h" |
22 | #include <sys/syscall.h> | 22 | #include <sys/syscall.h> |
23 | 23 | ||
24 | static void write_to_file(int fd, void *data, int size) { | 24 | void write_to_file(int fd, const void *data, int size) { |
25 | assert(data); | 25 | assert(data); |
26 | assert(size); | 26 | assert(size); |
27 | 27 | ||
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 0ce72f845..3a5e8560c 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -740,6 +740,12 @@ Example: | |||
740 | $ firejail \-\-machine-id | 740 | $ firejail \-\-machine-id |
741 | 741 | ||
742 | .TP | 742 | .TP |
743 | \fB\-\-memory-deny-write-execute | ||
744 | Install a seccomp filter to block attempts to create memory mappings | ||
745 | that are both writable and executable, to change mappings to be | ||
746 | executable or to create executable shared memory. | ||
747 | |||
748 | .TP | ||
743 | \fB\-\-mtu=number | 749 | \fB\-\-mtu=number |
744 | Assign a MTU value to the last network interface defined by a \-\-net option. | 750 | Assign a MTU value to the last network interface defined by a \-\-net option. |
745 | .br | 751 | .br |