Re: [RFCv2 0/9] UEFI emulator for kexec

From: Jan Hendrik Farr
Date: Mon Sep 09 2024 - 10:37:14 EST


On 09 16:04:50, Ard Biesheuvel wrote:
>
> [...]
>
> kdump has a kexec kernel 'standby' to launch when the kernel panics.
> So for the UKI/EFI payload case, this would imply that the load
> involves running the payload until EBS() and freezing the state.
>
> Whether execution occurs in true user space or in a deprivileged
> kernel context is an implementation detail, imho. We don't want to run
> external code in privileged mode inside the kernel in any case, as
> this would violate lockdown already. But it should be feasible to have
> a EFI compatible layer in the kernel that invokes the EFI entrypoint
> of an image in a way that protects the host kernel. This could be user
> mode on the CPU or perhaps a minimal KVM virtual machine.

This solution is what I'm currently in favor of (besides my original
approach), see: https://lore.kernel.org/kexec/Zt7EbvWjF9WPCYfn@gardel-login/T/#md4f02b7cb6c694cb28aa8d36fe47a02bd4dc17a4

>From the perspective of supporting UKIs the EFI compatibility layer
definetly has to be run in the kernel not in regular userspace so that
the chain of trust is maintained.

Why do you say that it would have to be a deprivileged kernel context
though? In lockdown mode we would enforce a signature check on the PE
file, so it shouldn't be any different from loading a signed kernel
module from a kernel lockdown perspective, right?

Using KVM is actually something I didn't consider yet, however it would
not work in VMs without nested virtualization.

> The advantage of this approach is that the whole concept of purgatory
> can be avoided - the EFI boot phase runs in parallel with the previous
> kernel, which has full control over authentication and [emulated] PCR
> externsion, and has ultimate control over whether the kexec reboot is
> permitted.

I'm under the impression that we still need some code to run between the
kernels to do two things:

1. Clean up the address space, so that it's what the EFI binary expects
2. Verify a checksum on the saved state in case a kernel panic is the
result of memory corruption

Sure, the majority of the work (running the EFI binary until EBS()) is
done while the old kernel is still running.

>
> [...]
>
> I don't think intermediate kernels are the solution here. We need to
> run as much as possible under the control of the preceding kernel, and
> minimize the bare metal handover that occurs after EBS(). Adding more
> code to the purgatory (as this series does) is not acceptable to me,
> as it is extremely difficult to debug, and duplicates drivers and
> other logic (making it an 'intermediate kernel' of sorts already)

I agree

>
> Today, UKI functionality is implemented in terms of EFI API calls. Any
> solution that needs either a parallel implementation (eBPF vs EFI) or
> needs to unpack the UKI in order to perform the steps that the UKI
> would perform itself if it were executed in an EFI environment is a
> no-go in my opinion.
>
> So either we provide some EFI compatible runtime sufficient to run a
> UKI, or we re-engineer UKI to be built on top of an abstraction that
> can be implemented straight-forwardly both on system firmware and in
> the EFI context.

A solution that can boot UKIs as they exist today is definetly the right
choice. Rewriting them for eBPF and maintaining two implementations is
way less than ideal.