aboutsummaryrefslogtreecommitdiffstats
path: root/src/fseccomp
diff options
context:
space:
mode:
authorLibravatar Topi Miettinen <toiwoton@gmail.com>2017-08-19 23:22:38 +0300
committerLibravatar Topi Miettinen <toiwoton@gmail.com>2017-08-19 23:33:11 +0300
commitd01216de45884300c87e7d3ccb70e53ebb461449 (patch)
tree480519f5849df4c6048a7f62ec97f96e51174c3e /src/fseccomp
parentMerge update after #1483 (diff)
downloadfirejail-d01216de45884300c87e7d3ccb70e53ebb461449.tar.gz
firejail-d01216de45884300c87e7d3ccb70e53ebb461449.tar.zst
firejail-d01216de45884300c87e7d3ccb70e53ebb461449.zip
Feature: switch/config option to block secondary architectures
Add a feature for a new (opt-in) command line switch and config file option to block secondary architectures entirely. Also block changing Linux execution domain with personality() system call for the primary architecture. Closes #1479
Diffstat (limited to 'src/fseccomp')
-rw-r--r--src/fseccomp/fseccomp.h1
-rw-r--r--src/fseccomp/main.c3
-rw-r--r--src/fseccomp/seccomp_print.c19
-rw-r--r--src/fseccomp/seccomp_secondary.c97
4 files changed, 87 insertions, 33 deletions
diff --git a/src/fseccomp/fseccomp.h b/src/fseccomp/fseccomp.h
index 144b612ae..2deb282f5 100644
--- a/src/fseccomp/fseccomp.h
+++ b/src/fseccomp/fseccomp.h
@@ -46,6 +46,7 @@ void protocol_build_filter(const char *prlist, const char *fname);
46// seccomp_secondary.c 46// seccomp_secondary.c
47void seccomp_secondary_64(const char *fname); 47void seccomp_secondary_64(const char *fname);
48void seccomp_secondary_32(const char *fname); 48void seccomp_secondary_32(const char *fname);
49void seccomp_secondary_block(const char *fname);
49 50
50// seccomp_file.c 51// seccomp_file.c
51void write_to_file(int fd, const void *data, int size); 52void write_to_file(int fd, const void *data, int size);
diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c
index 3bf7de0fa..ae0ae64ef 100644
--- a/src/fseccomp/main.c
+++ b/src/fseccomp/main.c
@@ -28,6 +28,7 @@ static void usage(void) {
28 printf("\tfseccomp protocol build list file\n"); 28 printf("\tfseccomp protocol build list file\n");
29 printf("\tfseccomp secondary 64 file\n"); 29 printf("\tfseccomp secondary 64 file\n");
30 printf("\tfseccomp secondary 32 file\n"); 30 printf("\tfseccomp secondary 32 file\n");
31 printf("\tfseccomp secondary block file\n");
31 printf("\tfseccomp default file\n"); 32 printf("\tfseccomp default file\n");
32 printf("\tfseccomp default file allow-debuggers\n"); 33 printf("\tfseccomp default file allow-debuggers\n");
33 printf("\tfseccomp drop file1 file2 list\n"); 34 printf("\tfseccomp drop file1 file2 list\n");
@@ -74,6 +75,8 @@ printf("\n");
74 seccomp_secondary_64(argv[3]); 75 seccomp_secondary_64(argv[3]);
75 else if (argc == 4 && strcmp(argv[1], "secondary") == 0 && strcmp(argv[2], "32") == 0) 76 else if (argc == 4 && strcmp(argv[1], "secondary") == 0 && strcmp(argv[2], "32") == 0)
76 seccomp_secondary_32(argv[3]); 77 seccomp_secondary_32(argv[3]);
78 else if (argc == 4 && strcmp(argv[1], "secondary") == 0 && strcmp(argv[2], "block") == 0)
79 seccomp_secondary_block(argv[3]);
77 else if (argc == 3 && strcmp(argv[1], "default") == 0) 80 else if (argc == 3 && strcmp(argv[1], "default") == 0)
78 seccomp_default(argv[2], 0); 81 seccomp_default(argv[2], 0);
79 else if (argc == 4 && strcmp(argv[1], "default") == 0 && strcmp(argv[3], "allow-debuggers") == 0) 82 else if (argc == 4 && strcmp(argv[1], "default") == 0 && strcmp(argv[3], "allow-debuggers") == 0)
diff --git a/src/fseccomp/seccomp_print.c b/src/fseccomp/seccomp_print.c
index 19fe7a545..7af95d51c 100644
--- a/src/fseccomp/seccomp_print.c
+++ b/src/fseccomp/seccomp_print.c
@@ -113,6 +113,25 @@ static int detect_filter_type(void) {
113 printf(" EXAMINE_SYSCALL\n"); 113 printf(" EXAMINE_SYSCALL\n");
114 return sizeof(start_secondary_32) / sizeof(struct sock_filter); 114 return sizeof(start_secondary_32) / sizeof(struct sock_filter);
115 } 115 }
116
117 const struct sock_filter start_secondary_block[] = {
118 VALIDATE_ARCHITECTURE_KILL,
119#if defined(__x86_64__)
120 EXAMINE_SYSCALL,
121 HANDLE_X32_KILL,
122#else
123 EXAMINE_SYSCALL
124#endif
125 };
126
127 if (memcmp(&start_secondary_block[0], filter, sizeof(start_secondary_block)) == 0) {
128 printf(" VALIDATE_ARCHITECTURE_KILL\n");
129 printf(" EXAMINE_SYSCALL\n");
130#if defined(__x86_64__)
131 printf(" HANDLE_X32_KILL\n");
132#endif
133 return sizeof(start_secondary_block) / sizeof(struct sock_filter);
134 }
116 135
117 return 0; // filter unrecognized 136 return 0; // filter unrecognized
118} 137}
diff --git a/src/fseccomp/seccomp_secondary.c b/src/fseccomp/seccomp_secondary.c
index fceb2c3ec..dd69b58cc 100644
--- a/src/fseccomp/seccomp_secondary.c
+++ b/src/fseccomp/seccomp_secondary.c
@@ -19,8 +19,29 @@
19*/ 19*/
20#include "fseccomp.h" 20#include "fseccomp.h"
21#include "../include/seccomp.h" 21#include "../include/seccomp.h"
22#include <sys/personality.h>
22#include <sys/syscall.h> 23#include <sys/syscall.h>
23 24
25static void write_filter(const char *fname, size_t size, const void *filter) {
26 // save filter to file
27 int dst = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
28 if (dst < 0) {
29 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname);
30 exit(1);
31 }
32
33 size_t written = 0;
34 while (written < size) {
35 ssize_t rv = write(dst, (unsigned char *) filter + written, size - written);
36 if (rv == -1) {
37 fprintf(stderr, "Error fseccomp: cannot write %s file\n", fname);
38 exit(1);
39 }
40 written += rv;
41 }
42 close(dst);
43}
44
24void seccomp_secondary_64(const char *fname) { 45void seccomp_secondary_64(const char *fname) {
25 // hardcoded syscall values 46 // hardcoded syscall values
26 struct sock_filter filter[] = { 47 struct sock_filter filter[] = {
@@ -84,23 +105,7 @@ void seccomp_secondary_64(const char *fname) {
84 }; 105 };
85 106
86 // save filter to file 107 // save filter to file
87 int dst = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 108 write_filter(fname, sizeof(filter), filter);
88 if (dst < 0) {
89 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname);
90 exit(1);
91 }
92
93 int size = (int) sizeof(filter);
94 int written = 0;
95 while (written < size) {
96 int rv = write(dst, (unsigned char *) filter + written, size - written);
97 if (rv == -1) {
98 fprintf(stderr, "Error fseccomp: cannot write %s file\n", fname);
99 exit(1);
100 }
101 written += rv;
102 }
103 close(dst);
104} 109}
105 110
106// i386 filter installed on amd64 architectures 111// i386 filter installed on amd64 architectures
@@ -166,21 +171,47 @@ void seccomp_secondary_32(const char *fname) {
166 }; 171 };
167 172
168 // save filter to file 173 // save filter to file
169 int dst = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 174 write_filter(fname, sizeof(filter), filter);
170 if (dst < 0) { 175}
171 fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname);
172 exit(1);
173 }
174 176
175 int size = (int) sizeof(filter); 177#define jmp_from_to(from_addr, to_addr) ((to_addr) - (from_addr) - 1)
176 int written = 0; 178
177 while (written < size) { 179#if __BYTE_ORDER == __BIG_ENDIAN
178 int rv = write(dst, (unsigned char *) filter + written, size - written); 180#define MSW 0
179 if (rv == -1) { 181#define LSW (sizeof(int))
180 fprintf(stderr, "Error fseccomp: cannot write %s file\n", fname); 182#else
181 exit(1); 183#define MSW (sizeof(int))
182 } 184#define LSW 0
183 written += rv; 185#endif
184 } 186
185 close(dst); 187void seccomp_secondary_block(const char *fname) {
188 struct sock_filter filter[] = {
189 // block other architectures
190 VALIDATE_ARCHITECTURE_KILL,
191 EXAMINE_SYSCALL,
192#if defined(__x86_64__)
193 // block x32
194 HANDLE_X32_KILL,
195#endif
196 // block personality(2) where domain != PER_LINUX or 0xffffffff (query current personality)
197 // 0: if personality(2), continue to 1, else goto 7 (allow)
198 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYS_personality, 0, jmp_from_to(0, 7)),
199 // 1: get LSW of system call argument 0
200 BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, args[0])) + LSW),
201 // 2: if LSW(arg0) == PER_LINUX, goto step 4, else continue to 3
202 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, PER_LINUX, jmp_from_to(2, 4), 0),
203 // 3: if LSW(arg0) == 0xffffffff, continue to 4, else goto 6 (kill)
204 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0xffffffff, 0, jmp_from_to(3, 6)),
205 // 4: get MSW of system call argument 0
206 BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, args[0])) + MSW),
207 // 5: if MSW(arg0) == 0, goto 7 (allow) else continue to 6 (kill)
208 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, jmp_from_to(5, 7), 0),
209 // 6:
210 KILL_PROCESS,
211 // 7:
212 RETURN_ALLOW
213 };
214
215 // save filter to file
216 write_filter(fname, sizeof(filter), filter);
186} 217}