efi: zboot specific mechanism for embedding SBAT section
authorVitaly Kuznetsov <vkuznets@redhat.com>
Tue, 13 May 2025 12:58:07 +0000 (14:58 +0200)
committerArd Biesheuvel <ardb@kernel.org>
Wed, 21 May 2025 13:31:42 +0000 (15:31 +0200)
SBAT is a mechanism which improves SecureBoot revocations of UEFI binaries
by introducing a generation-based technique. Compromised or vulnerable UEFI
binaries can be prevented from booting by bumping the minimal required
generation for the specific component in the bootloader. More information
on the SBAT can be obtained here:

https://github.com/rhboot/shim/blob/main/SBAT.md

Upstream Linux kernel does not currently participate in any way in SBAT as
there's no existing policy in how SBAT generation number should be
defined. Keep the status quo and provide a mechanism for distro vendors and
anyone else who signs their kernel for SecureBoot to include their own SBAT
data. This leaves the decision on the policy to the vendor. Basically, each
distro implementing SecureBoot today, will have an option to inject their
own SBAT data during kernel build and before it gets signed by their
SecureBoot CA. Different distro do not need to agree on the common SBAT
component names or generation numbers as each distro ships its own 'shim'
with their own 'vendor_cert'/'vendor_db'

Implement support for embedding SBAT data for architectures using
zboot (arm64, loongarch, riscv). Put '.sbat' section in between '.data' and
'.text' as the former also covers '.bss' and thus must be the last one.

Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
drivers/firmware/efi/Kconfig
drivers/firmware/efi/libstub/Makefile.zboot
drivers/firmware/efi/libstub/zboot-header.S
drivers/firmware/efi/libstub/zboot.lds

index 5fe61b9ab5f969ca4fd9c15b0528f03824f9d62f..db8c5c03d3a2547b3806ca5aff247a3e6e427f9b 100644 (file)
@@ -281,6 +281,30 @@ config EFI_EMBEDDED_FIRMWARE
        bool
        select CRYPTO_LIB_SHA256
 
+config EFI_SBAT
+       def_bool y if EFI_SBAT_FILE!=""
+
+config EFI_SBAT_FILE
+       string "Embedded SBAT section file path"
+       depends on EFI_ZBOOT
+       help
+         SBAT section provides a way to improve SecureBoot revocations of UEFI
+         binaries by introducing a generation-based mechanism. With SBAT, older
+         UEFI binaries can be prevented from booting by bumping the minimal
+         required generation for the specific component in the bootloader.
+
+         Note: SBAT information is distribution specific, i.e. the owner of the
+         signing SecureBoot certificate must define the SBAT policy. Linux
+         kernel upstream does not define SBAT components and their generations.
+
+         See https://github.com/rhboot/shim/blob/main/SBAT.md for the additional
+         details.
+
+         Specify a file with SBAT data which is going to be embedded as '.sbat'
+         section into the kernel.
+
+         If unsure, leave blank.
+
 endmenu
 
 config UEFI_CPER
index 48842b5c106b83a26cfc7fd7e2dfe95f85a289e4..92e3c73502ba15b76b32e8d94493d69ca1278cc4 100644 (file)
@@ -44,6 +44,10 @@ AFLAGS_zboot-header.o += -DMACHINE_TYPE=IMAGE_FILE_MACHINE_$(EFI_ZBOOT_MACH_TYPE
 $(obj)/zboot-header.o: $(srctree)/drivers/firmware/efi/libstub/zboot-header.S FORCE
        $(call if_changed_rule,as_o_S)
 
+ifneq ($(CONFIG_EFI_SBAT_FILE),)
+$(obj)/zboot-header.o: $(CONFIG_EFI_SBAT_FILE)
+endif
+
 ZBOOT_DEPS := $(obj)/zboot-header.o $(objtree)/drivers/firmware/efi/libstub/lib.a
 
 LDFLAGS_vmlinuz.efi.elf := -T $(srctree)/drivers/firmware/efi/libstub/zboot.lds
index fb676ded47fa43413240f8d78349cd5538b98fd6..e02247458b650931fecddff9e6a8d08522a78079 100644 (file)
@@ -123,11 +123,29 @@ __efistub_efi_zboot_header:
                        IMAGE_SCN_MEM_READ | \
                        IMAGE_SCN_MEM_EXECUTE
 
+#ifdef CONFIG_EFI_SBAT
+       .ascii          ".sbat\0\0\0"
+       .long           __sbat_size
+       .long           _sbat - .Ldoshdr
+       .long           __sbat_size
+       .long           _sbat - .Ldoshdr
+
+       .long           0, 0
+       .short          0, 0
+       .long           IMAGE_SCN_CNT_INITIALIZED_DATA | \
+                       IMAGE_SCN_MEM_READ | \
+                       IMAGE_SCN_MEM_DISCARDABLE
+
+       .pushsection ".sbat", "a", @progbits
+       .incbin CONFIG_EFI_SBAT_FILE
+       .popsection
+#endif
+
        .ascii          ".data\0\0\0"
        .long           __data_size
-       .long           _etext - .Ldoshdr
+       .long           _data - .Ldoshdr
        .long           __data_rawsize
-       .long           _etext - .Ldoshdr
+       .long           _data - .Ldoshdr
 
        .long           0, 0
        .short          0, 0
index 9ecc57ff5b451b847c67d36285cd72dd10b229e2..c3a166675450d52c096c4dd717e3a6f0dade56db 100644 (file)
@@ -29,7 +29,17 @@ SECTIONS
                . = _etext;
        }
 
+#ifdef CONFIG_EFI_SBAT
+        .sbat : ALIGN(4096) {
+               _sbat = .;
+               *(.sbat)
+               _esbat = ALIGN(4096);
+               . = _esbat;
+       }
+#endif
+
        .data : ALIGN(4096) {
+               _data = .;
                *(.data* .init.data*)
                _edata = ALIGN(512);
                . = _edata;
@@ -52,3 +62,4 @@ PROVIDE(__efistub__gzdata_size =
 
 PROVIDE(__data_rawsize = ABSOLUTE(_edata - _etext));
 PROVIDE(__data_size = ABSOLUTE(_end - _etext));
+PROVIDE(__sbat_size = ABSOLUTE(_esbat - _sbat));