1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-22 18:29:36 +01: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 commit 6cc6c15a2d)
This commit is contained in:
Eelco Dolstra 2017-05-29 11:34:24 +02:00
parent a8d13e66ee
commit e296b8884e
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
5 changed files with 67 additions and 0 deletions

View file

@ -9,6 +9,7 @@
#include "archive.hh"
#include "affinity.hh"
#include "builtins.hh"
#include "finally.hh"
#include <algorithm>
#include <iostream>
@ -54,6 +55,7 @@
#include <sys/mount.h>
#include <sys/syscall.h>
#include <linux/fs.h>
#include <seccomp.h>
#define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old))
#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()
{
/* Warning: in the child we should absolutely not make any SQLite
@ -2262,6 +2300,8 @@ void DerivationGoal::runChild()
commonChildInit(builderOut);
setupSeccomp();
#if __linux__
if (useChroot) {

View file

@ -14,6 +14,10 @@ ifeq ($(OS), SunOS)
libstore_LDFLAGS += -lsocket
endif
ifeq ($(OS), Linux)
libstore_LDFLAGS += -lseccomp
endif
libstore_CXXFLAGS = \
-DNIX_PREFIX=\"$(prefix)\" \
-DNIX_STORE_DIR=\"$(storedir)\" \

14
src/libutil/finally.hh Normal file
View 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(); }
};