Message ID | 20250305101744.1706803-1-vkuznets@redhat.com |
---|---|
State | New |
Headers | show |
Series | [RFC] x86/efi: Add a mechanism for embedding SBAT section | expand |
Hi Vitaly, Thanks for the elaborate writeup On Wed, 5 Mar 2025 at 11:18, Vitaly Kuznetsov <vkuznets@redhat.com> wrote: > > 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 > > Previously, an attempt was made to add ".sbat" section to the linux kernel: > > https://lwn.net/Articles/938422/ > > The approach was rejected mainly because currently there's no policy on how > to update SBAT generation number when a new vulnerability is discovered. In > particular, it is unclear what to do with stable kernels which may or may > not backport certain patches making it impossible to describe the current > state with a simple number. > > This patch suggests a different approach: instead of defining SBAT > information, provide a mechanism for downstream kernel builders (distros) > to include their own SBAT data. Why does this require a mechanism in the upstream kernel at all? Signing the kernel (which includes appending a cert table) does not require such changes, so why is this needed when adding an additional PE/COFF section? > This leaves the decision on the policy to > the distro vendors. 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'. Linux > upstream will never, ever need to care about the data unless they choose in > the future to participate in that way. > I'm sure this paragraph will make some skeptics happy. > Currently, shim checks .sbat data for itself in self-test and for second > stage bootloaders (grub, sd-boot, UKIs with sd-stub, ...) but kernel > revocations require cycling signing keys or adding kernel hashes to shim's > internal dbx. Adding .sbat to kernel and enforcing it on kernel loading > will allow us to do the same tracking and revocation distros are already > doing with a simplified mechanism, and without having to keep lists of > kernels outside of the git repos. > > Finding a place for SBAT section turned out to be a bit tricky. Current > PE layout looks like this: > > - without CONFIG_EFI_MIXED: > +-----------------------------------+-------------------------------+ > | setup [setup_signature]| compressed text | data [crc32]| > +-----------------------------------+-----------------+-------------+ > > - with CONFIG_EFI_MIXED: > +-------+---------------------------+----------------+-------------+ > | setup | pecompat [setup_signature]| compressed text| data [crc32]| > +-------+---------------------------+----------------+-------------+ > > Limitations are: > - To avoid problems with signatures, all sections must be 4k aligned with > no gaps between them. > - CRC32 must be at the end of the file. We never cared about the CRC32 before with signed EFI images, which gets clobbered when the image is signed. Why should we start caring about it now? > - Nothing can be put before 'setup'. > - Nothing can be squeezed between [setup_signature] and compressed text. > - The whole 'setup' (everything before '.text') must fit into 8 4k pages. > > Note: .pecompat contains only 8 bytes of useful data but to save the space, > the tail from .setup including [setup_signature] is also added to it (see > commit 1ad55cecf22f ("x86/efistub: Use 1:1 file:memory mapping for PE/COFF > .compat section")). > > With the limitations, there are three straightforward options: > - Put .sbat between .setup and .pecompat. Advantage: with normal sized > SBAT, kernel grows by 1 page only. Disadvantage: this one page comes from > the precious '8 pages' limit. > > - Put .sbat to the very end of the file. Advantage: no need to touch > 'setup'. Disadvantage: two pages are now needed as we don't want to make > CRC32 part of the SBAT section. > > - Put .sbat between '.text' and '.data'. Advantages: no need to touch > 'setup' and CRC32. 'CONFIG_EFI_MIXED' case doesn't seem to make much > difference either. > > Implement the last one as it doesn't seem to have obvious disadvantages. > > Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> > --- > RFC part: > - General acceptance of the idea. > - .sbat section placement. > > The implementation is done for x86 only at this moment but I think it > shouldn't be that hard to extend it to other arches (and I hope the > solution for those which use common zboot mechanism will be the same). Please don't create a special case for x86 again - iff this needs to be in upstream (which I am not convinced about) it needs to be implemented for all architectures. So I'd like to understand better what is preventing you from appending a PE/COFF section on an arbitrary bzImage (or EFI zboot image). Given an arbitrary PE/COFF image, I see Section { Number: 4 Name: .data (2E 64 61 74 61 00 00 00) VirtualSize: 0x47000 VirtualAddress: 0x934000 RawDataSize: 4608 PointerToRawData: 0x934000 PointerToRelocations: 0x0 PointerToLineNumbers: 0x0 RelocationCount: 0 LineNumberCount: 0 Characteristics [ (0xC0000040) IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) IMAGE_SCN_MEM_READ (0x40000000) IMAGE_SCN_MEM_WRITE (0x80000000) ] as the last section. There should be sufficient space in the header to add an additional section descriptor. So what is preventing us from just appending the SBAT data to the file, and creating a 5th section that lives right after .data both in the file view (at 0x934000 + 4608) and in the memory view (0x934000 + 0x47000). That should produce a valid PE/COFF image, no?
Ard Biesheuvel <ardb@kernel.org> writes: > Hi Vitaly, > > Thanks for the elaborate writeup > > > On Wed, 5 Mar 2025 at 11:18, Vitaly Kuznetsov <vkuznets@redhat.com> wrote: >> >> 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 >> >> Previously, an attempt was made to add ".sbat" section to the linux kernel: >> >> https://lwn.net/Articles/938422/ >> >> The approach was rejected mainly because currently there's no policy on how >> to update SBAT generation number when a new vulnerability is discovered. In >> particular, it is unclear what to do with stable kernels which may or may >> not backport certain patches making it impossible to describe the current >> state with a simple number. >> >> This patch suggests a different approach: instead of defining SBAT >> information, provide a mechanism for downstream kernel builders (distros) >> to include their own SBAT data. > > Why does this require a mechanism in the upstream kernel at all? > Signing the kernel (which includes appending a cert table) does not > require such changes, so why is this needed when adding an additional > PE/COFF section? Hi Ard, strictly speaking this is not a must (and that's part of the RFC, thanks for looking into it!). The main intention is to make distro's life easier by providing a working mechanism upstream. Here is an example of a downstream-only solution I've drafted for Fedora based distros: https://gitlab.com/cki-project/kernel-ark/-/merge_requests/3581/diffs?commit_id=07005140712545cb4dfce09da03545d9c54515e6 nothing too complicated but not a trivial one-liner either. I'm fairly sure kernel maintainers would very much prefer to have a simple "CONFIG_EFI_SBAT_FILE=/my/distros/sbat/data" instead. Additional motivation can be to avoid divergence between distros (e.g. one distro may deside to do things the way this patch does, the other decides to put it to the end, the third patches 'setup' and so on) which may lead to some incompatibility and distro-specific workarounds in bootloaders (e.g. shim) in the future. Third, having the SBAT *mechanism* supported upstream raises the visibility of the technology for those who do their own SecureBoot kernel signing. > >> This leaves the decision on the policy to >> the distro vendors. 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'. Linux >> upstream will never, ever need to care about the data unless they choose in >> the future to participate in that way. >> > > I'm sure this paragraph will make some skeptics happy. > It was a heated discussion last time so I had to :-) >> Currently, shim checks .sbat data for itself in self-test and for second >> stage bootloaders (grub, sd-boot, UKIs with sd-stub, ...) but kernel >> revocations require cycling signing keys or adding kernel hashes to shim's >> internal dbx. Adding .sbat to kernel and enforcing it on kernel loading >> will allow us to do the same tracking and revocation distros are already >> doing with a simplified mechanism, and without having to keep lists of >> kernels outside of the git repos. >> >> Finding a place for SBAT section turned out to be a bit tricky. Current >> PE layout looks like this: >> >> - without CONFIG_EFI_MIXED: >> +-----------------------------------+-------------------------------+ >> | setup [setup_signature]| compressed text | data [crc32]| >> +-----------------------------------+-----------------+-------------+ >> >> - with CONFIG_EFI_MIXED: >> +-------+---------------------------+----------------+-------------+ >> | setup | pecompat [setup_signature]| compressed text| data [crc32]| >> +-------+---------------------------+----------------+-------------+ >> >> Limitations are: >> - To avoid problems with signatures, all sections must be 4k aligned with >> no gaps between them. >> - CRC32 must be at the end of the file. > > We never cared about the CRC32 before with signed EFI images, which > gets clobbered when the image is signed. Why should we start caring > about it now? Oh, that's a good point, actually. As there's no reason to add SBAT to a kernel which is not going to be signed and signing breaks CRC32 anyway, we can as well add the section to the very end. Personally, I'd suggest we then don't put any CRC32 there at all and clearly state that in the documentation to avoid the confusion when people discover that there's a CRC which doesn't match. > >> - Nothing can be put before 'setup'. >> - Nothing can be squeezed between [setup_signature] and compressed text. >> - The whole 'setup' (everything before '.text') must fit into 8 4k pages. >> >> Note: .pecompat contains only 8 bytes of useful data but to save the space, >> the tail from .setup including [setup_signature] is also added to it (see >> commit 1ad55cecf22f ("x86/efistub: Use 1:1 file:memory mapping for PE/COFF >> .compat section")). >> >> With the limitations, there are three straightforward options: >> - Put .sbat between .setup and .pecompat. Advantage: with normal sized >> SBAT, kernel grows by 1 page only. Disadvantage: this one page comes from >> the precious '8 pages' limit. >> >> - Put .sbat to the very end of the file. Advantage: no need to touch >> 'setup'. Disadvantage: two pages are now needed as we don't want to make >> CRC32 part of the SBAT section. >> >> - Put .sbat between '.text' and '.data'. Advantages: no need to touch >> 'setup' and CRC32. 'CONFIG_EFI_MIXED' case doesn't seem to make much >> difference either. >> >> Implement the last one as it doesn't seem to have obvious disadvantages. >> >> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> >> --- >> RFC part: >> - General acceptance of the idea. >> - .sbat section placement. >> >> The implementation is done for x86 only at this moment but I think it >> shouldn't be that hard to extend it to other arches (and I hope the >> solution for those which use common zboot mechanism will be the same). > > Please don't create a special case for x86 again - iff this needs to > be in upstream (which I am not convinced about) it needs to be > implemented for all architectures. Oh, absolutely -- if we get past the 'general acceptance', then let's do other UEFI supporting arches from day 1. > > So I'd like to understand better what is preventing you from appending > a PE/COFF section on an arbitrary bzImage (or EFI zboot image). > > Given an arbitrary PE/COFF image, I see > > Section { > Number: 4 > Name: .data (2E 64 61 74 61 00 00 00) > VirtualSize: 0x47000 > VirtualAddress: 0x934000 > RawDataSize: 4608 > PointerToRawData: 0x934000 > PointerToRelocations: 0x0 > PointerToLineNumbers: 0x0 > RelocationCount: 0 > LineNumberCount: 0 > Characteristics [ (0xC0000040) > IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) > IMAGE_SCN_MEM_READ (0x40000000) > IMAGE_SCN_MEM_WRITE (0x80000000) > ] > > as the last section. There should be sufficient space in the header to > add an additional section descriptor. > > So what is preventing us from just appending the SBAT data to the > file, and creating a 5th section that lives right after .data both in > the file view (at 0x934000 + 4608) and in the memory view (0x934000 + > 0x47000). That should produce a valid PE/COFF image, no? Yes, if we forget about the CRC32 (which we do anyway), then adding a section to the end by external tool should work for as long as we have enough space in the header to add a new section. As this is going to be a downstream-only approach, nothing will guarantee that long term and things may eventually break.
On March 7, 2025 6:15:27 AM PST, Ard Biesheuvel <ardb@kernel.org> wrote: >On Fri, 7 Mar 2025 at 14:29, Gerd Hoffmann <kraxel@redhat.com> wrote: >> >> Hi, >> >> > > This patch suggests a different approach: instead of defining SBAT >> > > information, provide a mechanism for downstream kernel builders (distros) >> > > to include their own SBAT data. >> > >> > Why does this require a mechanism in the upstream kernel at all? >> >> To avoid every distro re-inventing the wheel? >> > >Fair enough. > >> > > - CRC32 must be at the end of the file. >> > >> > We never cared about the CRC32 before with signed EFI images, which >> > gets clobbered when the image is signed. Why should we start caring >> > about it now? >> >> I have some blurry memories on having seen this crc32 discussion >> before ... >> >> The crc32 is not clobbered. The signature is simply appended and >> wouldn't overwrite the crc32. But if software expects to find that >> crc32 in the last four bytes of the file then yes, that assumption does >> not hold any more for signed kernel binaries. >> > >The crc32 is a CRC over the entire bzImage. Whether or not it lives at >the end is irrelevant, as signing the bzImage will necessarily [*] >break the CRC, and subsequently regenerating the CRC will invalidate >the signature. (The CRC lives at the end because that is the easiest >way to generate an image whose checksum including the CRC itself is >~0. However, there are also other ways to achieve this) > >> Who uses that crc32 and how? If it is useless anyway, can we just drop >> it upstream? >> > >I tried but hpa objected to that. [0] > >> > Please don't create a special case for x86 again - iff this needs to >> > be in upstream (which I am not convinced about) it needs to be >> > implemented for all architectures. >> >> Well, x86 *is* the special case. Everybody else just uses zboot. >> >> But, yes, when this RfC patch discussion comes to the conclusion that >> this is useful to have upstream the plan is to do this for zboot too >> so all architectures are covered. >> > >Good. > >> > So I'd like to understand better what is preventing you from appending >> > a PE/COFF section on an arbitrary bzImage (or EFI zboot image). >> >> Well, assuming it is safe to ignore the crc32 as per above discussion >> then nothing really. It should be possible to do this as part of the >> signing process instead. That leaves the "not re-inventing the wheel" >> aspect of this on the table. >> > >[*] While it is feasible to generate an image that checksums to ~0 and >is signed for UEFI secure boot (details in [0]), I seriously doubt >that we should bother. Not even hpa's own bootloader 'syslinux' cares >about the CRC-32, and given that all signed distro kernels that have >been in circulation since they started signing them have corrupted >CRCs, there is really no need to start caring about that now. > >If there is a need to maintain this upstream, we can host the tools >but I don't see a reason to integrate this with the bzImage build as >this patch proposes. > > > > > >[0] https://lore.kernel.org/all/20230818134422.380032-1-ardb@kernel.org/T/#m3d3c7b62045072090c49706295a1fc9aa6a5e349 I don't remember who it was that asked for the CRC32 long ago. It wasn't for Syslinux; it was for an embedded boot loader which didn't have a file system. I don't know what would break, and it is obviously a mess that the signing protocol didn't take that into consideration, but that is water under the bridge, too. We could try zeroing out the CRC field and see if anyone screams...
On March 7, 2025 7:29:27 AM PST, Ard Biesheuvel <ardb@kernel.org> wrote: >On Fri, 7 Mar 2025 at 15:52, H. Peter Anvin <hpa@zytor.com> wrote: >> >> On March 7, 2025 6:15:27 AM PST, Ard Biesheuvel <ardb@kernel.org> wrote: >> >On Fri, 7 Mar 2025 at 14:29, Gerd Hoffmann <kraxel@redhat.com> wrote: >> >> >... >> >> The crc32 is not clobbered. The signature is simply appended and >> >> wouldn't overwrite the crc32. But if software expects to find that >> >> crc32 in the last four bytes of the file then yes, that assumption does >> >> not hold any more for signed kernel binaries. >> >> >> > >> >The crc32 is a CRC over the entire bzImage. Whether or not it lives at >> >the end is irrelevant, as signing the bzImage will necessarily [*] >> >break the CRC, and subsequently regenerating the CRC will invalidate >> >the signature. (The CRC lives at the end because that is the easiest >> >way to generate an image whose checksum including the CRC itself is >> >~0. However, there are also other ways to achieve this) >> > >> >> Who uses that crc32 and how? If it is useless anyway, can we just drop >> >> it upstream? >> >> >> > >> >I tried but hpa objected to that. [0] >> > >... >> >> I don't remember who it was that asked for the CRC32 long ago. It wasn't for Syslinux; it was for an embedded boot loader which didn't have a file system. >> >> I don't know what would break, and it is obviously a mess that the signing protocol didn't take that into consideration, but that is water under the bridge, too. >> >> We could try zeroing out the CRC field and see if anyone screams... >> > >If dropping the CRC is on the table, we might also consider my >original patch, which gets rid of the build tool entirely, given the >fact that generating the CRC is the only thing it is still used for. >(Either change can easily be reverted anyway) I think it would have to be up to the x86 maintainers, but I would be willing to test it. Perhaps it would be better, though, to make the CRC a build option – or we make it mutually exclusive with efistub.
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index be2c311f5118..05069b085663 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2062,6 +2062,31 @@ config EFI_RUNTIME_MAP See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map. +config EFI_SBAT + bool "Embed SBAT section in the kernel" + depends on EFI_STUB + 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. + + If unsure, say N. + +config EFI_SBAT_FILE + string "Embedded SBAT section file path" + depends on EFI_SBAT + help + Specify a file with SBAT data which is going to be embedded as '.sbat' + section into the kernel. + source "kernel/Kconfig.hz" config ARCH_SUPPORTS_KEXEC diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index 9cc0ff6e9067..73926fc79127 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -75,7 +75,7 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE SETUP_OBJS = $(addprefix $(obj)/,$(setup-y)) -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' +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\|_e\?sbat\|z_.*\)$$/\#define ZO_\2 0x\1/p' quiet_cmd_zoffset = ZOFFSET $@ cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@ diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 606c74f27459..aef3e20fdbd4 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -107,6 +107,13 @@ vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) += $(obj)/mem.o vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o vmlinux-libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a +vmlinux-objs-$(CONFIG_EFI_SBAT) += $(obj)/sbat.o + +$(obj)/sbat.o: $(obj)/sbat +targets += sbat +filechk_sbat = cat $(or $(real-prereqs), /dev/null) +$(obj)/sbat: $(CONFIG_EFI_SBAT_FILE) FORCE + $(call filechk,sbat) $(obj)/vmlinux: $(vmlinux-objs-y) $(vmlinux-libs-y) FORCE $(call if_changed,ld) diff --git a/arch/x86/boot/compressed/sbat.S b/arch/x86/boot/compressed/sbat.S new file mode 100644 index 000000000000..dfa8aeb36660 --- /dev/null +++ b/arch/x86/boot/compressed/sbat.S @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Embed SBAT data in the kernel. + */ + .pushsection ".sbat", "a", @progbits + .incbin "arch/x86/boot/compressed/sbat" + .balign 0x1000 + .popsection diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S index 083ec6d7722a..c93670bac7f8 100644 --- a/arch/x86/boot/compressed/vmlinux.lds.S +++ b/arch/x86/boot/compressed/vmlinux.lds.S @@ -43,6 +43,14 @@ SECTIONS *(.rodata.*) _erodata = . ; } +#ifdef CONFIG_EFI_SBAT + .sbat : ALIGN(0x1000) { + _sbat = . ; + *(.sbat) + _esbat = . ; + } + ASSERT((_esbat % 0x1000) == 0, "SBAT section end is not page-aligned!") +#endif .data : ALIGN(0x1000) { _data = . ; *(.data) diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index b5c79f43359b..38ce62ef89d9 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -183,9 +183,9 @@ pecompat_fstart: .byte 0 .byte 0 .byte 0 - .long ZO__data + .long text_fsize .long setup_size - .long ZO__data # Size of initialized data + .long text_fsize # Size of initialized data # on disk .long setup_size .long 0 # PointerToRelocations @@ -196,6 +196,23 @@ pecompat_fstart: IMAGE_SCN_MEM_READ | \ IMAGE_SCN_MEM_EXECUTE # Characteristics +#ifdef CONFIG_EFI_SBAT + .ascii ".sbat\0\0\0" + .long ZO__esbat - ZO__sbat # VirtualSize + .long setup_size + ZO__sbat # VirtualAddress + .long ZO__esbat - ZO__sbat # SizeOfRawData + .long setup_size + ZO__sbat # PointerToRawData + + .long 0, 0, 0 + .long IMAGE_SCN_CNT_INITIALIZED_DATA | \ + IMAGE_SCN_MEM_READ | \ + IMAGE_SCN_MEM_DISCARDABLE # Characteristics + + .set text_fsize, ZO__sbat +#else + .set text_fsize, ZO__data +#endif + .ascii ".data\0\0\0" .long ZO__end - ZO__data # VirtualSize .long setup_size + ZO__data # VirtualAddress
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 Previously, an attempt was made to add ".sbat" section to the linux kernel: https://lwn.net/Articles/938422/ The approach was rejected mainly because currently there's no policy on how to update SBAT generation number when a new vulnerability is discovered. In particular, it is unclear what to do with stable kernels which may or may not backport certain patches making it impossible to describe the current state with a simple number. This patch suggests a different approach: instead of defining SBAT information, provide a mechanism for downstream kernel builders (distros) to include their own SBAT data. This leaves the decision on the policy to the distro vendors. 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'. Linux upstream will never, ever need to care about the data unless they choose in the future to participate in that way. Currently, shim checks .sbat data for itself in self-test and for second stage bootloaders (grub, sd-boot, UKIs with sd-stub, ...) but kernel revocations require cycling signing keys or adding kernel hashes to shim's internal dbx. Adding .sbat to kernel and enforcing it on kernel loading will allow us to do the same tracking and revocation distros are already doing with a simplified mechanism, and without having to keep lists of kernels outside of the git repos. Finding a place for SBAT section turned out to be a bit tricky. Current PE layout looks like this: - without CONFIG_EFI_MIXED: +-----------------------------------+-------------------------------+ | setup [setup_signature]| compressed text | data [crc32]| +-----------------------------------+-----------------+-------------+ - with CONFIG_EFI_MIXED: +-------+---------------------------+----------------+-------------+ | setup | pecompat [setup_signature]| compressed text| data [crc32]| +-------+---------------------------+----------------+-------------+ Limitations are: - To avoid problems with signatures, all sections must be 4k aligned with no gaps between them. - CRC32 must be at the end of the file. - Nothing can be put before 'setup'. - Nothing can be squeezed between [setup_signature] and compressed text. - The whole 'setup' (everything before '.text') must fit into 8 4k pages. Note: .pecompat contains only 8 bytes of useful data but to save the space, the tail from .setup including [setup_signature] is also added to it (see commit 1ad55cecf22f ("x86/efistub: Use 1:1 file:memory mapping for PE/COFF .compat section")). With the limitations, there are three straightforward options: - Put .sbat between .setup and .pecompat. Advantage: with normal sized SBAT, kernel grows by 1 page only. Disadvantage: this one page comes from the precious '8 pages' limit. - Put .sbat to the very end of the file. Advantage: no need to touch 'setup'. Disadvantage: two pages are now needed as we don't want to make CRC32 part of the SBAT section. - Put .sbat between '.text' and '.data'. Advantages: no need to touch 'setup' and CRC32. 'CONFIG_EFI_MIXED' case doesn't seem to make much difference either. Implement the last one as it doesn't seem to have obvious disadvantages. Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> --- RFC part: - General acceptance of the idea. - .sbat section placement. The implementation is done for x86 only at this moment but I think it shouldn't be that hard to extend it to other arches (and I hope the solution for those which use common zboot mechanism will be the same). --- arch/x86/Kconfig | 25 +++++++++++++++++++++++++ arch/x86/boot/Makefile | 2 +- arch/x86/boot/compressed/Makefile | 7 +++++++ arch/x86/boot/compressed/sbat.S | 8 ++++++++ arch/x86/boot/compressed/vmlinux.lds.S | 8 ++++++++ arch/x86/boot/header.S | 21 +++++++++++++++++++-- 6 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 arch/x86/boot/compressed/sbat.S