aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Topi Miettinen <toiwoton@gmail.com>2017-07-29 19:53:27 +0300
committerLibravatar Topi Miettinen <topimiettinen@users.noreply.github.com>2017-07-30 16:48:16 +0000
commit53606495188a5cc16ea67e3b65561127a98925b3 (patch)
tree554c6e90c785ae015f8d784b593d9cdf75fde315 /src
parentImprove loading of seccomp filter (diff)
downloadfirejail-53606495188a5cc16ea67e3b65561127a98925b3.tar.gz
firejail-53606495188a5cc16ea67e3b65561127a98925b3.tar.zst
firejail-53606495188a5cc16ea67e3b65561127a98925b3.zip
Memory-deny-write-execute feature
Feature to block attempts to create writable and executable memory.
Diffstat (limited to 'src')
-rw-r--r--src/firejail/firejail.h3
-rw-r--r--src/firejail/main.c7
-rw-r--r--src/firejail/preproc.c2
-rw-r--r--src/firejail/profile.c11
-rw-r--r--src/firejail/sandbox.c5
-rw-r--r--src/fseccomp/fseccomp.h3
-rw-r--r--src/fseccomp/main.c3
-rw-r--r--src/fseccomp/seccomp.c54
-rw-r--r--src/fseccomp/seccomp_file.c2
-rw-r--r--src/man/firejail.txt6
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
355extern int arg_machineid; // preserve /etc/machine-id 357extern int arg_machineid; // preserve /etc/machine-id
356extern int arg_disable_mnt; // disable /mnt and /media 358extern int arg_disable_mnt; // disable /mnt and /media
357extern int arg_noprofile; // use default.profile if none other found/specified 359extern int arg_noprofile; // use default.profile if none other found/specified
360extern int arg_memory_deny_write_execute; // block writable and executable memory
358 361
359extern int login_shell; 362extern int login_shell;
360extern int parent_to_child_fds[2]; 363extern 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
111int arg_writable_var_log = 0; // writable /var/log 111int arg_writable_var_log = 0; // writable /var/log
112int arg_disable_mnt = 0; // disable /mnt and /media 112int arg_disable_mnt = 0; // disable /mnt and /media
113int arg_noprofile = 0; // use default.profile if none other found/specified 113int arg_noprofile = 0; // use default.profile if none other found/specified
114int arg_memory_deny_write_execute = 0; // block writable and executable memory
114 115
115int login_shell = 0; 116int 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);
48void seccomp_secondary_32(const char *fname); 48void seccomp_secondary_32(const char *fname);
49 49
50// seccomp_file.c 50// seccomp_file.c
51void write_to_file(int fd, const void *data, int size);
51void filter_init(int fd); 52void filter_init(int fd);
52void filter_add_whitelist(int fd, int syscall, int arg); 53void filter_add_whitelist(int fd, int syscall, int arg);
53void filter_add_blacklist(int fd, int syscall, int arg); 54void filter_add_blacklist(int fd, int syscall, int arg);
@@ -64,6 +65,8 @@ void seccomp_drop(const char *fname, char *list, int allow_debuggers);
64void seccomp_default_drop(const char *fname, char *list, int allow_debuggers); 65void seccomp_default_drop(const char *fname, char *list, int allow_debuggers);
65// whitelisted filter 66// whitelisted filter
66void seccomp_keep(const char *fname, char *list); 67void seccomp_keep(const char *fname, char *list);
68// block writable and executable memory
69void memory_deny_write_execute(const char *fname);
67 70
68// seccomp_print 71// seccomp_print
69void filter_print(const char *fname); 72void 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
24static void add_default_list(int fd, int allow_debuggers) { 27static 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
435void 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
24static void write_to_file(int fd, void *data, int size) { 24void 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
744Install a seccomp filter to block attempts to create memory mappings
745that are both writable and executable, to change mappings to be
746executable or to create executable shared memory.
747
748.TP
743\fB\-\-mtu=number 749\fB\-\-mtu=number
744Assign a MTU value to the last network interface defined by a \-\-net option. 750Assign a MTU value to the last network interface defined by a \-\-net option.
745.br 751.br