grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Linux DRTM on UEFI platforms


From: Heinrich Schuchardt
Subject: Re: Linux DRTM on UEFI platforms
Date: Thu, 31 Mar 2022 12:59:27 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.7.0

On 3/31/22 09:13, Ard Biesheuvel wrote:
On Thu, 31 Mar 2022 at 02:36, Daniel P. Smith
<dpsmith@apertussolutions.com> wrote:

Greetings Matthew,

First thank you to you and James for taking time out of your busy
schedules to sit down with us and work through all of this.

Hey Ard,

On 3/30/22 03:02, Ard Biesheuvel wrote:>> 1) From an EFI maintainer
perspective, is making the contract between
the boot stub and the kernel explicit viable?


No. The direction of travel has been to define EFI boot only in terms
of the handover from the loader to the stub. What happens next is up
to the architecture, and is deliberately not specified, because it is
considered to be internal Linux ABI. We've deviated from this once for
Xen on ARM, but this means we have already painted ourselves into a
corner when it comes the way we use DT internally at the handover
point between stub and kernel proper, and I am not eager to repeat
that. Locking down the stub-to-kernel protocol for all architectures
is not the way to go.

To help provide some visual context, for EFI today there is,

                                         bzImage
[EFI boot manager] -> [[efi-stub] -> [setup kernel] -> [main kernel]]

Where the efi-stub is responsible for interacting with firmware to
configure the system, store that configuration for the setup kernel and
the main kernel, and then call EBS before entering the setup kernel.

For Secure Launch the flow (on Intel) is,

       CPU instruction                   bzImage
[preamble] -> [ACM] -> [[sl-stub] -> [setup kernel] -> [main kernel]]

In order to make the CPU instruction call to enter the ACM the system
must be in a very specific quiescent state. This includes but not
exhaustively,
   * EBS must have been called
   * TPM should have all localities closed
   * IOMMU PMRs must be programmed appropriately
   * TXT heap space allocated
   * TXT heap space populated with config structures
   * All APs must be in a specific idle state
   * Execution is on the BSP
Carrying all this out is what is considered the DRTM preamble.


Thanks for the explanation, this is really helpful.

This is the wrinkle because the setup kernel and main kernel are both
predicated on the efi-stub and the efi-stub is predicated on running
before EBS.

Matthew suggested this already, but can you explain why handling this
in a callback is not an option? I'd by sympathetic to specifying a

The idea of the UEFI specification is that it is OS agnostic. So anything that is Linux-, Windows-, BSD-, etc. specific should not live in the UEFI firmware.

If you want to implement any Linux specific extra protocol, you should implement it in Shim, GRUB, the kernel stub or any other UEFI binary loaded by the UEFI firmware but, please, don't rely on the UEFI firmware itself to implement it.

If you are able to abstract the requirements for furthering secure boot in a way that is OS agnostic, then implementation in the UEFI firmware starts to make sense. But remember that there is a large installed base that is still lagging behind the current UEFI standard.

Best regards

Heinrich

Linux specific protocol that can be grabbed before EBS() but can be
invoked after (but not, say after SetVirtualAddressMap(), to keep
things simple). That should allow us to call back into firmware to
perform the secure launch right before handing over.

My other suggestion, to use a minimal EFI environment just to boot the
kernel, still seems viable to me as well, but it would boil down to
mostly the same, thing, i.e., to inject an intermediate boot stage
between the call to the firmware's EBS() and calling the entrypoint of
the kernel proper. What I do like about this approach is that the EFI
stub could execute unprivileged, which means the secure launch kernel
could track *exactly* what the EFI stub is doing in terms of memory
accesses and protocol invocations, which seems a bit more robust than
the approximation of 'this might be interesting enough to measure'
that the industry seems to have settled on.

So how can this wrinkle be addressed? The TrenchBoot project
proposed that the information collected by the efi-stub be formally
documented for two reasons, 1. to allow the sl-stub to be aware of what
and where all external data is being injected into the kernel so any
data that may be security critical could be measured, and 2. it would
allow third parties, e.g. GRUB, could correctly configure the system,
pass all EFI related information correctly to the setup kernel and the
main kernel before executing the preamble. Where the former is more of a
concern than enabling the latter.


The reason I am not willing to lock down the stub<->kernel boot
protocol is because it doesn't scale: currently, the discussion is
about x86, which is a bit different because we already so many ways to
boot it, but for other architectures, this is going to create a huge
maintenance burden: arm64, RISC-V and now LoongArch are all adding EFI
boot support and are looking to support ACPI, SMBIOS and other
features as well, and these are all gated on EFI boot, which requires
booting via the stub.

I'm not eager to kick this can down the road and go with something
that inevitably implies either specifying and maintaining a whole
array of internal protocols as external ABI, or revisiting this
discussion and coming up with two different ways to do DRTM depending
on whether you are running x86 or not.

Relating to what information is security critical, this can be a bit
subjective. For example Dave Weston has a twitter thread[1][2][3] over
what state Azure Attestation can validate for a DRTM Windows system.
This reflects what Microsoft believes it's customers will want to
validate about a Windows system before accessing services and data
stored in Azure. For Linux Secure Launch measuring everything would
obviously provide the finest grain of assertions regarding how the
kernel was configured to run but that comes at the expense that is
incurred for taking the measurements. To date the selection of
measurements have been an attempt of balancing the most meaningful
measurements with how many measurements should be taken. For instance it
would be possible to hash the SRTM (firmware) TPM event log to provide
an assertion of what its contents were at dynamic launch. Is that a
meaningful measurement? Not necessarily since there are other means to
validate the log but there is likely someone who is super cautious and
would like to see the extra layer of validation.


So how will the above translate into meaningful and fair feedback in
response to proposed changes to this documented stub<->kernel handover
protocol, once the need arrives to make changes? Is this super
cautious person going to be the one NAKing everything just because he
is super cautious?

Pardon the skepticism, but I am really reluctant to let this cat out
of the bag if the requirements are so vague and there doesn't seem to
consensus on the scope of DRTM.

Another thing I missed is how these systems are supposed to carry out
the tasks that the stub currently handles: Matt mentioned setting
MemoryOverwriteRequest, but there is also TPM event log handling, and
other bits and pieces. Are you saying this is all going to be part of
this boot protocol as well?

2) If so, is it desirable?

3) If either (1) or (2) is "no", is it reasonable to ensure that all
potentially security-critical state or configuration changes to the
boot stub are reviewed by DRTM people to verify whether the secure
launch code needs to be updated to match?

Wouldn't it be better for the secure launch kernel to boot the EFI
entrypoint directly? As it happens, I just completed a PoC last week
for a minimal implementation of EFI (in Rust) that only carries the
pieces that the EFI stub needs to boot Linux. It is currently just a
proof of concept that only works on QEMU/arm64, but it should not be
too hard to adapt it for x86 and for booting a kernel that has already
been loaded to memory.

IIUC, as you can see above, entering the efi-stub from the dynamic
launch will fail because EBS will have been called.


I think you are missing my point here, tbh. What I am suggesting here
is to run a separate, minimal EFI implementation, which has its own
EBS() which is unrelated to the firmware one. Matthew pointed out some
issues with this approach, but the fundamental idea is that it is just
an impedance matcher that looks like EFI to the EFI stub, but is
really just a loader with a memory map and some config tables.

The requirement for this came up in the confidential computing space,
but for bare metal, it seems having a tiny EFI-like shim that can only
boot a Linux kernel (or other EFI-like payloads with no dependencies
on the driver model or other UEFI/PI bloat) might be useful here as
well, especially because it would be completely generic from the EFI
side of things, as opposed to creating yet another project with
intimate knowledge of struct bootparams, device trees, where in memory
the kernel may be loaded on architecture X, where in memory the initrd
may be loaded on architecture X, etc etc.

So the bottom line is that we will have to make this work with EFI
boot one way or the other, but skipping the EFI stub altogether is
really not an option, unless you want to carry the burden of keeping
your code in sync with the kernel. Locking this down as external ABI
is not acceptable to me.

Thanks,
Ard.

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel




reply via email to

[Prev in Thread] Current Thread [Next in Thread]