aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-05-29 11:34:24 +0200
committerEelco Dolstra <edolstra@gmail.com>2017-05-29 16:14:10 +0200
commit6cc6c15a2d50d0021d7242e9806ed6d54538de17 (patch)
treee9a5fbd03cd6c1e0a1d8b68fff784f2d0f29dee7
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.
-rw-r--r--configure.ac7
-rw-r--r--release.nix2
-rw-r--r--shell.nix3
-rw-r--r--src/libstore/build.cc39
-rw-r--r--src/libstore/local.mk4
5 files changed, 54 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index 24a95ce56..9d8a81d04 100644
--- a/configure.ac
+++ b/configure.ac
@@ -176,6 +176,13 @@ AC_SUBST(HAVE_SODIUM, [$have_sodium])
PKG_CHECK_MODULES([LIBLZMA], [liblzma], [CXXFLAGS="$LIBLZMA_CFLAGS $CXXFLAGS"])
+# Look for libseccomp, required for Linux sandboxing.
+if test "$sys_name" = linux; then
+ PKG_CHECK_MODULES([LIBSECCOMP], [libseccomp],
+ [CXXFLAGS="$LIBSECCOMP_CFLAGS $CXXFLAGS"])
+fi
+
+
# Look for aws-cpp-sdk-s3.
AC_LANG_PUSH(C++)
AC_CHECK_HEADERS([aws/s3/S3Client.h],
diff --git a/release.nix b/release.nix
index f1a553d01..1e854a075 100644
--- a/release.nix
+++ b/release.nix
@@ -30,6 +30,7 @@ let
docbook5 docbook5_xsl
autoconf-archive
git
+ libseccomp
];
configureFlags = "--enable-gc";
@@ -78,6 +79,7 @@ let
openssl pkgconfig sqlite boehmgc
]
+ ++ lib.optional stdenv.isLinux libseccomp
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
++ lib.optional (stdenv.isLinux || stdenv.isDarwin)
(aws-sdk-cpp.override {
diff --git a/shell.nix b/shell.nix
index c4e2a20f8..435399f0b 100644
--- a/shell.nix
+++ b/shell.nix
@@ -22,7 +22,8 @@ with import ./release-common.nix { inherit pkgs; };
# For nix-perl
perl
perlPackages.DBDSQLite
- ];
+ ]
+ ++ lib.optional stdenv.isLinux libseccomp;
inherit configureFlags;
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 44cae3431..06d259606 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 e06002587..ffdb55abc 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)\" \