diff options
author | Topi Miettinen <toiwoton@gmail.com> | 2020-03-27 14:22:20 +0200 |
---|---|---|
committer | Topi Miettinen <topimiettinen@users.noreply.github.com> | 2020-04-06 16:30:20 +0000 |
commit | 3f27e8483158e50050f839db343bda7a522f686d (patch) | |
tree | d8dad893d71220ff97aa7744fe7e62900075e521 /src/fseccomp | |
parent | cleanup, fixes, more profstats (diff) | |
download | firejail-3f27e8483158e50050f839db343bda7a522f686d.tar.gz firejail-3f27e8483158e50050f839db343bda7a522f686d.tar.zst firejail-3f27e8483158e50050f839db343bda7a522f686d.zip |
Allow changing error action in seccomp filters
Let user specify the action when seccomp filters trigger:
- errno name like EPERM (default) or ENOSYS: return errno and let the process continue.
- 'kill': kill the process as previous versions
The default action is EPERM, but killing can still be specified with
syscall:kill syntax or globally with seccomp-error-action=kill. The
action can be also overridden /etc/firejail/firejail.config file.
Not killing the process weakens Firejail slightly when trying to
contain intrusion, but it may also allow tighter filters if the
only alternative is to allow a system call.
Diffstat (limited to 'src/fseccomp')
-rw-r--r-- | src/fseccomp/main.c | 13 | ||||
-rw-r--r-- | src/fseccomp/seccomp.c | 20 | ||||
-rw-r--r-- | src/fseccomp/seccomp_file.c | 15 | ||||
-rw-r--r-- | src/fseccomp/seccomp_secondary.c | 2 |
4 files changed, 38 insertions, 12 deletions
diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c index b3161a6db..98e32cdf4 100644 --- a/src/fseccomp/main.c +++ b/src/fseccomp/main.c | |||
@@ -18,7 +18,9 @@ | |||
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 | #include "fseccomp.h" | 20 | #include "fseccomp.h" |
21 | #include "../include/seccomp.h" | ||
21 | int arg_quiet = 0; | 22 | int arg_quiet = 0; |
23 | int arg_seccomp_error_action = EPERM; // error action: errno or kill | ||
22 | 24 | ||
23 | static void usage(void) { | 25 | static void usage(void) { |
24 | printf("Usage:\n"); | 26 | printf("Usage:\n"); |
@@ -67,6 +69,17 @@ printf("\n"); | |||
67 | if (quiet && strcmp(quiet, "yes") == 0) | 69 | if (quiet && strcmp(quiet, "yes") == 0) |
68 | arg_quiet = 1; | 70 | arg_quiet = 1; |
69 | 71 | ||
72 | char *error_action = getenv("FIREJAIL_SECCOMP_ERROR_ACTION"); | ||
73 | if (error_action) | ||
74 | if (strcmp(error_action, "kill") == 0) | ||
75 | arg_seccomp_error_action = SECCOMP_RET_KILL; | ||
76 | else { | ||
77 | arg_seccomp_error_action = errno_find_name(error_action); | ||
78 | if (arg_seccomp_error_action == -1) | ||
79 | errExit("seccomp-error-action: unknown errno"); | ||
80 | arg_seccomp_error_action |= SECCOMP_RET_ERRNO; | ||
81 | } | ||
82 | |||
70 | if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) { | 83 | if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) { |
71 | usage(); | 84 | usage(); |
72 | return 0; | 85 | return 0; |
diff --git a/src/fseccomp/seccomp.c b/src/fseccomp/seccomp.c index 0db7b5954..e808538b0 100644 --- a/src/fseccomp/seccomp.c +++ b/src/fseccomp/seccomp.c | |||
@@ -255,7 +255,7 @@ void memory_deny_write_execute(const char *fname) { | |||
255 | EXAMINE_ARGUMENT(2), | 255 | EXAMINE_ARGUMENT(2), |
256 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_WRITE|PROT_EXEC), | 256 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_WRITE|PROT_EXEC), |
257 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_WRITE|PROT_EXEC, 0, 1), | 257 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_WRITE|PROT_EXEC, 0, 1), |
258 | KILL_PROCESS, | 258 | KILL_OR_RETURN_ERRNO, |
259 | RETURN_ALLOW, | 259 | RETURN_ALLOW, |
260 | #endif | 260 | #endif |
261 | 261 | ||
@@ -264,7 +264,7 @@ void memory_deny_write_execute(const char *fname) { | |||
264 | EXAMINE_ARGUMENT(2), | 264 | EXAMINE_ARGUMENT(2), |
265 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC), | 265 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC), |
266 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1), | 266 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1), |
267 | KILL_PROCESS, | 267 | KILL_OR_RETURN_ERRNO, |
268 | RETURN_ALLOW, | 268 | RETURN_ALLOW, |
269 | 269 | ||
270 | // same for pkey_mprotect(,,PROT_EXEC), where available | 270 | // same for pkey_mprotect(,,PROT_EXEC), where available |
@@ -273,7 +273,7 @@ void memory_deny_write_execute(const char *fname) { | |||
273 | EXAMINE_ARGUMENT(2), | 273 | EXAMINE_ARGUMENT(2), |
274 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC), | 274 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC), |
275 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1), | 275 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1), |
276 | KILL_PROCESS, | 276 | KILL_OR_RETURN_ERRNO, |
277 | RETURN_ALLOW, | 277 | RETURN_ALLOW, |
278 | #endif | 278 | #endif |
279 | 279 | ||
@@ -284,7 +284,7 @@ void memory_deny_write_execute(const char *fname) { | |||
284 | EXAMINE_ARGUMENT(2), | 284 | EXAMINE_ARGUMENT(2), |
285 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, SHM_EXEC), | 285 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, SHM_EXEC), |
286 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SHM_EXEC, 0, 1), | 286 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SHM_EXEC, 0, 1), |
287 | KILL_PROCESS, | 287 | KILL_OR_RETURN_ERRNO, |
288 | RETURN_ALLOW, | 288 | RETURN_ALLOW, |
289 | #endif | 289 | #endif |
290 | #ifdef SYS_memfd_create | 290 | #ifdef SYS_memfd_create |
@@ -292,7 +292,7 @@ void memory_deny_write_execute(const char *fname) { | |||
292 | // arbitrary memory contents which can be later mapped | 292 | // arbitrary memory contents which can be later mapped |
293 | // as executable | 293 | // as executable |
294 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_memfd_create, 0, 1), | 294 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_memfd_create, 0, 1), |
295 | KILL_PROCESS, | 295 | KILL_OR_RETURN_ERRNO, |
296 | RETURN_ALLOW | 296 | RETURN_ALLOW |
297 | #endif | 297 | #endif |
298 | }; | 298 | }; |
@@ -327,7 +327,7 @@ void memory_deny_write_execute_32(const char *fname) { | |||
327 | EXAMINE_ARGUMENT(2), | 327 | EXAMINE_ARGUMENT(2), |
328 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_WRITE|PROT_EXEC), | 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), | 329 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_WRITE|PROT_EXEC, 0, 1), |
330 | KILL_PROCESS, | 330 | KILL_OR_RETURN_ERRNO, |
331 | RETURN_ALLOW, | 331 | RETURN_ALLOW, |
332 | #endif | 332 | #endif |
333 | #ifdef mprotect_32 | 333 | #ifdef mprotect_32 |
@@ -336,7 +336,7 @@ void memory_deny_write_execute_32(const char *fname) { | |||
336 | EXAMINE_ARGUMENT(2), | 336 | EXAMINE_ARGUMENT(2), |
337 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC), | 337 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC), |
338 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1), | 338 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1), |
339 | KILL_PROCESS, | 339 | KILL_OR_RETURN_ERRNO, |
340 | RETURN_ALLOW, | 340 | RETURN_ALLOW, |
341 | #endif | 341 | #endif |
342 | #ifdef pkey_mprotect_32 | 342 | #ifdef pkey_mprotect_32 |
@@ -345,7 +345,7 @@ void memory_deny_write_execute_32(const char *fname) { | |||
345 | EXAMINE_ARGUMENT(2), | 345 | EXAMINE_ARGUMENT(2), |
346 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC), | 346 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, PROT_EXEC), |
347 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1), | 347 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, PROT_EXEC, 0, 1), |
348 | KILL_PROCESS, | 348 | KILL_OR_RETURN_ERRNO, |
349 | RETURN_ALLOW, | 349 | RETURN_ALLOW, |
350 | #endif | 350 | #endif |
351 | 351 | ||
@@ -355,7 +355,7 @@ void memory_deny_write_execute_32(const char *fname) { | |||
355 | EXAMINE_ARGUMENT(2), | 355 | EXAMINE_ARGUMENT(2), |
356 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, SHM_EXEC), | 356 | BPF_STMT(BPF_ALU+BPF_AND+BPF_K, SHM_EXEC), |
357 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SHM_EXEC, 0, 1), | 357 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SHM_EXEC, 0, 1), |
358 | KILL_PROCESS, | 358 | KILL_OR_RETURN_ERRNO, |
359 | RETURN_ALLOW, | 359 | RETURN_ALLOW, |
360 | #endif | 360 | #endif |
361 | #ifdef memfd_create_32 | 361 | #ifdef memfd_create_32 |
@@ -363,7 +363,7 @@ void memory_deny_write_execute_32(const char *fname) { | |||
363 | // arbitrary memory contents which can be later mapped | 363 | // arbitrary memory contents which can be later mapped |
364 | // as executable | 364 | // as executable |
365 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, memfd_create_32, 0, 1), | 365 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, memfd_create_32, 0, 1), |
366 | KILL_PROCESS, | 366 | KILL_OR_RETURN_ERRNO, |
367 | #endif | 367 | #endif |
368 | #endif | 368 | #endif |
369 | RETURN_ALLOW | 369 | RETURN_ALLOW |
diff --git a/src/fseccomp/seccomp_file.c b/src/fseccomp/seccomp_file.c index 872b41261..9e8ceb898 100644 --- a/src/fseccomp/seccomp_file.c +++ b/src/fseccomp/seccomp_file.c | |||
@@ -112,6 +112,19 @@ void filter_add_blacklist(int fd, int syscall, int arg, void *ptrarg, bool nativ | |||
112 | } | 112 | } |
113 | } | 113 | } |
114 | 114 | ||
115 | void filter_add_blacklist_override(int fd, int syscall, int arg, void *ptrarg, bool native) { | ||
116 | (void) arg; | ||
117 | (void) ptrarg; | ||
118 | (void) native; | ||
119 | |||
120 | if (syscall >= 0) { | ||
121 | int saved_error_action = arg_seccomp_error_action; | ||
122 | arg_seccomp_error_action = SECCOMP_RET_KILL; | ||
123 | write_blacklist(fd, syscall); | ||
124 | arg_seccomp_error_action = saved_error_action; | ||
125 | } | ||
126 | } | ||
127 | |||
115 | // handle seccomp list exceptions (seccomp x,y,!z) | 128 | // handle seccomp list exceptions (seccomp x,y,!z) |
116 | void filter_add_blacklist_for_excluded(int fd, int syscall, int arg, void *ptrarg, bool native) { | 129 | void filter_add_blacklist_for_excluded(int fd, int syscall, int arg, void *ptrarg, bool native) { |
117 | (void) arg; | 130 | (void) arg; |
@@ -142,7 +155,7 @@ void filter_end_blacklist(int fd) { | |||
142 | 155 | ||
143 | void filter_end_whitelist(int fd) { | 156 | void filter_end_whitelist(int fd) { |
144 | struct sock_filter filter[] = { | 157 | struct sock_filter filter[] = { |
145 | KILL_PROCESS | 158 | KILL_OR_RETURN_ERRNO |
146 | }; | 159 | }; |
147 | write_to_file(fd, filter, sizeof(filter)); | 160 | write_to_file(fd, filter, sizeof(filter)); |
148 | } | 161 | } |
diff --git a/src/fseccomp/seccomp_secondary.c b/src/fseccomp/seccomp_secondary.c index 9a00d1884..f024859d3 100644 --- a/src/fseccomp/seccomp_secondary.c +++ b/src/fseccomp/seccomp_secondary.c | |||
@@ -142,7 +142,7 @@ void seccomp_secondary_block(const char *fname) { | |||
142 | // 5: if MSW(arg0) == 0, goto 7 (allow) else continue to 6 (kill) | 142 | // 5: if MSW(arg0) == 0, goto 7 (allow) else continue to 6 (kill) |
143 | BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, jmp_from_to(5, 7), 0), | 143 | BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, jmp_from_to(5, 7), 0), |
144 | // 6: | 144 | // 6: |
145 | KILL_PROCESS, | 145 | KILL_OR_RETURN_ERRNO, |
146 | // 7: | 146 | // 7: |
147 | RETURN_ALLOW | 147 | RETURN_ALLOW |
148 | }; | 148 | }; |