SELinux on NixOS

19 Likes

Wow. Thanks for your contributions!

1 Like

Isn’t SELinux fundamentally useless on NixOS due to Nix not allowing to change files metadata in /nix/store? (Nix issues 5327, 2670).

Did something change in this regard?

5 Likes

I believe that’s still the current thinking. Though, I think this is something still worth investigating and there may be a solution. Not 100% sure yet until I have declarative policies.

1 Like

Note that changing MAC labels on store paths is different from changing labels on where those store paths are linked to during activation, since file contexts are based on paths, but those paths can also be a link themselves (i.e. not in the store). It seems at least worth experimenting with at the NixOS layer (and anything that makes experimentation easier is a win, in my book).

1 Like

Yeah, it sounds like using that with /run/current-system/sw/bin may be what we should focus on then?

Even if /nix/store is left completely unlabelled, SELinux can still be used to control access to/from the rest of the system, or?

(e.g. processes, state in /var or wherever, secrets such as SSH keys, etc.)

1 Like

What does that even gain? Almost nothing uses /run/current-system. Except for maybe the interactive shell and optional dependencies on binaries.

Everywhere in nixos we prefer to refer to store paths directly instead. E.g. for shell scripts we rewrite shebangs automatically to refer to nix store paths. Same for basically everything everywhere. Same for execstart lines for systemd units. Most things work without being in environment.systemPackages and id like to keep it that way.

I think we should focus on AppArmor on NixOS Roadmap - #12 by Atemu instead as the solution for MAC on nixos. I dont think the SELinux route is going to end anywhere.

5 Likes

You at least provide policies for environment.systemPackages, systemd, and a few other things. Also I don’t think that we should reject this work because “AppArmor exists”. AppArmor and SELinux work differently and despite that nix itself could have issues with SELinux on the store, I don’t think that’s ultimately what should reject it. Like what others have mentioned, can’t we apply it to things other than the store?

That would be like patching a tiny hole when you have a massive flood elsewhere. MAC on NixOS must address the store, if we want implementing MAC to be a good use of time.

How would systemd integration even work? Systemd unit files live in the nix store. We can’t apply labels to them. So the systemd policy integration will never work on nixos. I don’t see a way how we can make systemd work.

1 Like

By using SELinuxContext in services. I don’t see great documentation on it but here’s an example: systemd/test/fuzz/fuzz-unit-file/systemd-machined.service at 6aa69f702b481d95e6254703f46daa31058deea1 · systemd/systemd · GitHub

That is a difference feature. I thought you were talking about the following in which systemd access as a SELinux Access Manager Chapter 10. SELinux systemd Access Control | Red Hat Product Documentation

which looks at labels on the calling process and on the unit files to make a decision whether a process can access systemd or not. This feature is not going to work in NixOS at all because:

1.The calling process is a binary executed from the nix store and thus is unlabeled
2. The unit file is in the nix store and thus is unlabeled

Also how would this work practically? Currently the whole of /run/current-system is a symlink to the nix store. We rely on this in many places and we can’t change that. So we can’t apply labels to things in /run/current-system/sw/bin as that lives in the nix store and thus doesn’t support labelling. I just don’t see how pratically anything in NixOS would work with SELinux. Can you please make a concrete example that works end to end that demonstrates what you want to do? I think it would really help me understand what you’re trying to do. Because all the things you’ve currently suggested I simply don’t see working on NixOS, unless we start propagating SELinux labels in NARs or something.

1 Like

I believe the systemd context option for services and labeling the binaries for a service is the same thing. It’s just not easily documented. Just labeling the binary will use the context from the label. While the context option will use it directly but the binary itself doesn’t have to be labeled.

@numinit and I may have come up with a solution using a store overlay. The lower bit is the store itself while the upper is the SELinux stuff. The SELinux layer is a tmpfs and everything is set up in NixOS stage 2.

2 Likes

And, regardless, we’ll have to benchmark whether overlayfs metacopy’s performance with SELinux is anything resembling reasonable, and whether the Nix daemon’s bind mount in stage2 plays nicely, though the bind mount vfs node is a feature I’ve dealt with before. This is indeed still a very exploratory thing for now.

1 Like

Yeah and we’re basically at the point to explore this. We hacked hard last night at fixing erroneous things and getting them into staging. refpolicy is also in nixpkgs and ready to be used. The next thing now is getting the basic VM testing.

3 Likes

That reminds me. I have a very experimental branch for stage 2 secure boot verification using overlayfs. I’m using a Nix patch that causes it to enable fs-verity on all files before registering a store path. Since fs-verity hashes are predictable, I have a derivation building a metadata-only erofs image containing the expected fs-verity root hash for all files in the system closure. The overlayfs just overlays this metadata-only file system on top of the store, both as separate lower layers (no need for any upper layer if you treat the store as immutable), and overlayfs enforces that the underlying files do actually have the same fs-verity root hash as the ones in the metadata-only image. The design goal is to have NixOS remain usable as a normal NixOS installation. So nix-daemon will unmount the overlayfs in its private mount namespace to give itself access to the underlying FS, and activation would swap out the overlayfs the same way system.etc.overlay does. That way you can still nixos-rebuild switch even with a verified stage 2 store. This is why the approach needs to use fs-verity instead of dm-verity.

Anyway, it sounds like an overlay on top of the store is desirable for SELinux as well, so maybe we could get the ideas working together.

6 Likes

This sounds awesome and we certainly should. I came up with this sparse overlay idea a while ago to enable package grafts too, for libc updates, but never got around to implementing it. It sounds like a bit of convergent evolution toward the same thing - that is, respecting the immutability of the store but allowing very limited system-level changes to it at runtime.

A similar method could be used to cook SELinux policies into a squashfs store image that gets an overlay for local changes. (Edit: I was actually exploring the dm-verity side of this, btw, less with cooking metadata into the RO image and more with being able to overlay it in a way that everything is happy about, including upgrades).

1 Like