F45 Change Proposal: Grub EFI For Confidential Computing (self-contained)

:link: GRUB EFI for Confidential Computing

This is a proposed Change for Fedora Linux.
This document represents a proposed Change. As part of the Changes process, proposals are publicly announced in order to receive community feedback. This proposal will only be implemented if approved by the Fedora Engineering Steering Committee.

Wiki
Announced

:link: Summary

An independent separate incarnation (package) of the GRUB bootloader for UEFI only that contains a minimal number of built-in modules, and can quickly boot a Unified Kernel Image (UKI) using Bootloader Specification (BLS) files. It will be built separately from the main GRUB package, and does not replace it for general usage.

:link: Owner

:link: Detailed Description

There is a need for a smaller, lighter version of the GRUB bootloader on UEFI to support booting sealed bootable container images, such as for Confidential Computing.

Since confidential VMs rely on remote attestation, TPM PCR values need to be stable and predictable over long periods of time. Updating the bootloader results in changes to PCRs, and should therefore be avoided if possible.

Additionally, Unified Kernel Images (UKIs) have become the preferred choice over the regular signed kernel because the whole payload is bundled and signed for Secure Boot, thus removing the vulnerability of the unsigned initramfs. They are used often in virtual environments, for confidential computing, and by CoreOS.

Taken together, the ideal bootloader for these types of environments should be small, light, and not get updated too often. The fewer modules are built-in, the smaller the attack surface, and the less frequent updates need to be. The resulting idea is to create a smaller version of GRUB, the supported bootloader in most Linux environments, for UEFI, which is built as a separate package from the main GRUB build, contains only the modules that are absolutely necessary for VMs, and natively supports UKI loading. This new package is not meant to be a replacement for GRUB for general use; rather it’s an additional package for specific applications.

A separate rpm that is still a part of the grub2 build is already available for x86_64 and aarch64 in Fedora Rawhide for testing. It is signed for Secure Boot with the GRUB key. In the future, it is expected to get its own Secure Boot signing key.

Work is in progress to add support for this new build of GRUB in bootupd to enable safe bootloader updates on bootable container systems: Add support for systemd-boot (and minimal GRUB2 builds) · Issue #1080 · coreos/bootupd · GitHub

:link: Feedback

The original idea was to use systemd-boot for this application, but this was rejected for a number of reasons:

  • While the systemd team can support sd-boot in its present form, they view any additional features as a no-go
  • Although sd-boot is a light and trivial bootloader, it has not been widely tested or fuzzed, like GRUB has been
  • Long term maintenance of more than one bootloader would result in a lack of parity and added technical debt
  • Potential expansion to other architectures would necessitate a compatible bootloader anyway.

The new lighter GRUB build is already being tested by CoreOS, and is generally working as expected. Small changes are still being made, and suggestions for changes are welcome.

:link: Benefit to Fedora

This change will create a minimal UEFI bootloader for virtual environments that can further be tailored for use in those environments. It will natively load UKIs, support Secure Boot, and be a part of a robust and tested bootloader used in many Linux environments.

:link: Scope

  • Proposal owners: The bootloader engineering team needs to create a new GRUB package, separate from the core package that includes all the changes mentioned.

  • Other developers: CoreOS, who will be the main users, at least in the beginning, need to test, provide feedback, and perhaps change some of their workflows as needed.

  • Release engineering: #Releng issue number

  • Policies and guidelines: N/A (not needed for this Change)

  • Trademark approval: N/A (not needed for this Change)

  • Alignment with the Fedora Strategy:

:link: Upgrade/compatibility impact

This is a new package, independent of the normal all-purpose GRUB, so unless a user installs it on purpose, there is no compatibility impact.

:link: Early Testing (Optional)

This new package is designed specifically for VMs that run UEFI firmware, so an x86_64 or aarch64 VM is the environment to use.

:link: Prepare the test environment:

  • Install or create one or more UKIs
    • Install kernel-uki-virt and add a command line addon using ukify, see instructions below
    • Use ukify to create the UKI from scratch, see instructions below
  • If booting with Secure Boot enabled, sign your add-on or UKI, and enroll your public key in the MOK, see instructions below.
    If you will not sign your UKI/addon, don’t forget to disable Secure Boot.
  • Create the /boot/efi/loader/entries directory
  • Create BLS entries in that directory for each UKI. Specify the path to the UKI using the efi keyword, as you normally would use linux for the kernel. A minimal BLS file only needs to have a title and the path to the UKI:

cat /boot/efi/loader/entries/7.0.10-200-UKI.fc45.x86_64.conf title Fedora 45 UKI (7.0.10-200.fc45.x86_64) efi /EFI/Linux/7.0.10-200.fc45.x86_64.efi

:link: (If you don’t feel like doing all of that, you can boot regular kernels instead):

Because this version of GRUB is intended for UKIs, it expects those UKIs to be on the EFI system partition, but it can load a regular kernel too, as long as it’s in the correct place. If you copy a kernel and its initrd from /boot to /boot/efi/EFI/Linux and that kernel’s BLS configuration file from /boot/loader/entries to /boot/efi/loader/entries (and edit it to reflect the correct paths), then it should simply boot as usual.

:link: Test:

cp ./usr/lib/efi/grub2/1:2.12-60.fc45/EFI/fedora/cc/grubx64-cc.efi /boot/efi/EFI/fedora/grubx64.efi

  • Reboot your machine

You should see the GRUB menu with entries for each of the UKIs that you installed. If you press ‘e’ to edit an entry, you should see something like chainloader /path/to/UKI and when you execute any of the entries, they should successfully boot.

You can check the size of the efi, and see that it is smaller than the normal grubx64.efi.

Use the tpm2_pcrread command between reboots of different UKIs to see that the value of PCR8 does not change.

:link: How to build your own UKI addon

The generic UKI that fedora ships has only console=tty0 console=ttyS0 on its kernel command line. In order for it to actually boot on your system, it needs more information, like the root filesystem UUID, which you can see if you # cat /proc/cmdline. Since the UKI already has the command line bundled, you need to create a command line addon containing the additional information. You can do this using the ukify command. First get the generic UKI by installing kernel-virt-uki and the command by installing systemd-ukify. Then something like this should work:

ukify build \ -cmdline “$(cat /proc/cmdline | cut -d’ ’ -f2-6)” \ –output set_root.unsigned.addon.efi

You then need to copy the addon to the UKI’s extra.d directory in /boot/efi/EFI/Linux/ if you want to only apply it to a single UKI, or create /boot/efi/loader/addons/ and copy it there, if you want it to work for all UKIs. (If you are planning to sign the addon, wait to move it until after you have signed it.)

:link: How to build your own UKI

You can build your own UKI using kernels and initrds that you already have installed on your system once you have also installed systemd-ukify. Building one for the running kernel using the ukify command, looks like this:

ukify build \ –linux /usr/lib/modules/$(uname -r)/vmlinuz \ –initrd /boot/initramfs-$(uname -r).img \ –uname $(uname -r) \ –cmdline “$(cat /proc/cmdline | cut -d’ ’ -f2-6)” \ –output kernel-$(uname -r | rev | cut -d’.’ -f3-6 | rev)-UKI.efi \ –profile “kernel $(uname -r | rev | cut -d’.’ -f3-6 | rev) UKI (Fedora $(cat /etc/os-release | grep VERSION_ID | sed -e ‘s/VERSION_ID=//g’))”

You then need to copy the UKI to the correct directory. Typically this is /boot/efi/EFI/Linux/ but can be the directory of your choosing, as long as you specify that in the UKI’s BLS file. (If you are planning to sign the UKI, wait to move it until after you have signed it.)

:link: How to sign for Secure Boot

It’s actually possible to sign your UKI or addon during the ukify build, but this more generic procedure can be used to sign any artifact for Secure Boot.

Install openssl and pesign and generate your signing key:

openssl req -quiet -newkey rsa:4096 -nodes \ -keyout custom_db.key -new -x509 -sha256 -days 3650 \ -subj “/CN=UKI Signing key/” \ –outform DER -out custom_db.der

In this case the key size is 4096 bit, uses RSA for encryption, and can be used for signing for 10 years.

Import the public key into the NSS database that pesign uses and give it a nickname:

certutil -A -t “,” -d /etc/pki/pesign -n \ ‘My Secureboot Signer’ -i custom_db.der

Convert the public and private keys to PKCS12 format and import the result to enable signing using pesign:

openssl pkcs12 -export -out custom_db.pfx \ -inkey custom_db.key -in custom_db.der

pk12util -i custom_db.pfx \ -d/etc/pki/pesign -n ‘My Secureboot Signer’

Sign your UKI or addon with your private key:

pesign --certificate ‘My Secureboot Signer’ \ –in set_root.unsigned.addon.efi \ –out set_root.addon.efi --sign

Move or copy the UKI or addon to the proper directory, see above.

Import your public key into the Machine Owner Key (MOK) database:

mokutil --import custom_db.der

You will be asked to create a password. You need to reboot the machine to complete the enrollment, and you will be asked for this password at that time.

After rebooting, you can check that your key is actually in the MOK database:

mokutil --list-enrolled

:link: Dependencies

N/A as this is a new package.

:link: Documentation

N/A (not a System Wide Change) or to be determined.

:link: Release Notes

To be determined.

Last edited by @amoloney 2026-06-11T18:53:43Z

Last edited by @amoloney 2026-06-11T18:53:43Z

2 Likes

How do you feel about the proposal as written?

  • Strongly in favor
  • In favor, with reservations
  • Neutral
  • Opposed, but could be convinced
  • Strongly opposed
0 voters

If you are in favor but have reservations, or are opposed but something could change your mind, please explain in a reply.

We want everyone to be heard, but many posts repeating the same thing actually makes that harder. If you have something new to say, please say it. If, instead, you find someone has already covered what you’d like to express, please simply give that post a :heart: instead of reiterating. You can even do this by email, by replying with the heart emoji or just “+1”. This will make long topics easier to follow.

Please note that this is an advisory “straw poll” meant to gauge sentiment. It isn’t a vote or a scientific survey. See About the Change Proposals category for more about the Change Process and moderation policy.

I’m not so much opposed to “light grub variant” per se, but the proposal seems to be giving up on the idea of systemd-boot (or something else) as a new and lean boot loader.
grub does (too) many things and is “organically grown” (legacy), and I’m not convinced that chopping off some parts leads us into a sustainable direction.

6 Likes

I find the points against systemd-boot to not be very convincing.

This feels contradictory to the idea of limiting GRUB features. Are there some features that you want to keep for this minimal GRUB that aren’t present in sd-boot?

Citation needed. Also, it’s not like systemd-boot is something entirely new and unused. Trying to guess which is more secure by popularity seems like reading tea leaves.

This is a more convincing point, but unless the regular GRUB configuration is limited to only using features that are available to the minimal configuration, there is still a risk of feature disparity.

Could you elaborate on this? Is there some architecture candidate for support that is or surely will be supported by GRUB but not sd-boot?

3 Likes

I am not convinced this is the way to go, if we are targeting UEFI environments, we should probably look at using a lean EFI binary that has the smallest footprint possible. Specially given the domain.

We already ship systemd-boot and ukiboot which, even if GRUB is trimmed down, they are still considerably smaller in size compared to those two.

GRUB is already a high value target for security researchers and we probably want to reduce the amount of places we use it on rather than using it in more use cases.

As per the reasons to reject systemd-boot I don’t think they are strong. I think that if we compare shipped code size and historic CVEs in GRUB2, we will see that the burden of maintaining a GRUB variant is likely higher than the burden of supporting systemd-boot in an additional use case that is very limited in scope. UKIboot could be another option that we are supporting in AutoSD and Fedora IoT.

As per other architectures, the only one that’d be relevant for GRUB is PowerVM if they ever shipped confidential computing features. It would make sense to use a minimal build of grub if that ever happened, but I don’t think we should burden the UEFI user base with yet another use case for GRUB.

4 Likes

I didn’t read the rest of the proposal yet, but the part about sd-boot is divorced from reality.

The upstream UKI specification is being extended regularly with new features, and systemd-boot and systemd-stub are extended with new features regularly.

https://github.com/systemd/systemd/blob/main/NEWS is the authorative source.

I asked an llm to filter the list for sd-boot over the last few releases. FWIW, here is its output:

v261 (in development)

  • Will never auto-boot a non-default UKI profile (prevents accidental boots into alternative profiles after a timeout expiry).

v260

  • Boot menu timeout configurable via SMBIOS Type 11 string io.systemd.boot.timeout=.
  • New LoaderEntryPreferred setting, similar to LoaderEntryDefault but takes boot-assessment into account and skips entries with tries-left=0.

v259

  • Log levels supported, set via log-level= in loader.conf or SMBIOS Type 11 io.systemd.boot.loglevel=.
  • loader.conf gained secure-boot-enroll-timeout-sec= for SecureBoot key enrollment timeout.
  • Boot Loader Specification Type #1 entries gained a profile field for selecting a profile in multi-profile UKIs.
  • (Removal: TPM 1.2 support dropped.)

v258

  • Two new BLS Type #1 stanzas: uki and uki-url (the latter for HTTP/HTTPS-hosted UKIs).
  • Looks for SMBIOS Type #11 io.systemd.boot.entries-extra= to synthesize additional boot menu entries.
  • loader.conf gained reboot-on-error setting (reboot vs. show menu when boot fails).
  • loader.conf gained secure-boot-enroll-action (reboot or shut down after auto-enrollment).
  • Honors new LoaderSysFail EFI variable to pick a fallback entry on firmware-reported system failure.
  • Sets LoaderTpm2ActivePcrBanks EFI variable advertising the available TPM2 PCR banks.

v257

  • Menu now reacts to volume up/down rocker presses the same as arrow up/down (useful on phones).

v256

  • Passing additional kernel cmdline via SMBIOS Type #11 io.systemd.boot.kernel-cmdline-extra (now also applies to BLS Type #1 entries, not just stub).
  • Automatic SecureBoot enrollment gained dbx enrollment support (previously db/KEK/PK only), plus UEFI “Custom” and “Audit” modes.

v255

  • New hotkeys “B” (reboot) and “O” (poweroff) in the boot menu, with auto-reboot/auto-poweroff loader.conf options to show them as menu entries.
  • New menu-disabled value for set-timeout (fully disables menu including hotkey).
  • Measures content of loader.conf into TPM2 PCR 5.
  • systemd-boot and systemd-stub now use distinct SBAT project keys for independent revocation.
  • No longer loads unverified DeviceTree blobs under UEFI SecureBoot (CVE fix: GHSA-6m6p-rjcq-334c).

v254

  • gnu-efi build dependency dropped; pyelftools is now used to perform ELF→PE relocations at build time.

v253

  • Passes random seed directly to the kernel via the LINUX_EFI_RANDOM_SEED_TABLE_GUID config table (seeds the RNG very early).
  • Passes a disk-backed random seed even under SecureBoot when EFI RNG protocol (or prior bootloader seed) is available.
  • systemd-boot-system-token.service renamed to systemd-boot-random-seed.service and now always refreshes the ESP seed.
  • Seed inputs handled with a domain- and field-separated hashing scheme.
  • random-seed-mode option removed (a system token is always required).
  • Can now be loaded from outside the ESP (e.g. direct kernel boot under QEMU, embedded in firmware).
  • Parses SMBIOS info to detect virtualization (skip irrelevant warnings, etc.).
  • New if-safe mode that performs auto SecureBoot enrollment only when “safe” (currently: in a VM).

v252

  • UEFI monotonic boot counter mixed into the updated random seed file (extra entropy).
  • EFI mixed-mode boot supported (64-bit kernel over 32-bit UEFI firmware).
  • (Experimental) Automatic SecureBoot key enrollment from files staged on the ESP, in force or manual modes.

In fact, this list gives a misleading impression, since it covers sd-boot only. sd-boot is actually just the menu, so there isn’t that much to do. The interesting stuff happens in sd-stub, i.e. the part that is attached to the kernel image to form an UKI.

  • Although sd-boot is a light and trivial bootloader, it has not been widely tested or fuzzed

It is fairly widely used. The code is fuzzed through oss-fuzz. (Not as extensively as it should be. Nevertheless, a blanket statement that is is not fuzzed is unsubstantiated.)

  • Long term maintenance of more than one bootloader would result in a lack of parity and added technical debt

Maybe. One could also argue that maintenance of systemd is “light and trivial” and not much of an issue


  • Potential expansion to other architectures would necessitate a compatible bootloader anyway.

This one is somewhere between misleading and wrong. sd-boot supports multiple architectures (7 atm.) and new ones could be added. The majority of code is portable C. A bigger limitation is that sd-boot only supports UEFI architectures. But if we expand to new architectures, they are very likely to support UEFI.

It’s actually good to make a comparison with the alternative projects in a proposal, but please try to be factual.

1 Like

efi /EFI/Linux/7.0.10-200.fc45.x86_64.efi

The appropriate type for UKIs is uki, not efi c.f. https://uapi-group.org/specifications/specs/boot_loader_specification/#type-1-boot-loader-entry-keys

Systemd recently gained (in upcoming systemd 261) bootctl link. This is a command to create a type#1 entry referring to a UKI. Please check it this works for your usecase.

--cmdline "$(cat /proc/cmdline | cut -d' ' -f2-6)"

This is very iffy and fragile. I assume that the goal it to filter out the initrd=
 param at the beginning and something else at the end (??). It would be much better to extend ukify to support this natively. (Maybe as --cmdline=auto or --cmdline=current or a new option, details TBFO.) Please talk with the upstream about this.

1 Like

With /etc/kernel/install.conf containing

BOOT_ROOT=/efi
layout=uki
initrd_generator=dracut
uki_generator=ukify

an uki kernel is generated and signed automatically by the scripts in /usr/lib/kernel. That works great for a couple of releases already.

The only problems I see with sd-boot are

  • you can’t make it pretty
  • It can’t boot in classical BIOS mode
1 Like

I don’t think this necessarily gives up on sd-boot, but it makes more sense to me to start from something that works in the scenarios that we need it to work in, and remove stuff, than start with something minimal and having to add untested code to it.

If we weren’t already using and supporting GRUB in so many different environments, I would agree that adopting it for this case doesn’t make sense. But given the amount of investment that has already been made in GRUB, our work and expertise, and all the fuzzing and testing that it has already undergone, I believe this application is sound.

The point was not that some feature is missing now, but that if anything were to be lacking, it would not be implemented. And I’m not referring here to the upstream implementation.

It’s true I’m not familiar with sd-boot fuzzing, but I am aware of a number of such efforts for GRUB. The more that a program is used and tested and fuzzed, the more we know about its bugs and vulnerabilities.

Development and necessary fixes will continue in GRUB, but since this build would be limited, it simply wouldn’t need as frequent updates since it is smaller in scope.

sd-boot is UEFI-only while GRUB natively supports many other arches. The change, as written, is specific to UEFI, but it can be extended.

Why don’t you think a possible missing feature would not be implemented?
Is this more systemd FUD?

Are you planning on find out what fuzzing and testing is done?

If anything, I feel like the fact Fedora has at times carried quite a few patches for GRUB as they slowly wound their way upstream makes GRUB look like the bootloader that isn’t looking to grow new features, not systemd-boot.

And given how many comments Lennart has made about systemd-boot specifically not growing features like additional filesystem drivers for the express purpose of not growing the attack surface, and that this is an effort to strip down GRUB to also reduce the attack surface, it really feels like reinventing a wheel just to avoid to systemd-boot for reasons which have already been mostly discounted.

2 Likes

Because that’s what we were told by RHEL/fedora systemd maintainers.

I will find out more, yes.

For a long time the GRUB upstream was not functioning at all, and once it started functioning, a number of years ago, it was slow and manual. That’s the reason that fedora has so many downstream patches. This year GRUB upstream moved to gitlab, has much better CI, become more accessible and much more lively.

We believe in a community approach that supports the things that people need and want, including support for various filesystems for those that want that, and a slimmer package with a smaller surface for those that want that.

On Fedora devel mailing list the systemd folks have denied this.

There seems to be a communications problem


1 Like

They (Fedora systemd maintainer) alson replied here saying that this isn’t the case so I wonder who got spoken to and what was said.

1 Like

IMO in the long term would be better to use GRUB in less contexts. GRUB is not used everywhere in Fedora/RHEL either, for example is not used in s390x or bare metal ppc64le.

2 Likes

It is also the default in openSUSE Tumbleweed since the past couple of months as well: https://lists.opensuse.org/archives/list/factory@lists.opensuse.org/thread/4ZPQU7PV3ODS7WELADHE7F3SVBQDFIOP/

2 Likes

Note that the testing instructions in the change are just for testing and do not fully correspond to the logic for sealed bootable container images that we are working on in bootc, which triggered this change request.

In this case however, bootc is still using efi as the work started before the uki key was added to the specification and we forgot to update that. I’ve filed: composefs: Use `uki` key for Type 1 configs pointing to a UKI · Issue #2263 · bootc-dev/bootc · GitHub to track that.

Reading https://github.com/systemd/systemd/pull/41543, I don’t think this fits our use case right now notably because we want to control the order of the boot entries precisely. But this is something we should look at and consider extending.