From 6cc6c15a2d50d0021d7242e9806ed6d54538de17 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 29 May 2017 11:34:24 +0200 Subject: [PATCH] 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. --- configure.ac | 7 +++++++ release.nix | 2 ++ shell.nix | 3 ++- src/libstore/build.cc | 39 +++++++++++++++++++++++++++++++++++++++ src/libstore/local.mk | 4 ++++ 5 files changed, 54 insertions(+), 1 deletion(-) 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 #include #include +#include #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)\" \