New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
kernel: enable module signing #87426
Conversation
pkgs/top-level/all-packages.nix
Outdated
autoModuleSignHook = kernel: makeSetupHook | ||
{ substitutions = | ||
{ kernel = kernel.dev + "/lib/modules/${kernel.modDirVersion}/build"; | ||
hash = if (kernel.configfile.structuredConfig ? MODULE_SIG_HASH) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another shortcoming, due to differing hash algos, we need to specify a default or read it in from the output config.
c7ae5cf
to
2bf1dc9
Compare
cp $buildRoot/$f $dev/lib/modules/${modDirVersion}/build/certs | ||
fi | ||
done | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the private signing key in the store, wouldn't this allow anyone on the system to sign arbitrary modules?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it wouldn't be as much of a problem as the certs are generated on every kernel build since we don't supply one by default.
I also assumed that derivations in /nix/store wouldn't be writable by other things (if that's compromised I don't think anything I could do would be much better).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand? As long as the key is in the store, you can just take it and sign an arbitrary module with it, without ever needing to touch anything else in the nix store, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For my specific use case for this PR, it's to modprobe out of tree modules doing the boot phase. The only modules in the initrd are the result of a nix derivation so I'd expect that nothing would be compromised there.
I'm not sure if you can modprobe
modules that aren't in the nix store, but if you can, then yeah, that would be a problem.
If it's just the act of signing arbitrary modules, then if the above isn't possible, then it shouldn't really matter, since if you can't use it, it doesn't make a difference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can load a module from anywhere if it's binary-compatible with your kernel.
Let's imagine the scenario: I somehow gained access to the insmod
command (it loads a kernel module from a file and is a low-level interface to module loading facilities) and able to pass it any path (incorrect SUID configuration on a vulnerable program?). I could craft a kernel module for the same kernel you use (and I could make a reasonable guess by comparing the hashes, if you use a standard Nixpkgs kernel) and then inject it into the kernel.
If the private keys for signing kernel modules are in the /nix/store, I could try to exfiltrate them using the hashes to find the kernel directory (or just by using /run/booted-system?) and sign the module with them. Bam, I have kernel-level access.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One use-case I could imagine would be the builder nix store being kept secret (e.g. separate, access-restriced machine).
Without access to that, the security would hold on the target machine.
Depends on #87856 for certain scenarios. |
2bf1dc9
to
67b1cdf
Compare
67b1cdf
to
8575b86
Compare
47dfbfd
to
dafb287
Compare
dafb287
to
7ca0592
Compare
7ca0592
to
721f102
Compare
5283707
to
043b279
Compare
6b415af
to
21e38db
Compare
21e38db
to
1fe16c6
Compare
1fe16c6
to
61f94cf
Compare
61f94cf
to
afbaee8
Compare
afbaee8
to
7305114
Compare
Can one sign modules after-the-fact with a key and make the kernel recognize it without rebuilding? While I understand signing modules after building would hurt binary reproducibility of derivations including kernel modules (will it? I've heard signatures can be stripped easily if needed or even accidentally) it would allow the private keys to be outside of |
7305114
to
7aa45d1
Compare
7aa45d1
to
bd5c201
Compare
This reverts commit 4938fc4.
bd5c201
to
35f733f
Compare
I also think signing modules and baking the key into the kernel after the fact would be the better approach. It'd probably be best to do that outside a Nix drv honestly; a script that signs modules on |
It is probably possible to inject the key afterwards, but I'm not sure how much effort it would require nor am I exactly really keen on doing so right now. This was just simple POC-ish thing that would allow booting (with external modules) to work with lockdown If I recall correctly, the signature is just appended to the module (I think, I'm not sure, don't really remember), in which case yes, it will be easy to strip the signature afterwards. Probably the way to go if we go this route is to let the kernel generate a key and sign its modules (with |
I feel like whatever would be going on with keys and signing better happen out of my Nix store, preferably in the bootloader integration phase in the switching. It will make I wish we could sign kernels for Secure Boot in a similar way... I've been thinking about doing it with a modified systemd-boot module, but my laptop turned out to have a glitchy UEFI and now I can't boot NixOS automatically, the UEFI entries just refuse to be modified. |
I marked this as stale due to inactivity. → More info |
Closing for now ... I'll see how this ends up going if I have time in between university and 2 research groups ... |
This suffers from the same pitfalls as #86835, if the kernel needs to be rebuilt twice, the generated certificate will be wrong and thus the module is unable to be loaded due to the invalid certificate.
Though with the flawed approach to force the kernel to be the same, I included an example to show it works (zfs).
Motivation for this change
If lockdown is enabled, or module signatures are forced, unsigned modules are unable to be loaded.
Things done
sandbox
innix.conf
on non-NixOS linux)nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
./result/bin/
)nix path-info -S
before and after)