Skip to content

Allow gc-ing with a rootless daemon#15026

Closed
artemist wants to merge 1 commit intoNixOS:masterfrom
obsidiansystems:rootless-daemon-new
Closed

Allow gc-ing with a rootless daemon#15026
artemist wants to merge 1 commit intoNixOS:masterfrom
obsidiansystems:rootless-daemon-new

Conversation

@artemist
Copy link
Member

Motivation

Determining garbage collection roots requires root access, but little other of nix does. If garbage collection is moved out to a minimal external daemon and the nix store is owned as an unprivileged user then nix can run with no root permissions, reducing the damage if it is exploited.

Context

This is a replacement for #5380 and a fix for #5208. I determined a new branch was easier than squashing and rebasing so many commits after major changes to the nix codebase.

The main gc code is moved out of libstore into a new libroots, which can be accessed by both libstore and the new nix-roots-daemon.

This is still a draft as the nix-roots-daemon has not been written and libroots still relies on libutil.


Add 👍 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

@artemist artemist force-pushed the rootless-daemon-new branch from 5b752cb to 12e2277 Compare January 20, 2026 18:25
@artemist
Copy link
Member Author

I'm not entirely convinced that we need to remove the libutil dependency. The C++ standard library lacks many useful tools that have been provided in libutil (e.g. string parsing, calling external programs, parsing environment), and reimplemting those would require duplication and may result in lower code quality in libroots.

We would also need to reimplement the assert-fail wrapper from nix-meson-build-support, as that relies on libutil.

@xokdvium
Copy link
Contributor

libroots still relies on libutil.

Why is that an issue? It seems like we can reuse a bunch of code without reimplementing everything from scratch.

Also, I've been a bit stumped by which issue we are solving here exactly. What's the threat model? I don't see any security gains from this at least for NixOS, since a pwned daemon would allow trivial privilege escalation anyway (by replacing a sensitive store path).

@artemist
Copy link
Member Author

This is not useful for NixOS, but it does reduce nix's attack surface on non-NixOS Linux.

@artemist
Copy link
Member Author

I am somewhat confused why the original code uses boost::unordered_flat_map<std::string, boost::unordered_flat_set<std::string, StringViewHash, std::equal_to<>>, StringViewHash, std::equal_to<>> as UncheckedRoots instead of std::map<std::string, std::set<std::string>>. I heard there may be some advantage to boost, but I do not know what it is.

@xokdvium
Copy link
Contributor

So the use-case would be:

  • You want a multi-user installation, but don't trust the daemon to not be pwned. So no privileged user can ever run software from the store, otherwise the point is moot.
  • But you still want to trace runtime roots, which requires CAP_SYS_PTRACE (which is root in a couple of steps).

One alternative:

We can probably just disable runtime root scanning if we don't have CAP_SYS_PTRACE and just scan whatever we have access to. Then the usecase with a multi-user install on non-NixOS could just have a group that the daemon runs as. Runtime roots won't be found without CAP_SYS_PTRACE, but presumably any security-conscious use-case would never allow ptracing arbitrary processes anyway.

I think the more productive ways to harden the daemon are:

  • Drop capabilities aggressively. Currently it's not done at all, but there are some very high value ones like CAP_FSETID (dropping it would mean that we can't ever mess up with setuid bits when chowning).
  • Eradicate filesystem races everywhere.

@artemist artemist force-pushed the rootless-daemon-new branch from 12e2277 to effed85 Compare January 20, 2026 21:02
The new "libroots" library intentionally does not rely on other parts of
the nix codebase, so as to allow creating a minimal daemon to find roots
while the rest of nix is left unprivileged.

Co-Authored-By: Théophane Hufschmitt <theophane.hufschmitt@tweag.io>
Co-Authored-By: John Ericson <John.Ericson@Obsidian.Systems>
@artemist
Copy link
Member Author

artemist commented Feb 4, 2026

Replaced by #15143

@artemist artemist closed this Feb 4, 2026
@edolstra
Copy link
Member

edolstra commented Feb 4, 2026

@artemist Allegedly the boost types are faster (9f2b6a1).

@Ericson2314 Ericson2314 deleted the rootless-daemon-new branch February 10, 2026 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants