mirror of
https://github.com/NixOS/nix
synced 2025-06-30 07:33:16 +02:00
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 (47f587700d
). Reported by Linus Heckemann. (cherry picked from commit6cc6c15a2d
)
This commit is contained in:
parent
a8d13e66ee
commit
e296b8884e
5 changed files with 67 additions and 0 deletions
|
@ -200,6 +200,13 @@ AC_SUBST(HAVE_SODIUM, [$have_sodium])
|
||||||
PKG_CHECK_MODULES([LIBLZMA], [liblzma], [CXXFLAGS="$LIBLZMA_CFLAGS $CXXFLAGS"])
|
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
|
||||||
|
|
||||||
|
|
||||||
# Whether to use the Boehm garbage collector.
|
# Whether to use the Boehm garbage collector.
|
||||||
AC_ARG_ENABLE(gc, AC_HELP_STRING([--enable-gc],
|
AC_ARG_ENABLE(gc, AC_HELP_STRING([--enable-gc],
|
||||||
[enable garbage collection in the Nix expression evaluator (requires Boehm GC) [default=no]]),
|
[enable garbage collection in the Nix expression evaluator (requires Boehm GC) [default=no]]),
|
||||||
|
|
|
@ -27,6 +27,7 @@ let
|
||||||
[ curl bison flex perl libxml2 libxslt bzip2 xz
|
[ curl bison flex perl libxml2 libxslt bzip2 xz
|
||||||
dblatex (dblatex.tex or tetex) nukeReferences pkgconfig sqlite libsodium
|
dblatex (dblatex.tex or tetex) nukeReferences pkgconfig sqlite libsodium
|
||||||
docbook5 docbook5_xsl
|
docbook5 docbook5_xsl
|
||||||
|
libseccomp
|
||||||
] ++ lib.optional (!lib.inNixShell) git;
|
] ++ lib.optional (!lib.inNixShell) git;
|
||||||
|
|
||||||
configureFlags = ''
|
configureFlags = ''
|
||||||
|
@ -85,6 +86,7 @@ let
|
||||||
|
|
||||||
buildInputs =
|
buildInputs =
|
||||||
[ curl perl bzip2 xz openssl pkgconfig sqlite boehmgc ]
|
[ curl perl bzip2 xz openssl pkgconfig sqlite boehmgc ]
|
||||||
|
++ lib.optional stdenv.isLinux libseccomp
|
||||||
++ lib.optional stdenv.isLinux libsodium;
|
++ lib.optional stdenv.isLinux libsodium;
|
||||||
|
|
||||||
configureFlags = ''
|
configureFlags = ''
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "archive.hh"
|
#include "archive.hh"
|
||||||
#include "affinity.hh"
|
#include "affinity.hh"
|
||||||
#include "builtins.hh"
|
#include "builtins.hh"
|
||||||
|
#include "finally.hh"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -54,6 +55,7 @@
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
#include <seccomp.h>
|
||||||
#define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old))
|
#define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2251,6 +2253,42 @@ void DerivationGoal::startBuilder()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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()
|
void DerivationGoal::runChild()
|
||||||
{
|
{
|
||||||
/* Warning: in the child we should absolutely not make any SQLite
|
/* Warning: in the child we should absolutely not make any SQLite
|
||||||
|
@ -2262,6 +2300,8 @@ void DerivationGoal::runChild()
|
||||||
|
|
||||||
commonChildInit(builderOut);
|
commonChildInit(builderOut);
|
||||||
|
|
||||||
|
setupSeccomp();
|
||||||
|
|
||||||
#if __linux__
|
#if __linux__
|
||||||
if (useChroot) {
|
if (useChroot) {
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,10 @@ ifeq ($(OS), SunOS)
|
||||||
libstore_LDFLAGS += -lsocket
|
libstore_LDFLAGS += -lsocket
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS), Linux)
|
||||||
|
libstore_LDFLAGS += -lseccomp
|
||||||
|
endif
|
||||||
|
|
||||||
libstore_CXXFLAGS = \
|
libstore_CXXFLAGS = \
|
||||||
-DNIX_PREFIX=\"$(prefix)\" \
|
-DNIX_PREFIX=\"$(prefix)\" \
|
||||||
-DNIX_STORE_DIR=\"$(storedir)\" \
|
-DNIX_STORE_DIR=\"$(storedir)\" \
|
||||||
|
|
14
src/libutil/finally.hh
Normal file
14
src/libutil/finally.hh
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
/* A trivial class to run a function at the end of a scope. */
|
||||||
|
class Finally
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::function<void()> fun;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Finally(std::function<void()> fun) : fun(fun) { }
|
||||||
|
~Finally() { fun(); }
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue