From: Luca Boccassi Date: Mon, 14 Jul 2025 23:52:01 +0000 (+0100) Subject: stub: restore compatibility for shim (< 16.0) -> UKI case X-Git-Tag: v258-rc1~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=23d56ae890f8e7c8e29ef51e05494e445725d3ff;p=thirdparty%2Fsystemd.git stub: restore compatibility for shim (< 16.0) -> UKI case It is possible to boot directly a UKI from shim, and Fedora Cloud Base UKI does exactly this. This used to work fine until https://github.com/systemd/systemd/pull/37372 which broke compatibility when shim < 16.0 (no loader protocol override) is used. Shim 15.8 is still in use in several distributions, and will be for a long time. Restore a part of the previous implementation, and if running with secure boot enabled, and with shim but < 16.0, apply a security override. Follow-up for cab9c7b5a42effa8a45611fc6b8556138c869b5f Fixes https://github.com/systemd/systemd/issues/38104 --- diff --git a/src/boot/linux.c b/src/boot/linux.c index 1e8fe15bd1b..655d151481b 100644 --- a/src/boot/linux.c +++ b/src/boot/linux.c @@ -22,6 +22,28 @@ #define STUB_PAYLOAD_GUID \ { 0x55c5d1f8, 0x04cd, 0x46b5, { 0x8a, 0x20, 0xe5, 0x6c, 0xbb, 0x30, 0x52, 0xd0 } } +typedef struct { + const void *addr; + size_t len; + const EFI_DEVICE_PATH *device_path; +} ValidationContext; + +static bool validate_payload( + const void *ctx, const EFI_DEVICE_PATH *device_path, const void *file_buffer, size_t file_size) { + + const ValidationContext *payload = ASSERT_PTR(ctx); + + if (device_path != payload->device_path) + return false; + + /* Security arch (1) protocol does not provide a file buffer. Instead we are supposed to fetch the payload + * ourselves, which is not needed as we already have everything in memory and the device paths match. */ + if (file_buffer && (file_buffer != payload->addr || file_size != payload->len)) + return false; + + return true; +} + static EFI_STATUS load_via_boot_services( EFI_HANDLE parent, EFI_LOADED_IMAGE_PROTOCOL* parent_loaded_image, @@ -43,6 +65,19 @@ static EFI_STATUS load_via_boot_services( _cleanup_free_ EFI_DEVICE_PATH* file_path = device_path_replace_node(parent_loaded_image->FilePath, NULL, &device_node.Header); + /* When running with shim < v16 and booting a UKI directly from it, without a second stage loader, + * the shim verify protocol needs to be called or it will raise a security violation when starting + * the image (e.g.: Fedora Cloud Base UKI). TODO: drop once support for shim < v16 is not needed. */ + if (!shim_loader_available()) + install_security_override( + validate_payload, + &(ValidationContext) { + .addr = kernel->iov_base, + .len = kernel->iov_len, + .device_path = file_path, + }); + + err = BS->LoadImage(/* BootPolicy= */false, parent, file_path, @@ -50,6 +85,9 @@ static EFI_STATUS load_via_boot_services( kernel->iov_len, &kernel_image); + if (!shim_loader_available()) + uninstall_security_override(); + if (err != EFI_SUCCESS) return log_error_status(EFI_LOAD_ERROR, "Error loading inner kernel with shim: %m"); @@ -131,7 +169,7 @@ EFI_STATUS linux_exec( * * See https://github.com/rhboot/shim/blob/main/README.md#shim-loader-protocol */ - if (secure_boot_enabled() && shim_loader_available()) + if (secure_boot_enabled() && (shim_loader_available() || shim_loaded())) return load_via_boot_services( parent, parent_loaded_image,