From nobody Sun Feb 8 01:30:12 2026 Received: from mailout3.inleed.net (mailout3.inleed.net [194.14.207.128]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B39931BAEDC for ; Sun, 12 Jan 2025 15:51:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=194.14.207.128 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736697124; cv=none; b=fKaXODQHslOyudO8yWvQVP/LgHgwA39XnyGb0RYOSvdQAlR8xI6FgxyqmwE/DkcQ+fdwZOKMkTrjvtCl4GmcxnpH4G8WqaJbKPZZJe+YV1qWGfjxfHVnIj5uNSpRaAo+r8OfdYSz/abe7KjX2V/tK2NBPNXcYiMG723C3dXCBWo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736697124; c=relaxed/simple; bh=dPKxrRvnncK5gzDaoFPDzvmoakk8aNcTkmEup6rQl7M=; h=Date:From:To:Subject:Message-ID:MIME-Version:Content-Type: Content-Disposition; b=W6fxNjeRbDJMlTHYYZWgBMpuruxGOzsYWumVAj/u/Yt023FYBXGnmfJf3MzrNBRqnG9HL1goRporl+cSu+TZbccX9ySEv2jqBIW2L2uxyPSn7mLaOJLV795Y3eDj4+5qozfdUOVzJb+GDtrZgBZxUXiAKRuDKgSfHD42EfWWnMA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=andraxin.se; spf=pass smtp.mailfrom=andraxin.se; dkim=pass (2048-bit key) header.d=andraxin.se header.i=@andraxin.se header.b=svec2O3g; arc=none smtp.client-ip=194.14.207.128 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=andraxin.se Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=andraxin.se Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=andraxin.se header.i=@andraxin.se header.b="svec2O3g" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=andraxin.se ; s=x; h=Content-Transfer-Encoding:Content-Type:MIME-Version:Message-ID: Subject:To:From:Date:Sender:Reply-To:Cc:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=QCZgjwclcla0COuQsdWpSKtyOIrJ6xCeA1lggt6YQTw=; b=svec2O3gTwCSOPzkhf0WZ6w1TP 3vV16SWp2mn8eK3Ag2+aVnQUfnw6cS0TjKCTeBQU0Tt44NHUAXba4wzYdCVcHXQEaoKtbpBgGrzsU uM91iqJXWClqikOKveC3bTBiUcd62dw7H+LgvVQLGD4cX/1vTevop+T73wgAfaBOMfCO4yc7vqjc1 YMa91DseTLRhfMiCIF6rfLdfA99qwHkdYce7OXUA3GNRUzVf7jk+RFrFXp+sV5rGWP8VP3/LJU5K+ oh0QXbfZSd731oZ33M4wM7Jm4S1czIZBG3h3w2VicnPG3Z03hbOeaPdqeTW4CiCPKGq641zCChrHr eO208X/g==; Received: from c-85-224-10-52.bbcust.telenor.se ([85.224.10.52] helo=localhost) by ns3.inleed.net with esmtpsa (TLS1.3) tls TLS_AES_256_GCM_SHA384 (Exim 4.98) (envelope-from ) id 1tWzdF-00000002y7k-3G1m; Sun, 12 Jan 2025 16:12:05 +0100 Date: Sun, 12 Jan 2025 16:11:25 +0100 From: kernel.org@andraxin.se To: Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , linux-kernel@vger.kernel.org Subject: SBAT support in EFI stub? Message-ID: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="6JZgxZTZW4eYr/ys" Content-Disposition: inline Content-Transfer-Encoding: 8bit X-Authenticated-Id: andras@andraxin.se --6JZgxZTZW4eYr/ys Content-Disposition: inline Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Folks, The problem: *secure boot* directly via EFI stub on a system, where the necessary key management options are not present (disabled by the OEM) in the BIOS. Unless one is prepared to hack that BIOS, following, say https://lukegb.com/posts/2016-11-11-secure-boot-shenanigans/ the standard approach would be to use SHIM (and MOK): https://github.com/rhboot/shim A few years back, CVE-2020-10713 ("BootHole") prompted what one might call a lightweight revocation solution: Secure Boot Advanced Targeting (SBAT). https://github.com/rhboot/shim/blob/main/SBAT.md As a result, SHIM flatly refuses to load an EFI binary without an embedded SBAT section. Adding SBAT to a "plain" kernel, as described, for instance here: https://www.rodsbooks.com/efi-bootloaders/secureboot.html#sbat works fine, but doing the same for a kernel with EFI stub=20 messes up the binary and results in a boot loop. That's, perhaps, not surprising considering that the intervention also changes the file's signature: ``` $ file bzImage-6.12.9-gentoo bzImage-6.12.9-gentoo: Linux kernel x86 boot executable bzImage, version 6.= 12.9-gentoo ... $ objcopy --set-section-alignment '.sbat=3D512' --add-section .sbat=3Dsbat.= csv --adjust-section-vma .sbat+10000000 bzImage-6.12.9-gentoo $ file bzImage-6.12.9-gentoo bzImage-6.12.9-gentoo: PE32+ executable (EFI application) x86-64 (stripped = to external PDB), for MS Windows, 4 sections $ ``` NB: I have NOT tried the `pe-add-sections.py` script linked from https://github.com/rhboot/shim/issues/376#issuecomment-1628004034 but I'd expect similar results to the `objcopy` case above, since the EFI stub is a bit "special" in its construction. BTW, workarounds for secure boot on such a system via OTHER MEANS than EFI stub do exist. One could simply employ a bootloader, or build a Unified Kernel Image using `ukify` that will add both its own "EFIStub" and an SBAT section to a "plain" kernel. https://manpages.debian.org/bookworm-backports/systemd/ukify.1.en.html https://wiki.gentoo.org/wiki/Unified_kernel_image#EFI_stub I realize that wanting to stick with the kernel's built-in EFI stub may be a bit of a niche issue, and I do have a WORKSFORME-level hack to address this for myself (attached, since it's not a proper patch for review, only a conversation starter); so, this isn't high priority. I'm only checking if adding SBAT support may be of general interest. Best, --andr=C3=A1s PS BTW, I wasn't kidding. My current approach_is_ a hack. The included `sbat.csv` is for Gentoo (although simple to adapt). The code blindly uses a fixed (overly large) size for SBAT. The final binary MUST be renamed to `grubx64.efi` (or similar, for 32-bit systems); AND, it MUST be enrolled by hash, since I haven't added any code that might satisfy the "participating bootloader" requirements. https://github.com/rhboot/shim/commit/39df41ceb5a793f7db9233a2741d30c55b6a8= 861 Interestingly, MOK Manager cannot (or doesn't want to?) extract the hash from a signed binary; so, either the hash must be enrolled via `mokutil`, or the kernel can be left unsigned... --6JZgxZTZW4eYr/ys Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="sbat.patch" diff '--color=auto' -ruN linux-6.12.1-gentoo/arch/x86/boot/Makefile linux-6.12.1-gentoo.sbat/arch/x86/boot/Makefile --- linux-6.12.1-gentoo/arch/x86/boot/Makefile 2024-11-22 22:47:28.288743052 +0100 +++ linux-6.12.1-gentoo.sbat/arch/x86/boot/Makefile 2024-11-23 13:39:34.930313632 +0100 @@ -63,9 +63,9 @@ quiet_cmd_image = BUILD $@ silent_redirect_image = >/dev/null cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin \ - $(obj)/zoffset.h $@ $($(quiet)redirect_image) + $(obj)/zoffset.h $(obj)/sbat.csv $@ $($(quiet)redirect_image) -$(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE +$(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/sbat.csv $(obj)/tools/build FORCE $(call if_changed,image) @$(kecho) 'Kernel: $@ is ready' ' (#'$(or $(KBUILD_BUILD_VERSION),`cat .version`)')' @@ -75,6 +75,16 @@ SETUP_OBJS = $(addprefix $(obj)/,$(setup-y)) + +quiet_cmd_sbat = SBAT $@ + cmd_sbat = sed s@%KERNELVERSION%@$(KERNELVERSION)@ $(srctree)/$@ > $@ + + +targets += sbat.csv +$(obj)/sbat.csv: $(srctree)/$@ FORCE + $(call if_changed,sbat) + + sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [a-zA-Z] \(startup_32\|efi.._stub_entry\|efi\(32\)\?_pe_entry\|input_data\|kernel_info\|_end\|_ehead\|_text\|_e\?data\|z_.*\)$$/\#define ZO_\2 0x\1/p' quiet_cmd_zoffset = ZOFFSET $@ diff '--color=auto' -ruN linux-6.12.1-gentoo/arch/x86/boot/header.S linux-6.12.1-gentoo.sbat/arch/x86/boot/header.S --- linux-6.12.1-gentoo/arch/x86/boot/header.S 2024-11-22 22:47:28.291743064 +0100 +++ linux-6.12.1-gentoo.sbat/arch/x86/boot/header.S 2024-11-30 15:33:33.427367030 +0100 @@ -83,9 +83,9 @@ .long ZO__end - ZO__data # SizeOfInitializedData .long 0 # SizeOfUninitializedData - .long setup_size + ZO_efi_pe_entry # AddressOfEntryPoint + .long setup_size + salign + ZO_efi_pe_entry # AddressOfEntryPoint - .long setup_size # BaseOfCode + .long setup_size + salign # BaseOfCode #ifdef CONFIG_X86_32 .long 0 # data #endif @@ -106,7 +106,7 @@ .word 0 # MinorSubsystemVersion .long 0 # Win32VersionValue - .long setup_size + ZO__end # SizeOfImage + .long setup_size + salign + ZO__end # SizeOfImage .long salign # SizeOfHeaders .long 0 # CheckSum @@ -179,15 +179,25 @@ #else .set pecompat_fstart, setup_size #endif + + .ascii ".sbat\0\0\0" + .long salign # SizeOfRawData + .long setup_size # VirtualAddress + .long salign # SizeOfRawData + .long setup_size # PointerToRawData + + .long 0, 0, 0 + .long IMAGE_SCN_ALIGN_512BYTES + .ascii ".text" .byte 0 .byte 0 .byte 0 .long ZO__data - .long setup_size + .long setup_size + salign .long ZO__data # Size of initialized data # on disk - .long setup_size + .long setup_size + salign .long 0 # PointerToRelocations .long 0 # PointerToLineNumbers .word 0 # NumberOfRelocations @@ -198,9 +208,9 @@ .ascii ".data\0\0\0" .long ZO__end - ZO__data # VirtualSize - .long setup_size + ZO__data # VirtualAddress + .long setup_size + salign + ZO__data # VirtualAddress .long ZO__edata - ZO__data # SizeOfRawData - .long setup_size + ZO__data # PointerToRawData + .long setup_size + salign + ZO__data # PointerToRawData .long 0, 0, 0 .long IMAGE_SCN_CNT_INITIALIZED_DATA | \ diff '--color=auto' -ruN linux-6.12.1-gentoo/arch/x86/boot/sbat.csv linux-6.12.1-gentoo.sbat/arch/x86/boot/sbat.csv --- linux-6.12.1-gentoo/arch/x86/boot/sbat.csv 1970-01-01 01:00:00.000000000 +0100 +++ linux-6.12.1-gentoo.sbat/arch/x86/boot/sbat.csv 2024-11-23 13:39:34.930313632 +0100 @@ -0,0 +1,2 @@ +sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md +kernel,1,Gentoo Linux,gentoo-sources,%KERNELVERSION%,https://www.gentoo.org diff '--color=auto' -ruN linux-6.12.1-gentoo/arch/x86/boot/tools/build.c linux-6.12.1-gentoo.sbat/arch/x86/boot/tools/build.c --- linux-6.12.1-gentoo/arch/x86/boot/tools/build.c 2024-11-22 22:47:28.292743068 +0100 +++ linux-6.12.1-gentoo.sbat/arch/x86/boot/tools/build.c 2024-11-30 15:27:50.721048086 +0100 @@ -6,11 +6,15 @@ */ /* - * This file builds a disk-image from three different files: + * This file builds a disk-image from 4 different files: * * - setup: 8086 machine code, sets up system parm * - system: 80386 code for actual system * - zoffset.h: header with ZO_* defines + * - sbat.csv: policy specification for Secure Boot Advanced Targeting + * only needed when CONFIG_EFI_STUB is selected, + * and secure boot is enabled, but does no harm + * to include SBAT in either case * * It does some checking that all files are of the correct type, and writes * the result to the specified destination, removing headers and padding to @@ -43,6 +47,7 @@ /* Minimal number of setup sectors */ #define SETUP_SECT_MIN 5 #define SETUP_SECT_MAX 64 +#define SBAT_SIZE 4096 /* This must be large enough to hold the entire setup */ u8 buf[SETUP_SECT_MAX*512]; @@ -130,7 +135,7 @@ static void usage(void) { - die("Usage: build setup system zoffset.h image"); + die("Usage: build setup system zoffset.h sbat.csv image"); } /* @@ -179,13 +184,13 @@ void *kernel; u32 crc = 0xffffffffUL; - if (argc != 5) + if (argc != 6) usage(); parse_zoffset(argv[3]); - dest = fopen(argv[4], "w"); + dest = fopen(argv[5], "w"); if (!dest) - die("Unable to write `%s': %m", argv[4]); + die("Unable to write `%s': %m", argv[5]); /* Copy the setup code */ file = fopen(argv[1], "r"); @@ -215,8 +220,7 @@ if (fstat(fd, &sb)) die("Unable to stat `%s': %m", argv[2]); if (_edata != sb.st_size) - die("Unexpected file size `%s': %u != %u", argv[2], _edata, - sb.st_size); + die("Unexpected file size `%s': %u != %u", argv[2], _edata, sb.st_size); sz = _edata - 4; kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); if (kernel == MAP_FAILED) @@ -226,6 +230,22 @@ if (fwrite(buf, 1, i, dest) != i) die("Writing setup failed"); + /* Copy CSV for Secure Boot Advanced Targeting (SBAT) */ + file = fopen(argv[4], "r"); + if (!file) + die("Unable to open `%s': %m", argv[4]); + c = fread(buf, 1, sizeof(buf), file); + if (ferror(file)) + die("read-error on SBAT"); + fclose(file); + if (c > SBAT_SIZE) + die("SBAT must be at most %u bytes", SBAT_SIZE); + if (c < SBAT_SIZE) + memset(buf+c, 0, SBAT_SIZE-c); + crc = partial_crc32(buf, SBAT_SIZE, crc); + if (fwrite(buf, 1, SBAT_SIZE, dest) != SBAT_SIZE) + die("Writing SBAT failed"); + /* Copy the kernel code */ crc = partial_crc32(kernel, sz, crc); if (fwrite(kernel, 1, sz, dest) != sz) --6JZgxZTZW4eYr/ys--