emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master c8d542f 2/2: Add a variant of the Seccomp filter file that allows


From: Philipp Stephani
Subject: master c8d542f 2/2: Add a variant of the Seccomp filter file that allows 'execve'.
Date: Sun, 11 Apr 2021 15:19:27 -0400 (EDT)

branch: master
commit c8d542fd593f06b85d4b7b712378a4f84ec4d2b3
Author: Philipp Stephani <phst@google.com>
Commit: Philipp Stephani <phst@google.com>

    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.
---
 .gitignore                                       |  2 ++
 lib-src/Makefile.in                              |  7 +++--
 lib-src/seccomp-filter.c                         | 39 +++++++++++++++++++++---
 test/src/emacs-resources/seccomp-filter-exec.bpf |  1 +
 test/src/emacs-tests.el                          | 33 ++++++++++++++++++++
 5 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/.gitignore b/.gitignore
index ecf768d..a1e3cb9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -306,3 +306,5 @@ src/gdb.ini
 # Seccomp filter files.
 lib-src/seccomp-filter.bpf
 lib-src/seccomp-filter.pfc
+lib-src/seccomp-filter-exec.bpf
+lib-src/seccomp-filter-exec.pfc
diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in
index 35cfa56..091f4fb 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
 all: ${EXE_FILES} ${SCRIPTS}
 
 ifeq ($(SECCOMP_FILTER),1)
-all: seccomp-filter.bpf
+all: seccomp-filter.bpf seccomp-filter-exec.bpf
 endif
 
 .PHONY: all need-blessmail maybe-blessmail
@@ -430,9 +430,10 @@ seccomp-filter$(EXEEXT): $(srcdir)/seccomp-filter.c 
$(config_h)
        $(AM_V_CCLD)$(CC) $(ALL_CFLAGS) $(LIBSECCOMP_CFLAGS) $< \
          $(LIBSECCOMP_LIBS) -o $@
 
-seccomp-filter.bpf seccomp-filter.pfc: seccomp-filter$(EXEEXT)
+seccomp-filter.bpf seccomp-filter.pfc seccomp-filter-exec.bpf 
seccomp-filter-exec.pfc: seccomp-filter$(EXEEXT)
        $(AM_V_GEN)./seccomp-filter$(EXEEXT) \
-         seccomp-filter.bpf seccomp-filter.pfc
+         seccomp-filter.bpf seccomp-filter.pfc \
+         seccomp-filter-exec.bpf seccomp-filter-exec.pfc
 endif
 
 ## Makefile ends here.
diff --git a/lib-src/seccomp-filter.c b/lib-src/seccomp-filter.c
index a5f2e0a..ed362bc 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.
 
 Usage:
 
-  seccomp-filter out.bpf out.pfc
+  seccomp-filter out.bpf out.pfc out-exec.bpf out-exec.pfc
 
 This writes the raw `struct sock_filter' array to out.bpf and a
-human-readable representation to out.pfc.  */
+human-readable representation to out.pfc.  Additionally, it writes
+variants of those files that can be used to sandbox Emacs before
+'execve' to out-exec.bpf and out-exec.pfc.  */
 
 #include "config.h"
 
@@ -42,6 +44,7 @@ human-readable representation to out.pfc.  */
 #include <stdio.h>
 #include <time.h>
 
+#include <asm/prctl.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
@@ -139,8 +142,9 @@ export_filter (const char *file,
 int
 main (int argc, char **argv)
 {
-  if (argc != 3)
-    fail (0, "usage: %s out.bpf out.pfc", argv[0]);
+  if (argc != 5)
+    fail (0, "usage: %s out.bpf out.pfc out-exec.bpf out-exec.pfc",
+          argv[0]);
 
   /* Any unhandled syscall should abort the Emacs process.  */
   ctx = seccomp_init (SCMP_ACT_KILL_PROCESS);
@@ -156,6 +160,8 @@ main (int argc, char **argv)
   verify (CHAR_BIT == 8);
   verify (sizeof (int) == 4 && INT_MIN == INT32_MIN
           && INT_MAX == INT32_MAX);
+  verify (sizeof (long) == 8 && LONG_MIN == INT64_MIN
+          && LONG_MAX == INT64_MAX);
   verify (sizeof (void *) == 8);
   verify ((uintptr_t) NULL == 0);
 
@@ -327,4 +333,29 @@ main (int argc, char **argv)
 
   EXPORT_FILTER (argv[1], seccomp_export_bpf);
   EXPORT_FILTER (argv[2], seccomp_export_pfc);
+
+  /* When applying a Seccomp filter before executing the Emacs binary
+     (e.g. using the `bwrap' program), we need to allow further system
+     calls.  Firstly, the wrapper binary will need to `execve' the
+     Emacs binary.  Furthermore, the C library requires some system
+     calls at startup time to set up thread-local storage.  */
+  RULE (SCMP_ACT_ALLOW, SCMP_SYS (execve));
+  RULE (SCMP_ACT_ALLOW, SCMP_SYS (set_tid_address));
+  RULE (SCMP_ACT_ALLOW, SCMP_SYS (arch_prctl),
+        SCMP_A0_32 (SCMP_CMP_EQ, ARCH_SET_FS));
+  RULE (SCMP_ACT_ALLOW, SCMP_SYS (statfs));
+
+  /* We want to allow starting the Emacs binary itself with the
+     --seccomp flag, so we need to allow the `prctl' and `seccomp'
+     system calls.  */
+  RULE (SCMP_ACT_ALLOW, SCMP_SYS (prctl),
+        SCMP_A0_32 (SCMP_CMP_EQ, PR_SET_NO_NEW_PRIVS),
+        SCMP_A1_64 (SCMP_CMP_EQ, 1), SCMP_A2_64 (SCMP_CMP_EQ, 0),
+        SCMP_A3_64 (SCMP_CMP_EQ, 0), SCMP_A4_64 (SCMP_CMP_EQ, 0));
+  RULE (SCMP_ACT_ALLOW, SCMP_SYS (seccomp),
+        SCMP_A0_32 (SCMP_CMP_EQ, SECCOMP_SET_MODE_FILTER),
+        SCMP_A1_32 (SCMP_CMP_EQ, SECCOMP_FILTER_FLAG_TSYNC));
+
+  EXPORT_FILTER (argv[3], seccomp_export_bpf);
+  EXPORT_FILTER (argv[4], seccomp_export_pfc);
 }
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 0000000..5b0e997
--- /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 89d811f..09f9a24 100644
--- a/test/src/emacs-tests.el
+++ b/test/src/emacs-tests.el
@@ -177,4 +177,37 @@ to `make-temp-file', which see."
         (ert-info ((format "Process output: %s" (buffer-string)))
           (should-not (eql status 0)))))))
 
+(ert-deftest emacs-tests/bwrap/allows-stdout ()
+  (let ((bash (executable-find "bash"))
+        (bwrap (executable-find "bwrap"))
+        (emacs
+         (expand-file-name invocation-name invocation-directory))
+        (filter (ert-resource-file "seccomp-filter-exec.bpf"))
+        (process-environment nil))
+    (skip-unless bash)
+    (skip-unless bwrap)
+    (skip-unless (file-executable-p emacs))
+    (skip-unless (file-readable-p filter))
+    (should-not (file-remote-p bwrap))
+    (should-not (file-remote-p emacs))
+    (should-not (file-remote-p filter))
+    (with-temp-buffer
+      (let* ((command
+              (concat
+               (mapconcat #'shell-quote-argument
+                          `(,(file-name-unquote bwrap)
+                            "--ro-bind" "/" "/"
+                            "--seccomp" "20"
+                            "--"
+                            ,(file-name-unquote emacs)
+                            "--quick" "--batch"
+                            ,(format "--eval=%S" '(message "Hi")))
+                          " ")
+               " 20< "
+               (shell-quote-argument (file-name-unquote filter))))
+             (status (call-process bash nil t nil "-c" command)))
+        (ert-info ((format "Process output: %s" (buffer-string)))
+          (should (eql status 0)))
+        (should (equal (string-trim (buffer-string)) "Hi"))))))
+
 ;;; emacs-tests.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]