Re: [PATCH v3 4/6] efi/libstub: implement generic EFI zboot

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

 



On Fri, 19 Aug 2022 at 09:41, Heinrich Schuchardt
<heinrich.schuchardt@xxxxxxxxxxxxx> wrote:
>
> On 8/19/22 09:07, Ard Biesheuvel wrote:
> > On Fri, 19 Aug 2022 at 09:01, Heinrich Schuchardt
> > <heinrich.schuchardt@xxxxxxxxxxxxx> wrote:
> >>
> >> On 8/19/22 08:52, Ard Biesheuvel wrote:
> >>> On Fri, 19 Aug 2022 at 07:29, Heinrich Schuchardt
> >>> <heinrich.schuchardt@xxxxxxxxxxxxx> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 8/18/22 19:10, Ard Biesheuvel wrote:
...
> >>>>> What we could do is define a vendor GUID for the decompressed kernel,
> >>>>> and create a device path for it. That way, you can grab the
> >>>>> loaded_image of the parent to obtain this information.
> >>>>>
> >>>>> What did you have in mind as a use case?
> >>>>
> >>>> The device-path could be used in the kernel log.
> >>>>
> >>>> It can be used to find the device or folder with initrd where we use
> >>>> initrd= on the command line.
> >>>>
> >>>> You could use the device path to access the original file, e.g. to read
> >>>> additional information.
> >>>>
> >>>> For all use cases you would want to have the original device path.
> >>>>
> >>>
> >>> What we could do is:
> >>>
> >>> - define a device path in the decompressor, e.g.,
> >>>
> >>> <original device path>/Offset(<start>, <end>)/VendorMedia(xxx-xxx-xxx,
> >>> <compression type>)
> >>>
> >>> where start, end and compression type describe the compressed payload
> >>> inside the decompressor executable. (The compression type could be
> >>> omitted, or could be a separate node.)
> >>>
> >>> - install the LoadFile2 protocol and the device path protocol onto a
> >>> handle, and move the decompression logic into the LoadFile2
> >>> implementation
>
> Why would you create a LoadFile2 implementation if the decompressor is
> the only user? In this case I think an internal function call is more
> adequate.
>

You argued that you would want to access the original file, no? When
using the SourceBuffer argument to LoadImage(), the original data is
gone. When you pass a LoadFile2 protocol, you can use the device path
to reload the data (compressed or uncompressed) as needed.

> A LoadFile2 protocol would make sense if the compressed image contains
> both a compressed kernel and the initrd and you wanted to provide the
> initrd via the LoadFile2 protocol.
>

The initrd loading is a completely separate issue, and the fact that
we might use LoadFile2 for both is just a coincidence.

> For Iot use cases it would make sense to have a standalone process which
> you can use to:
>
> * compress a kernel
> * create a binary containing
> * * a prepended decompressor binary
> * * the compressed kernel
> * * an optional initrd
> * * an optional device-tree
> * sign the complete file
>
> At runtime the decompressor would:
>
> * decompress the kernel
> * create a LoadFile2 protocol for the initrd
> * call the firmware to fix-up the device-tree
> * install the fixed-up device-tree
> * invoke the EFI stub of the kernel
>
> This way we could have one binary where all relevant components are
> inside a single signed image.
>

The only generic and portable way to move data into memory and execute
it as code is using LoadImage/StartImage. Everything else is a hack,
and hacks are notoriously non-portable between architectures and
firmware implementations.

This means the 'inner' executable *must* be invoked using
LoadImage/StartImage, which implies it must be signed if secure boot
is enabled.

Fixing up the device tree is tied to specific architectures, and the
notion that the OS should be involved in poking the firmware at the
right time to fix it up is also highly arch dependent. Which means it
does not belong in a generic EFI decompressor either.

What you are describing is essentially the systemd-stub, which also
omits LoadImage/StartImage, which means it has to parse the PE/COFF
image, load the sections, apply the relocations, etc etc, all of which
it surely got correct right off the bat ...

The reason I am so adamant about this is that we are digging ourselves
into a hole here, and the more instances we add of this pattern, the
more difficult it is to reason about it, and to fix it when things
break.

Shim should not need to exist, but we all know it has to. But ideally,
it would only hook LoadImage/StartImage to interpose its own
implementations, leaving subsequent stages none the wiser. I
personally find it very disappointing that distro GRUB cannot work
without shim even if the distro's signing key is in db - this is a
missed opportunity imo.

But if we repeat this pattern at every level above it, (i.e., open
code PE app launch to avoid using LoadImage/StartImage), reasoning
about secure boot and measured boot becomes very difficult, and every
stage needs to invoke the TCG protocols directly etc etc



[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux