CONFIG_MODULE_SIG and the unreproducible Linux Kernel

James Addison jay at jp-hosting.net
Mon Sep 16 21:23:27 UTC 2024


Thanks again; please find my responses inline below:

On Sun, 15 Sept 2024 at 03:47, kpcyrd <kpcyrd at archlinux.org> wrote:
>
> On 9/14/24 6:22 PM, James Addison via rb-general wrote:
> > Thank you for the interesting read.  Please let me know whether the
> > summary below seems accurate - and also nitpick anything about it
> > where relevant:
> >
> >    * [currently] Linux kernel modules may be signed using public-key
> > cryptography.
> >
> >    * [currently] When kernel lockdown mode is enabled, only
> > acceptably-signed modules can be loaded by the Linux kernel.
> >
> >    * [currently] Cryptographic signing introduces output randomness --
> > that is, it is nondeterministic -- and that conflicts with the goal of
> > bit-for-bit reproducible builds.
> >
> >    * [proposed] Your suggestion is to replace the lockdown mode's
> > cryptographic signature verification with integrity hash verification:
> > to elaborate, kernel modules would be built (reproducibly) with the
> > cryptographic signature option disabled, and the resulting,
> > deterministic, integrity hashes of the kernel module (.ko) files would
> > be embedded into the kernel binary.  The kernel would then refer to
> > those module integrity hashes to determine whether to load a module or
> > not.
>
> Thanks! Yes, I think this sums it up nicely.
>
> > Two questions / possible misunderstandings:
> >
> >    * You mention that public-key crypto could still be used to
> > authenticate other modules -- would that public key be provided as a
> > stable, constant input to the build process?
>
> Yes, *if* there's an explicit need for additional signed modules and a
> distro-controlled keypair (which Arch Linux currently doesn't have, but
> Debian does for example), then the public key would be configured as a
> stable, well-known build input through something similar to
> CONFIG_MODULE_SIG_KEY. This would be compatible with reproducible builds.

That makes sense, OK.  So, following this proposal, each built kernel
could optionally allowlist a set of kernel modules -- the kernel
module integrity hash collection -- and/or could accept the universe
of suitably-signed kernel modules (as is already possible today).
Those pathways could be enabled individually, or both could be enabled
simultaneously.  Neither of these should introduce build
reproducibility problems.

> >    * Relatedly: would the suggestion be anticipated to affect security,
> > or is it solely focused on achieving build reproducibility?  (what I
> > am thinking here: if a public key is provided and continues to allow
> > other modules to be loaded, then that implies that a corresponding
> > distro-controlled private key exists -- perhaps that key wouldn't be
> > required during each kernel package build, but it would be required to
> > sign loadable kernel modules distributed in other packages -- and it
> > would be as legitimate as any ephemerally-generated build-time private
> > key).
>
> Yes that's also correct.
>
> There are additional security advantages of not having a privileged
> keypair (beyond reproducible builds), for the obvious reason that a
> non-existant keypair can't be compromised. Even with an (allegedly)
> ephemerally-generated key there's no way to prove the key wasn't
> retained in some way.
>
> Modules that are part of the kernel package build could be included in
> the embedded hashset (not needing a signature), but a package with
> additional kernel modules would need access to the distro-controlled
> signing key (and therefore not be reproducible).
>
> Hopefully it would be possible to build computers without these
> packages, allowing for systems built with reproducible-only binaries.

Most of this I agree with, but I have some concern about tampering of
kernel binaries and/or modules.

As a hypothetical attacker who might be interested in compromising
private keys used/generated by build systems, perhaps this feature
could thwart some of my plans.  But my next observation/thought would
be that instead of requiring a copy of a private key to forge loadable
kernel modules (a capability that I would presumably rarely use),
instead I could modify the integrity checksum(s) within relevant
kernel binaries to match my forged module(s) -- and arguably this
would be less traceable (that is, there would be no individual key
that could be reported as compromised upon discovery of a tampered
kernel / kernel module).

To phrase that another way: if the attacker has write access to both
the kernel binary (compressed or otherwise) and kernel modules on a
particular system, and if that systems relies solely on integrity
checksums from those files, then I believe it would be vulnerable to
compromise, and that that compromise would be difficult to attribute.

There are ways that individual environments could mitigate against
this; delivering kernel/module binaries from read-only filesystems
and/or over the network.  Adding integrity checks to I/O reads and
writes.  And observing for unexpected modifications of the
kernel/module.  But I think some caution and evidence would be
important before suggesting that a widely-used software distribution
should use this mechanism for kernels that they distribute to their
users.

> > I have one thought about a limitation that this might introduce, but
> > I'll try to wait for you to confirm whether I'm following along
> > correctly first!

I feel that I'm within acceptable margins of understanding so far, so:

The limitation is that there would be a tight coupling between a
kernel release (git sha / tarball) and the in-tree kernel modules that
could be loaded for it when using pure-integrity based lockdown
limits.  That seems, to a certain extent, to be by-design of the
feature -- but it could affect the way that some distributions
prepare, package and apply upgrades for their users' systems.

Please take all of the above with some grains of salt - I'm not a
kernel developer and my computer security experience lacks any formal
credentials - I'm a keen enthusiast.

Note also that there is some kind of vague concern about software
freedom ringing in my mind as I write this too: the Linux kernel has
an ABI/API, and is open source, and as a result of those, people can
write code (even kernel modules) that are suitable for any given
version of it.  I can appreciate that the kernel module integrity
feature would be an opt-in, configurable mechanism that would be
selectively enabled by individual distributions, but I also think that
it is important to ensure that it could not become a complete lock-out
mechanism for any particular hardware/software combination.

Regards,
James


More information about the rb-general mailing list