Producing verifiable initramfs images

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Producing verifiable initramfs images

Matthew Garrett-4
I'm working on measured boot as a way to determine whether a system
has been tampered with (https://mjg59.dreamwidth.org/54203.html has an
overview of this). For this to be practical, we need to know what the
expected measurements provided by the TPM are. This is reasonably
straightforward as far as the bootloader and kernel go (we have
shipped artifacts that hash to a known value), but it's a problem for
the initramfs.

The "easiest" solution to this would be to ship an initramfs as an
artifact. This is complicated by two things:

1) Local configuration ending up in the initramfs
2) Additional files ending up in the initramfs based on system configuration

For (1), I've been playing with grub and discovered that its initramfs
code supports the following syntax:

initrd initramfs.img newc:/etc/crypttab:/boot/crypttab

which will load the initramfs, and then also read /boot/crypttab and
incorporate it into an additional CPIO archive as /etc/crypttab. The
kernel will unpack each initramfs image in turn, allowing the
/boot/crypttab file to be incorporated into the initramfs as if it had
been shipped there. This allows us to remove dynamic configuration
components from the initramfs while still allowing them to be provided
on a per-system basis. As long as the measurements verify that the
dynamic content was copied to locations that match configuration
rather than code (and, further, that said configuration doesn't alter
the behaviour of code in ways we care about for boot security), the
actual contents of the configuration files don't matter.

The second is a different problem, but still seems achievable. Each
package that potentially adds content to the initramfs could provide a
pre-build CPIO containing its code, and based on local configuration
we can ask grub to load those as well.

This would result in something that's roughly equivalent to our
current situation, but would allow us to verify that the initramfs
images containing code hadn't been tampered with. This makes it much
easier to verify that the system is in a secure state before a user
enters any credentials, avoiding attacks like
https://yassine.tioual.com/index.php/2017/04/26/backdoor-initramfs-and-make-your-rootkit-persistent/
. Users who don't need this functionality would still be able to
generate their own initramfs images as before (measured boot tracks
what was booted, but doesn't block anything from booting - if you
build your own initramfs then it'd boot fine, but give different
measurements).

A minimal proof of concept here would presumably be a patch to the
kernel package to build an initramfs binary package, and then some
additional tooling to copy appropriate config to the boot partition
and have grub pick that up. Does anybody have any strong feelings on
the topic? If not, I'll try to mock this up.

Reply | Threaded
Open this post in threaded view
|

Re: Producing verifiable initramfs images

Sam Hartman-3
This is not a disagreement with anything you write.

I've noticed that there is a lot more configuration that gets encoded in
the initramfs than I thought.
The most surprising for me is that if you want to control the names of
network devices or anything else set by the .link file,
that ends up needing to go on the initramfs, because udevd will set up
network devices even if they are not needed to find the root.
Unfortunately, that means that initramfs udev configuration (including
/etc/systemd/network/*.link) tends to need to be on the initramfs.

I realize you only gave crypttab as an example, but the set of initramfs
configuration is larger than I at least expected.

--Sam

Reply | Threaded
Open this post in threaded view
|

Re: Producing verifiable initramfs images

Anthony DeRobertis
In reply to this post by Matthew Garrett-4
An interesting challenge you've taken up, I fear it's going to be a lot
of work.

On almost all of my older installs, the initramfs is built with
MODULES=dep, because otherwise /boot runs out of space; the amount of
space MODULES=most takes is ever-increasing. So the kernel packages
plopping a default initramfs in /boot would break those systems (but
that's solvable e.g., by having it be an optional extra binary package)

Even with the default, it's possible to include extra modules — either
by the admin plopping them in /etc/initramfs-tools/modules or I believe
through package hooks. (I'm not sure if it also does the work
MODULES=dep does and adds any extra modules found). But maybe as long as
the kernel is only loading signed modules, it's OK to put additional
modules in an extra, non-TPM-measured archive?

/etc/modprobe.d is included in initramfs. That's going to be challenging
because it can include both configuration and code, and even without the
code, "arbitrary kernel modules loaded with arbitrary options" seems to
big a difference to ignore. And you can't not include this, since
initramfs loads so many modules.

Local udev rules (from /etc/udev/rules.d/) are included as well; they
wind up in /usr/lib/udev/rules.d on the initramfs. Those are again an
interesting combination of configuration and code.

Reply | Threaded
Open this post in threaded view
|

Re: Producing verifiable initramfs images

Matthew Garrett-4
On Thu, Feb 6, 2020 at 12:07 AM Anthony DeRobertis <[hidden email]> wrote:
>
> An interesting challenge you've taken up, I fear it's going to be a lot
> of work.

Heh. It's work we're doing internally, so it'd be good to get it into
an upstream-acceptable form.

> On almost all of my older installs, the initramfs is built with
> MODULES=dep, because otherwise /boot runs out of space; the amount of
> space MODULES=most takes is ever-increasing. So the kernel packages
> plopping a default initramfs in /boot would break those systems (but
> that's solvable e.g., by having it be an optional extra binary package)

Right. Not everyone is going to care about this use case - I'd just
like to enable it. Of course, one approach here would be to provide
two images - one with a minimal set of modules suitable for booting
most systems, and one with a more complete set of modules. It wouldn't
precisely solve the MODULES=dep problem, but it should handle both the
common resource constrained case (most desktop and laptop hardware)
and the case where you probably aren't too worried about the size of
/boot (most servers).

> Even with the default, it's possible to include extra modules — either
> by the admin plopping them in /etc/initramfs-tools/modules or I believe
> through package hooks. (I'm not sure if it also does the work
> MODULES=dep does and adds any extra modules found). But maybe as long as
> the kernel is only loading signed modules, it's OK to put additional
> modules in an extra, non-TPM-measured archive?

Yup, that's definitely an option.

> /etc/modprobe.d is included in initramfs. That's going to be challenging
> because it can include both configuration and code, and even without the
> code, "arbitrary kernel modules loaded with arbitrary options" seems to
> big a difference to ignore. And you can't not include this, since
> initramfs loads so many modules.
>
> Local udev rules (from /etc/udev/rules.d/) are included as well; they
> wind up in /usr/lib/udev/rules.d on the initramfs. Those are again an
> interesting combination of configuration and code.

I think there's two options here:

1) Rather than copy the files in directly, provide an abstraction that
covers the initramfs use cases and generates modprobe.d and udev rules
from static configuration, or:
2) As long as these files don't change frequently, this isn't a
problem - you can ask the user or admin to verify the files and then
flag them as acceptable for future measurements. This is slightly less
helpful, but is still an improvement (ie, you're able to figure out
/which/ files have changed rather than just knowing that something in
the initramfs has changed)