diff options
| author | Philipp Stephani | 2021-04-11 19:47:36 +0200 |
|---|---|---|
| committer | Philipp Stephani | 2021-04-11 21:19:09 +0200 |
| commit | c8d542fd593f06b85d4b7b712378a4f84ec4d2b3 (patch) | |
| tree | c2368357e6a417f4d7441e8eec13ee1ffc71b2d2 /lib-src/seccomp-filter.c | |
| parent | cf0701eff0f3b06e0324be07f7810cbaf261f7f3 (diff) | |
| download | emacs-c8d542fd593f06b85d4b7b712378a4f84ec4d2b3.tar.gz emacs-c8d542fd593f06b85d4b7b712378a4f84ec4d2b3.zip | |
Add a variant of the Seccomp filter file that allows 'execve'.
This is useful when starting Emacs with a Seccomp filter enabled,
e.g. using 'bwrap'.
* lib-src/seccomp-filter.c (main): Generate new Seccomp files.
* lib-src/Makefile.in (all)
(seccomp-filter.bpf seccomp-filter.pfc seccomp-filter-exec.bpf
seccomp-filter-exec.pfc): Generate new Seccomp files.
* .gitignore: Ignore new Seccomp files.
* test/src/emacs-tests.el (emacs-tests/bwrap/allows-stdout): New unit
test.
Diffstat (limited to 'lib-src/seccomp-filter.c')
| -rw-r--r-- | lib-src/seccomp-filter.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/lib-src/seccomp-filter.c b/lib-src/seccomp-filter.c index a5f2e0adbca..ed362bc18d9 100644 --- a/lib-src/seccomp-filter.c +++ b/lib-src/seccomp-filter.c | |||
| @@ -26,10 +26,12 @@ only a Linux kernel supporting the Secure Computing extension. | |||
| 26 | 26 | ||
| 27 | Usage: | 27 | Usage: |
| 28 | 28 | ||
| 29 | seccomp-filter out.bpf out.pfc | 29 | seccomp-filter out.bpf out.pfc out-exec.bpf out-exec.pfc |
| 30 | 30 | ||
| 31 | This writes the raw `struct sock_filter' array to out.bpf and a | 31 | This writes the raw `struct sock_filter' array to out.bpf and a |
| 32 | human-readable representation to out.pfc. */ | 32 | human-readable representation to out.pfc. Additionally, it writes |
| 33 | variants of those files that can be used to sandbox Emacs before | ||
| 34 | 'execve' to out-exec.bpf and out-exec.pfc. */ | ||
| 33 | 35 | ||
| 34 | #include "config.h" | 36 | #include "config.h" |
| 35 | 37 | ||
| @@ -42,6 +44,7 @@ human-readable representation to out.pfc. */ | |||
| 42 | #include <stdio.h> | 44 | #include <stdio.h> |
| 43 | #include <time.h> | 45 | #include <time.h> |
| 44 | 46 | ||
| 47 | #include <asm/prctl.h> | ||
| 45 | #include <sys/ioctl.h> | 48 | #include <sys/ioctl.h> |
| 46 | #include <sys/mman.h> | 49 | #include <sys/mman.h> |
| 47 | #include <sys/prctl.h> | 50 | #include <sys/prctl.h> |
| @@ -139,8 +142,9 @@ export_filter (const char *file, | |||
| 139 | int | 142 | int |
| 140 | main (int argc, char **argv) | 143 | main (int argc, char **argv) |
| 141 | { | 144 | { |
| 142 | if (argc != 3) | 145 | if (argc != 5) |
| 143 | fail (0, "usage: %s out.bpf out.pfc", argv[0]); | 146 | fail (0, "usage: %s out.bpf out.pfc out-exec.bpf out-exec.pfc", |
| 147 | argv[0]); | ||
| 144 | 148 | ||
| 145 | /* Any unhandled syscall should abort the Emacs process. */ | 149 | /* Any unhandled syscall should abort the Emacs process. */ |
| 146 | ctx = seccomp_init (SCMP_ACT_KILL_PROCESS); | 150 | ctx = seccomp_init (SCMP_ACT_KILL_PROCESS); |
| @@ -156,6 +160,8 @@ main (int argc, char **argv) | |||
| 156 | verify (CHAR_BIT == 8); | 160 | verify (CHAR_BIT == 8); |
| 157 | verify (sizeof (int) == 4 && INT_MIN == INT32_MIN | 161 | verify (sizeof (int) == 4 && INT_MIN == INT32_MIN |
| 158 | && INT_MAX == INT32_MAX); | 162 | && INT_MAX == INT32_MAX); |
| 163 | verify (sizeof (long) == 8 && LONG_MIN == INT64_MIN | ||
| 164 | && LONG_MAX == INT64_MAX); | ||
| 159 | verify (sizeof (void *) == 8); | 165 | verify (sizeof (void *) == 8); |
| 160 | verify ((uintptr_t) NULL == 0); | 166 | verify ((uintptr_t) NULL == 0); |
| 161 | 167 | ||
| @@ -327,4 +333,29 @@ main (int argc, char **argv) | |||
| 327 | 333 | ||
| 328 | EXPORT_FILTER (argv[1], seccomp_export_bpf); | 334 | EXPORT_FILTER (argv[1], seccomp_export_bpf); |
| 329 | EXPORT_FILTER (argv[2], seccomp_export_pfc); | 335 | EXPORT_FILTER (argv[2], seccomp_export_pfc); |
| 336 | |||
| 337 | /* When applying a Seccomp filter before executing the Emacs binary | ||
| 338 | (e.g. using the `bwrap' program), we need to allow further system | ||
| 339 | calls. Firstly, the wrapper binary will need to `execve' the | ||
| 340 | Emacs binary. Furthermore, the C library requires some system | ||
| 341 | calls at startup time to set up thread-local storage. */ | ||
| 342 | RULE (SCMP_ACT_ALLOW, SCMP_SYS (execve)); | ||
| 343 | RULE (SCMP_ACT_ALLOW, SCMP_SYS (set_tid_address)); | ||
| 344 | RULE (SCMP_ACT_ALLOW, SCMP_SYS (arch_prctl), | ||
| 345 | SCMP_A0_32 (SCMP_CMP_EQ, ARCH_SET_FS)); | ||
| 346 | RULE (SCMP_ACT_ALLOW, SCMP_SYS (statfs)); | ||
| 347 | |||
| 348 | /* We want to allow starting the Emacs binary itself with the | ||
| 349 | --seccomp flag, so we need to allow the `prctl' and `seccomp' | ||
| 350 | system calls. */ | ||
| 351 | RULE (SCMP_ACT_ALLOW, SCMP_SYS (prctl), | ||
| 352 | SCMP_A0_32 (SCMP_CMP_EQ, PR_SET_NO_NEW_PRIVS), | ||
| 353 | SCMP_A1_64 (SCMP_CMP_EQ, 1), SCMP_A2_64 (SCMP_CMP_EQ, 0), | ||
| 354 | SCMP_A3_64 (SCMP_CMP_EQ, 0), SCMP_A4_64 (SCMP_CMP_EQ, 0)); | ||
| 355 | RULE (SCMP_ACT_ALLOW, SCMP_SYS (seccomp), | ||
| 356 | SCMP_A0_32 (SCMP_CMP_EQ, SECCOMP_SET_MODE_FILTER), | ||
| 357 | SCMP_A1_32 (SCMP_CMP_EQ, SECCOMP_FILTER_FLAG_TSYNC)); | ||
| 358 | |||
| 359 | EXPORT_FILTER (argv[3], seccomp_export_bpf); | ||
| 360 | EXPORT_FILTER (argv[4], seccomp_export_pfc); | ||
| 330 | } | 361 | } |