libstore/build: drop cgroups experimental feature

We drop it to re-introduce it via the concept of build context which
will control in which cgroup a certain build should be spawned.

Change-Id: I4b4705d768129a6d7c0f061dc2163ba116088b18
Signed-off-by: Raito Bezarius <raito@lix.systems>
This commit is contained in:
Raito Bezarius
2025-06-10 16:00:51 +00:00
parent 21dbd7745d
commit 1783d5b348
12 changed files with 6 additions and 194 deletions
+1 -52
View File
@@ -16,7 +16,6 @@
#include "lix/libutil/result.hh"
#include "lix/libutil/topo-sort.hh"
#include "lix/libutil/json.hh"
#include "lix/libutil/cgroup.hh"
#include "lix/libstore/build/personality.hh"
#include "lix/libutil/namespaces.hh"
#include "lix/libstore/build/child.hh"
@@ -403,57 +402,8 @@ void LocalDerivationGoal::cleanupPostOutputsRegisteredModeNonCheck()
kj::Promise<Result<void>> LocalDerivationGoal::startBuilder()
try {
if ((buildUser && buildUser->getUIDCount() != 1)
#if __linux__
|| settings.useCgroups
#endif
)
{
#if __linux__
experimentalFeatureSettings.require(Xp::Cgroups);
auto cgroupFS = getCgroupFS();
if (!cgroupFS)
throw Error("cannot determine the cgroups file system");
auto ourCgroups = getCgroups("/proc/self/cgroup");
auto ourCgroup = ourCgroups[""];
if (ourCgroup == "")
throw Error("cannot determine cgroup name from /proc/self/cgroup");
auto ourCgroupPath = canonPath(*cgroupFS + "/" + ourCgroup);
if (!pathExists(ourCgroupPath))
throw Error("expected cgroup directory '%s'", ourCgroupPath);
static std::atomic<unsigned int> counter{0};
cgroup = buildUser
? fmt("%s/nix-build-uid-%d", ourCgroupPath, buildUser->getUID())
: fmt("%s/nix-build-pid-%d-%d", ourCgroupPath, getpid(), counter++);
debug("using cgroup '%s'", *cgroup);
/* When using a build user, record the cgroup we used for that
user so that if we got interrupted previously, we can kill
any left-over cgroup first. */
if (buildUser) {
auto cgroupsDir = settings.nixStateDir + "/cgroups";
createDirs(cgroupsDir);
auto cgroupFile = fmt("%s/%d", cgroupsDir, buildUser->getUID());
if (pathExists(cgroupFile)) {
auto prevCgroup = readFile(cgroupFile);
destroyCgroup(prevCgroup);
}
writeFile(cgroupFile, *cgroup);
}
#else
if (buildUser && buildUser->getUIDCount() != 1) {
throw Error("cgroups are not supported on this platform");
#endif
}
/* Make sure that no other processes are executing under the
@@ -823,7 +773,6 @@ try {
co_return result::current_exception();
}
Pid LocalDerivationGoal::startChild(std::function<void()> openSlave) {
return startProcess([&]() {
openSlave();
+1 -7
View File
@@ -21,11 +21,6 @@ struct LocalDerivationGoal : public DerivationGoal
*/
Pid pid;
/**
* The cgroup of the builder, if any.
*/
std::optional<Path> cgroup;
/**
* The temporary directory.
*/
@@ -238,8 +233,7 @@ struct LocalDerivationGoal : public DerivationGoal
void killChild() override final;
/**
* Kill any processes running under the build user UID or in the
* cgroup of the build.
* Kill any processes running under the build user UID.
*/
virtual void killSandbox(bool getStats);
-1
View File
@@ -108,7 +108,6 @@ libstore_setting_definitions = files(
'settings/timeout.md',
'settings/trusted-public-keys.md',
'settings/trusted-substituters.md',
'settings/use-cgroups.md',
'settings/use-sqlite-wal.md',
'settings/use-xdg-base-directories.md',
# keep-sorted end
+1 -21
View File
@@ -1,5 +1,4 @@
#include "lix/libstore/build/worker.hh"
#include "lix/libutil/cgroup.hh"
#include "lix/libutil/finally.hh"
#include "lix/libstore/gc-store.hh"
#include "lix/libutil/signals.hh"
@@ -819,15 +818,6 @@ void LinuxLocalDerivationGoal::prepareSandbox()
for (auto & i : drv->outputsAndPaths(worker.store)) {
pathsInChroot.erase(worker.store.printStorePath(i.second.second));
}
if (cgroup) {
if (mkdir(cgroup->c_str(), 0755) != 0)
throw SysError("creating cgroup '%s'", *cgroup);
chownToBuilder(*cgroup);
chownToBuilder(*cgroup + "/cgroup.procs");
chownToBuilder(*cgroup + "/cgroup.threads");
//chownToBuilder(*cgroup + "/cgroup.subtree_control");
}
}
Pid LinuxLocalDerivationGoal::startChild(std::function<void()> openSlave)
@@ -967,10 +957,6 @@ Pid LinuxLocalDerivationGoal::startChild(std::function<void()> openSlave)
"nixbld:!:%1%:\n"
"nogroup:x:65534:\n", sandboxGid()));
/* Move the child into its own cgroup. */
if (cgroup)
writeFile(*cgroup + "/cgroup.procs", fmt("%d", pid.get()));
/* Signal the builder that we've updated its user namespace. */
writeFull(userNamespaceSync.writeSide.get(), "1");
@@ -979,13 +965,7 @@ Pid LinuxLocalDerivationGoal::startChild(std::function<void()> openSlave)
void LinuxLocalDerivationGoal::killSandbox(bool getStats)
{
if (cgroup) {
auto stats = destroyCgroup(*cgroup);
if (getStats) {
buildResult.cpuUser = stats.cpuUser;
buildResult.cpuSystem = stats.cpuSystem;
}
} else if (!useChroot) {
if (!useChroot) {
/* Linux sandboxes use PID namespaces, which ensure that processes cannot escape from a build.
Therefore, we don't need to kill all processes belonging to the build user.
This avoids processes unrelated to the build being killed, thus avoiding: https://git.lix.systems/lix-project/lix/issues/667 */
+2 -3
View File
@@ -40,14 +40,13 @@ private:
void prepareSandbox() override;
/**
* Start child process in new namespaces and cgroup,
* Start child process in new namespaces,
* create /etc/passwd and /etc/group based on discovered uid/gid
*/
Pid startChild(std::function<void()> openSlave) override;
/**
* Kill all processes by build user, possibly using a reused
* cgroup if we have one
* Kill all processes by build user.
*/
void killSandbox(bool getStatus) override;
-12
View File
@@ -1,12 +0,0 @@
---
name: use-cgroups
internalName: useCgroups
platforms: [linux]
type: bool
default: false
experimentalFeature: cgroups
---
Whether to execute builds inside cgroups.
Cgroups are required and enabled automatically for derivations
that require the `uid-range` system feature.
@@ -1,6 +0,0 @@
---
name: cgroups
internalName: Cgroups
---
Allows Nix to execute builds inside cgroups. See
the [`use-cgroups`](../command-ref/conf-file.md#conf-use-cgroups) setting for details.
-1
View File
@@ -142,7 +142,6 @@ libutil_headers = files(
experimental_feature_definitions = files(
# keep-sorted start
'experimental-features/auto-allocate-uids.md',
'experimental-features/cgroups.md',
'experimental-features/coerce-integers.md',
'experimental-features/daemon-trust-override.md',
'experimental-features/fetch-closure.md',
+1 -1
View File
@@ -18,7 +18,7 @@
nix.settings.substituters = lib.mkForce [ ];
nix.extraOptions =
''
extra-experimental-features = nix-command auto-allocate-uids cgroups
extra-experimental-features = nix-command auto-allocate-uids
extra-system-features = uid-range
'';
nix.nixPath = [ "nixpkgs=${nixpkgs}" ];
-8
View File
@@ -1,8 +0,0 @@
{ name, uidRange ? false }:
with import <nixpkgs> {};
runCommand name
{ requiredSystemFeatures = if uidRange then ["uid-range"] else [];
}
"id; id > $out"
-80
View File
@@ -1,80 +0,0 @@
{ nixpkgs }:
let
machine = { config, pkgs, ... }:
{
system.stateVersion = "22.05";
boot.isContainer = true;
systemd.services.console-getty.enable = false;
networking.dhcpcd.enable = false;
services.httpd = {
enable = true;
adminAddr = "nixos@example.org";
};
systemd.services.test = {
wantedBy = [ "multi-user.target" ];
after = [ "httpd.service" ];
script = ''
source /.env
echo "Hello World" > $out/msg
ls -lR /dev > $out/dev
${pkgs.curl}/bin/curl -sS --fail http://localhost/ > $out/page.html
'';
unitConfig = {
FailureAction = "exit-force";
FailureActionExitStatus = 42;
SuccessAction = "exit-force";
};
};
};
cfg = (import (nixpkgs + "/nixos/lib/eval-config.nix") {
modules = [ machine ];
system = "x86_64-linux";
});
config = cfg.config;
in
with cfg._module.args.pkgs;
runCommand "test"
{ buildInputs = [ config.system.path ];
requiredSystemFeatures = [ "uid-range" ];
toplevel = config.system.build.toplevel;
}
''
root=$(pwd)/root
mkdir -p $root $root/etc
export > $root/.env
# Make /run a tmpfs to shut up a systemd warning.
mkdir /run
mount -t tmpfs none /run
mount -t cgroup2 none /sys/fs/cgroup
mkdir -p $out
chmod +w /etc
touch /etc/os-release
echo a5ea3f98dedc0278b6f3cc8c37eeaeac > /etc/machine-id
SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=1 \
${config.systemd.package}/bin/systemd-nspawn \
--keep-unit \
-M ${config.networking.hostName} -D "$root" \
--register=no \
--resolv-conf=off \
--bind-ro=/nix/store \
--bind=$out \
--bind=/proc:/run/host/proc \
--bind=/sys:/run/host/sys \
--private-network \
$toplevel/init
''
-2
View File
@@ -150,8 +150,6 @@ in
tarballFlakes = runNixOSTestFor "x86_64-linux" ./tarball-flakes.nix;
containers = runNixOSTestFor "x86_64-linux" ./containers/containers.nix;
setuid = lib.genAttrs
["i686-linux" "x86_64-linux"]
(system: runNixOSTestFor system ./setuid/setuid.nix);