about summary refs log tree commit diff
path: root/src/libstore
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-05-29T09·34+0200
committerEelco Dolstra <edolstra@gmail.com>2017-05-29T14·14+0200
commit6cc6c15a2d50d0021d7242e9806ed6d54538de17 (patch)
treee9a5fbd03cd6c1e0a1d8b68fff784f2d0f29dee7 /src/libstore
parent6e01ecd112dce8d8bbe46c839f982892a3ffb589 (diff)
Add a seccomp filter to prevent creating setuid/setgid binaries
This prevents builders from setting the S_ISUID or S_ISGID bits,
preventing users from using a nixbld* user to create a setuid/setgid
binary to interfere with subsequent builds under the same nixbld* uid.

This is based on aszlig's seccomp code
(47f587700d646f5b03a42f2fa57c28875a31efbe).

Reported by Linus Heckemann.
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/build.cc39
-rw-r--r--src/libstore/local.mk4
2 files changed, 43 insertions, 0 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 44cae3431fc2..06d259606661 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -46,6 +46,7 @@
 #include <sys/param.h>
 #include <sys/mount.h>
 #include <sys/syscall.h>
+#include <seccomp.h>
 #define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old))
 #endif
 
@@ -2298,6 +2299,42 @@ void DerivationGoal::doExportReferencesGraph()
 }
 
 
+void setupSeccomp()
+{
+#if __linux__
+    scmp_filter_ctx ctx;
+
+    if (!(ctx = seccomp_init(SCMP_ACT_ALLOW)))
+        throw SysError("unable to initialize seccomp mode 2");
+
+    Finally cleanup([&]() {
+        seccomp_release(ctx);
+    });
+
+    if (seccomp_arch_add(ctx, SCMP_ARCH_X86) != 0)
+        throw SysError("unable to add 32-bit seccomp architecture");
+
+    for (int perm : { S_ISUID, S_ISGID }) {
+        // TODO: test chmod and fchmod.
+        if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(chmod), 1,
+                SCMP_A1(SCMP_CMP_MASKED_EQ, perm, perm)) != 0)
+            throw SysError("unable to add seccomp rule");
+
+        if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmod), 1,
+                SCMP_A1(SCMP_CMP_MASKED_EQ, perm, perm)) != 0)
+            throw SysError("unable to add seccomp rule");
+
+        if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmodat), 1,
+                SCMP_A2(SCMP_CMP_MASKED_EQ, perm, perm)) != 0)
+            throw SysError("unable to add seccomp rule");
+    }
+
+    if (seccomp_load(ctx) != 0)
+        throw SysError("unable to load seccomp BPF program");
+#endif
+}
+
+
 void DerivationGoal::runChild()
 {
     /* Warning: in the child we should absolutely not make any SQLite
@@ -2307,6 +2344,8 @@ void DerivationGoal::runChild()
 
         commonChildInit(builderOut);
 
+        setupSeccomp();
+
         bool setUser = true;
 
         /* Make the contents of netrc available to builtin:fetchurl
diff --git a/src/libstore/local.mk b/src/libstore/local.mk
index e06002587f94..ffdb55abc65b 100644
--- a/src/libstore/local.mk
+++ b/src/libstore/local.mk
@@ -18,6 +18,10 @@ ifeq ($(OS), SunOS)
 	libstore_LDFLAGS += -lsocket
 endif
 
+ifeq ($(OS), Linux)
+	libstore_LDFLAGS += -lseccomp
+endif
+
 libstore_CXXFLAGS = \
  -DNIX_PREFIX=\"$(prefix)\" \
  -DNIX_STORE_DIR=\"$(storedir)\" \