From 0bd358e4ee0c61355ab057a977fa6f5e311b7f07 Mon Sep 17 00:00:00 2001
From: Alexey Makhalov <amakhalov@vmware.com>
Date: Fri, 22 Sep 2023 12:25:24 -0700
Subject: [PATCH 2/3] Add .sbat section
To be able to revoke previously shipped signed kernel images by SBAT
generation. See https://github.com/rhboot/shim/blob/main/SBAT.md
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
---
arch/x86/boot/Makefile | 2 +-
arch/x86/boot/header.S | 22 ++++++++++++++++++++++
arch/x86/boot/tools/build.c | 33 ++++++++++++++++++++++++++-------
security/Kconfig | 12 ++++++++++++
4 files changed, 61 insertions(+), 8 deletions(-)
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 9e38ffaad..c757ce1fb 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -79,7 +79,7 @@ $(obj)/bzImage: asflags-y := $(SVGA_MODE)
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 $@ $(CONFIG_SECURITY_SBAT) $($(quiet)redirect_image)
$(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE
$(call if_changed,image)
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index f912d7770..1c0225fbd 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -232,6 +232,28 @@ section_table:
IMAGE_SCN_MEM_DISCARDABLE | \
IMAGE_SCN_ALIGN_1BYTES # Characteristics
+#ifdef CONFIG_SECURITY_SBAT
+ #
+ # The offset & size fields are filled in by build.c.
+ #
+ .ascii ".sbat"
+ .byte 0
+ .byte 0
+ .byte 0
+ .long 0 # VirtualSize
+ .long 0 # VirtualAddress
+ .long 0 # SizeOfRawData
+ .long 0 # PointerToRawData
+ .long 0 # PointerToRelocations
+ .long 0 # PointerToLineNumbers
+ .word 0 # NumberOfRelocations
+ .word 0 # NumberOfLineNumbers
+ .long IMAGE_SCN_CNT_INITIALIZED_DATA | \
+ IMAGE_SCN_MEM_READ | \
+ IMAGE_SCN_MEM_DISCARDABLE | \
+ IMAGE_SCN_ALIGN_1BYTES # Characteristics
+#endif
+
#ifdef CONFIG_EFI_MIXED
#
# The offset & size fields are filled in by build.c.
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index a3725ad46..d0b803d55 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -195,12 +195,12 @@ static void update_pecoff_section_header(char *section_name, u32 offset, u32 siz
update_pecoff_section_header_fields(section_name, offset, size, size, offset);
}
-static void update_pecoff_setup_and_reloc(unsigned int size)
+static void update_pecoff_setup_and_reloc(unsigned int size, unsigned int sbat_size)
{
u32 setup_offset = 0x200;
- u32 reloc_offset = size - PECOFF_RELOC_RESERVE - PECOFF_COMPAT_RESERVE;
+ u32 reloc_offset = size - PECOFF_RELOC_RESERVE - PECOFF_COMPAT_RESERVE - sbat_size;
#ifdef CONFIG_EFI_MIXED
- u32 compat_offset = reloc_offset + PECOFF_RELOC_RESERVE;
+ u32 compat_offset = reloc_offset + PECOFF_RELOC_RESERVE + sbat_size;
#endif
u32 setup_size = reloc_offset - setup_offset;
@@ -304,7 +304,8 @@ static void efi_stub_entry_update(void)
#else
-static inline void update_pecoff_setup_and_reloc(unsigned int size) {}
+static inline void update_pecoff_setup_and_reloc(unsigned int size,
+ unsigned int sbat_size) {}
static inline void update_pecoff_text(unsigned int text_start,
unsigned int file_sz,
unsigned int init_sz) {}
@@ -371,7 +372,7 @@ int main(int argc, char ** argv)
{
unsigned int i, sz, setup_sectors, init_sz;
int c;
- u32 sys_size;
+ u32 sys_size, sbat_size = 0;
struct stat sb;
FILE *file, *dest;
int fd;
@@ -380,7 +381,7 @@ int main(int argc, char ** argv)
efi_stub_defaults();
- if (argc != 5)
+ if (argc != 5 && argc != 6)
usage();
parse_zoffset(argv[3]);
@@ -401,6 +402,13 @@ int main(int argc, char ** argv)
die("Boot block hasn't got boot flag (0xAA55)");
fclose(file);
+ if (argc == 6) {
+ if (stat(argv[5], &sb))
+ die("Unable to stat `%s': %m", argv[5]);
+ sbat_size = sb.st_size;
+ memset(buf+c, 0, sbat_size);
+ c += sbat_size;
+ }
c += reserve_pecoff_compat_section(c);
c += reserve_pecoff_reloc_section(c);
@@ -411,7 +419,18 @@ int main(int argc, char ** argv)
i = setup_sectors*512;
memset(buf+c, 0, i-c);
- update_pecoff_setup_and_reloc(i);
+ update_pecoff_setup_and_reloc(i, sbat_size);
+ if (sbat_size) {
+ u32 sbat_offset = i - PECOFF_COMPAT_RESERVE - sbat_size;
+ update_pecoff_section_header(".sbat", sbat_offset, sbat_size);
+ file = fopen(argv[5], "r");
+ if (!file)
+ die("Unable to open `%s': %m", argv[5]);
+ if (fread(&buf[sbat_offset], 1, sizeof(buf) - sbat_offset,
+ file) != sbat_size)
+ die("Reading sbat failed");
+ fclose(file);
+ }
/* Set the default root device */
put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
diff --git a/security/Kconfig b/security/Kconfig
index e6db09a77..536689678 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -206,6 +206,18 @@ source "security/loadpin/Kconfig"
source "security/yama/Kconfig"
source "security/safesetid/Kconfig"
source "security/lockdown/Kconfig"
+
+config SECURITY_SBAT
+ string "Add .sbat section to kernel PE image"
+ depends on SECURITY
+ help
+ If set, this option should be the filename of a CSV-formatted file
+ containing SBAT data to be included as a .sbat section in PE kernel
+ image (bzImage).
+
+ See <https://github.com/rhboot/shim/blob/main/SBAT.md> for more information
+ about SBAT.
+
source "security/landlock/Kconfig"
source "security/integrity/Kconfig"
--
2.39.0