aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--lib-src/Makefile.in7
-rw-r--r--lib-src/seccomp-filter.c39
l---------test/src/emacs-resources/seccomp-filter-exec.bpf1
-rw-r--r--test/src/emacs-tests.el33
5 files changed, 75 insertions, 7 deletions
diff --git a/.gitignore b/.gitignore
index ecf768dc4d6..a1e3cb92f87 100644
--- a/.gitignore
+++ b/.gitignore
@@ -306,3 +306,5 @@ src/gdb.ini
306# Seccomp filter files. 306# Seccomp filter files.
307lib-src/seccomp-filter.bpf 307lib-src/seccomp-filter.bpf
308lib-src/seccomp-filter.pfc 308lib-src/seccomp-filter.pfc
309lib-src/seccomp-filter-exec.bpf
310lib-src/seccomp-filter-exec.pfc
diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in
index 35cfa56d8be..091f4fb0199 100644
--- a/lib-src/Makefile.in
+++ b/lib-src/Makefile.in
@@ -240,7 +240,7 @@ config_h = ../src/config.h $(srcdir)/../src/conf_post.h
240all: ${EXE_FILES} ${SCRIPTS} 240all: ${EXE_FILES} ${SCRIPTS}
241 241
242ifeq ($(SECCOMP_FILTER),1) 242ifeq ($(SECCOMP_FILTER),1)
243all: seccomp-filter.bpf 243all: seccomp-filter.bpf seccomp-filter-exec.bpf
244endif 244endif
245 245
246.PHONY: all need-blessmail maybe-blessmail 246.PHONY: all need-blessmail maybe-blessmail
@@ -430,9 +430,10 @@ seccomp-filter$(EXEEXT): $(srcdir)/seccomp-filter.c $(config_h)
430 $(AM_V_CCLD)$(CC) $(ALL_CFLAGS) $(LIBSECCOMP_CFLAGS) $< \ 430 $(AM_V_CCLD)$(CC) $(ALL_CFLAGS) $(LIBSECCOMP_CFLAGS) $< \
431 $(LIBSECCOMP_LIBS) -o $@ 431 $(LIBSECCOMP_LIBS) -o $@
432 432
433seccomp-filter.bpf seccomp-filter.pfc: seccomp-filter$(EXEEXT) 433seccomp-filter.bpf seccomp-filter.pfc seccomp-filter-exec.bpf seccomp-filter-exec.pfc: seccomp-filter$(EXEEXT)
434 $(AM_V_GEN)./seccomp-filter$(EXEEXT) \ 434 $(AM_V_GEN)./seccomp-filter$(EXEEXT) \
435 seccomp-filter.bpf seccomp-filter.pfc 435 seccomp-filter.bpf seccomp-filter.pfc \
436 seccomp-filter-exec.bpf seccomp-filter-exec.pfc
436endif 437endif
437 438
438## Makefile ends here. 439## Makefile ends here.
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
27Usage: 27Usage:
28 28
29 seccomp-filter out.bpf out.pfc 29 seccomp-filter out.bpf out.pfc out-exec.bpf out-exec.pfc
30 30
31This writes the raw `struct sock_filter' array to out.bpf and a 31This writes the raw `struct sock_filter' array to out.bpf and a
32human-readable representation to out.pfc. */ 32human-readable representation to out.pfc. Additionally, it writes
33variants 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,
139int 142int
140main (int argc, char **argv) 143main (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}
diff --git a/test/src/emacs-resources/seccomp-filter-exec.bpf b/test/src/emacs-resources/seccomp-filter-exec.bpf
new file mode 120000
index 00000000000..5b0e9978221
--- /dev/null
+++ b/test/src/emacs-resources/seccomp-filter-exec.bpf
@@ -0,0 +1 @@
../../../lib-src/seccomp-filter-exec.bpf \ No newline at end of file
diff --git a/test/src/emacs-tests.el b/test/src/emacs-tests.el
index 89d811f8b4e..09f9a248efb 100644
--- a/test/src/emacs-tests.el
+++ b/test/src/emacs-tests.el
@@ -177,4 +177,37 @@ to `make-temp-file', which see."
177 (ert-info ((format "Process output: %s" (buffer-string))) 177 (ert-info ((format "Process output: %s" (buffer-string)))
178 (should-not (eql status 0))))))) 178 (should-not (eql status 0)))))))
179 179
180(ert-deftest emacs-tests/bwrap/allows-stdout ()
181 (let ((bash (executable-find "bash"))
182 (bwrap (executable-find "bwrap"))
183 (emacs
184 (expand-file-name invocation-name invocation-directory))
185 (filter (ert-resource-file "seccomp-filter-exec.bpf"))
186 (process-environment nil))
187 (skip-unless bash)
188 (skip-unless bwrap)
189 (skip-unless (file-executable-p emacs))
190 (skip-unless (file-readable-p filter))
191 (should-not (file-remote-p bwrap))
192 (should-not (file-remote-p emacs))
193 (should-not (file-remote-p filter))
194 (with-temp-buffer
195 (let* ((command
196 (concat
197 (mapconcat #'shell-quote-argument
198 `(,(file-name-unquote bwrap)
199 "--ro-bind" "/" "/"
200 "--seccomp" "20"
201 "--"
202 ,(file-name-unquote emacs)
203 "--quick" "--batch"
204 ,(format "--eval=%S" '(message "Hi")))
205 " ")
206 " 20< "
207 (shell-quote-argument (file-name-unquote filter))))
208 (status (call-process bash nil t nil "-c" command)))
209 (ert-info ((format "Process output: %s" (buffer-string)))
210 (should (eql status 0)))
211 (should (equal (string-trim (buffer-string)) "Hi"))))))
212
180;;; emacs-tests.el ends here 213;;; emacs-tests.el ends here