Skip to content

kernel: enable module signing#87426

Closed
eadwu wants to merge 8 commits intoNixOS:masterfrom
eadwu:kernel/sign-modules
Closed

kernel: enable module signing#87426
eadwu wants to merge 8 commits intoNixOS:masterfrom
eadwu:kernel/sign-modules

Conversation

@eadwu
Copy link
Member

@eadwu eadwu commented May 9, 2020

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
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS linux)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.

Copy link
Member Author

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.

@ofborg ofborg bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 501+ This PR causes many rebuilds on Linux and should normally target the staging branches. 10.rebuild-linux: 1001-2500 This PR causes many rebuilds on Linux and should target the staging branches. labels May 9, 2020
@eadwu eadwu force-pushed the kernel/sign-modules branch from c7ae5cf to 2bf1dc9 Compare May 15, 2020 02:14
Copy link
Member

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?

Copy link
Member Author

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).

Copy link
Member

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?

Copy link
Member Author

@eadwu eadwu May 15, 2020

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?

Copy link
Member

@vikanezrimaya vikanezrimaya Nov 11, 2020

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.

Copy link
Member

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.

@ofborg ofborg bot added the 8.has: package (new) This PR adds a new package label May 15, 2020
@eadwu
Copy link
Member Author

eadwu commented May 15, 2020

Depends on #87856 for certain scenarios.

@eadwu eadwu force-pushed the kernel/sign-modules branch from 2bf1dc9 to 67b1cdf Compare May 23, 2020 15:39
@eadwu eadwu force-pushed the kernel/sign-modules branch from 67b1cdf to 8575b86 Compare June 30, 2020 19:48
@ofborg ofborg bot requested review from layus, teto and thoughtpolice June 30, 2020 19:56
@eadwu eadwu force-pushed the kernel/sign-modules branch 4 times, most recently from 47dfbfd to dafb287 Compare July 1, 2020 01:46
@ofborg ofborg bot requested a review from abbradar July 1, 2020 01:54
@eadwu eadwu force-pushed the kernel/sign-modules branch from dafb287 to 7ca0592 Compare July 1, 2020 22:13
@eadwu eadwu force-pushed the kernel/sign-modules branch from 7ca0592 to 721f102 Compare July 20, 2020 02:17
@eadwu eadwu force-pushed the kernel/sign-modules branch 3 times, most recently from 5283707 to 043b279 Compare August 16, 2020 18:42
@ofborg ofborg bot added 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: module (update) This PR changes an existing module in `nixos/` labels Aug 16, 2020
@ofborg ofborg bot requested a review from Atemu August 16, 2020 19:29
@ofborg ofborg bot removed 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: module (update) This PR changes an existing module in `nixos/` labels Aug 16, 2020
@eadwu eadwu force-pushed the kernel/sign-modules branch from 6b415af to 21e38db Compare August 17, 2020 01:47
@eadwu eadwu force-pushed the kernel/sign-modules branch from 21e38db to 1fe16c6 Compare September 8, 2020 16:00
@eadwu eadwu force-pushed the kernel/sign-modules branch from 1fe16c6 to 61f94cf Compare September 26, 2020 15:25
@eadwu eadwu force-pushed the kernel/sign-modules branch from 61f94cf to afbaee8 Compare October 7, 2020 18:00
@eadwu eadwu force-pushed the kernel/sign-modules branch from afbaee8 to 7305114 Compare October 29, 2020 20:15
@vikanezrimaya
Copy link
Member

vikanezrimaya commented Nov 11, 2020

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 /nix/store.

@eadwu eadwu force-pushed the kernel/sign-modules branch from 7305114 to 7aa45d1 Compare November 16, 2020 19:08
@eadwu eadwu force-pushed the kernel/sign-modules branch from 7aa45d1 to bd5c201 Compare December 21, 2020 06:07
@eadwu eadwu force-pushed the kernel/sign-modules branch from bd5c201 to 35f733f Compare January 11, 2021 18:08
@Atemu
Copy link
Member

Atemu commented Jan 11, 2021

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 nixos-rebuild switch could use any form of authentication you could want (e.g. private key inside a hardware token) and the kernel + modules need to be touched at that moment anyways.

@ofborg ofborg bot requested a review from andresilva January 11, 2021 19:42
@eadwu
Copy link
Member Author

eadwu commented Jan 11, 2021

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 MODULE_SIG and whatnot config options), before stripping the signatures and public key in the fixupPhase, before doing some brittle monkey patching on the kernel (a good idea?) and resigning the modules, though it probably will result in an extra kernel and kernel-modules derivation in the store.

@SuperSandro2000 SuperSandro2000 added the 2.status: merge conflict This PR has merge conflicts with the target branch label Jan 18, 2021
@vikanezrimaya
Copy link
Member

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 nixos-rebuild boot a little bit longer but a lot more secure.

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.

@stale
Copy link

stale bot commented Sep 3, 2021

I marked this as stale due to inactivity. → More info

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Sep 3, 2021
@eadwu
Copy link
Member Author

eadwu commented Sep 3, 2021

Closing for now ... I'll see how this ends up going if I have time in between university and 2 research groups ...

@stale stale bot removed the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Sep 3, 2021
@eadwu eadwu closed this Sep 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2.status: merge conflict This PR has merge conflicts with the target branch 8.has: package (new) This PR adds a new package 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 501+ This PR causes many rebuilds on Linux and should normally target the staging branches. 10.rebuild-linux: 1001-2500 This PR causes many rebuilds on Linux and should target the staging branches.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants