Blame SOURCES/0436-util-mkimage-Add-an-option-to-import-SBAT-metadata-i.patch

b1bcb2
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
b1bcb2
From: Peter Jones <pjones@redhat.com>
b1bcb2
Date: Fri, 26 Feb 2021 01:43:30 +0100
b1bcb2
Subject: [PATCH] util/mkimage: Add an option to import SBAT metadata into a
b1bcb2
 .sbat section
b1bcb2
b1bcb2
Add a --sbat option to the grub-mkimage tool which allows us to import
b1bcb2
an SBAT metadata formatted as a CSV file into a .sbat section of the
b1bcb2
EFI binary.
b1bcb2
b1bcb2
Signed-off-by: Peter Jones <pjones@redhat.com>
b1bcb2
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
b1bcb2
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
b1bcb2
---
b1bcb2
 util/grub-install-common.c  |  2 +-
b1bcb2
 util/grub-mkimage.c         | 15 ++++++++++++++-
b1bcb2
 util/mkimage.c              | 44 +++++++++++++++++++++++++++++++++++++-------
b1bcb2
 include/grub/util/install.h |  3 ++-
b1bcb2
 docs/grub.texi              | 21 +++++++++++++++++++++
b1bcb2
 5 files changed, 75 insertions(+), 10 deletions(-)
b1bcb2
b1bcb2
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
b1bcb2
index d49a93d4740..b4192cf47a3 100644
b1bcb2
--- a/util/grub-install-common.c
b1bcb2
+++ b/util/grub-install-common.c
b1bcb2
@@ -498,7 +498,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
b1bcb2
   grub_install_generate_image (dir, prefix, fp, outname,
b1bcb2
 			       modules.entries, memdisk_path,
b1bcb2
 			       pubkeys, npubkeys, config_path, tgt,
b1bcb2
-			       note, compression);
b1bcb2
+			       note, compression, NULL);
b1bcb2
   while (dc--)
b1bcb2
     grub_install_pop_module ();
b1bcb2
 }
b1bcb2
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
b1bcb2
index 1e0bcf1bf4f..c674f76c42a 100644
b1bcb2
--- a/util/grub-mkimage.c
b1bcb2
+++ b/util/grub-mkimage.c
b1bcb2
@@ -80,6 +80,7 @@ static struct argp_option options[] = {
b1bcb2
   {"output",  'o', N_("FILE"), 0, N_("output a generated image to FILE [default=stdout]"), 0},
b1bcb2
   {"format",  'O', N_("FORMAT"), 0, 0, 0},
b1bcb2
   {"compression",  'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0},
b1bcb2
+  {"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0},
b1bcb2
   {"verbose",     'v', 0,      0, N_("print verbose messages."), 0},
b1bcb2
   { 0, 0, 0, 0, 0, 0 }
b1bcb2
 };
b1bcb2
@@ -121,6 +122,7 @@ struct arguments
b1bcb2
   size_t npubkeys;
b1bcb2
   char *font;
b1bcb2
   char *config;
b1bcb2
+  char *sbat;
b1bcb2
   int note;
b1bcb2
   const struct grub_install_image_target_desc *image_target;
b1bcb2
   grub_compression_t comp;
b1bcb2
@@ -215,6 +217,13 @@ argp_parser (int key, char *arg, struct argp_state *state)
b1bcb2
       arguments->prefix = xstrdup (arg);
b1bcb2
       break;
b1bcb2
 
b1bcb2
+    case 's':
b1bcb2
+      if (arguments->sbat)
b1bcb2
+	free (arguments->sbat);
b1bcb2
+
b1bcb2
+      arguments->sbat = xstrdup (arg);
b1bcb2
+      break;
b1bcb2
+
b1bcb2
     case 'v':
b1bcb2
       verbosity++;
b1bcb2
       break;
b1bcb2
@@ -299,7 +308,8 @@ main (int argc, char *argv[])
b1bcb2
 			       arguments.memdisk, arguments.pubkeys,
b1bcb2
 			       arguments.npubkeys, arguments.config,
b1bcb2
 			       arguments.image_target, arguments.note,
b1bcb2
-			       arguments.comp);
b1bcb2
+			       arguments.comp,
b1bcb2
+			       arguments.sbat);
b1bcb2
 
b1bcb2
   grub_util_file_sync  (fp);
b1bcb2
   fclose (fp);
b1bcb2
@@ -310,5 +320,8 @@ main (int argc, char *argv[])
b1bcb2
   if (arguments.output)
b1bcb2
     free (arguments.output);
b1bcb2
 
b1bcb2
+  if (arguments.sbat)
b1bcb2
+    free (arguments.sbat);
b1bcb2
+
b1bcb2
   return 0;
b1bcb2
 }
b1bcb2
diff --git a/util/mkimage.c b/util/mkimage.c
b1bcb2
index 938a06a2d3f..44e2b8adfd8 100644
b1bcb2
--- a/util/mkimage.c
b1bcb2
+++ b/util/mkimage.c
b1bcb2
@@ -1032,12 +1032,14 @@ grub_install_generate_image (const char *dir, const char *prefix,
b1bcb2
 			     size_t npubkeys, char *config_path,
b1bcb2
 			     const struct grub_install_image_target_desc *image_target,
b1bcb2
 			     int note,
b1bcb2
-			     grub_compression_t comp)
b1bcb2
+			     grub_compression_t comp,
b1bcb2
+			     const char *sbat_path)
b1bcb2
 {
b1bcb2
   char *kernel_img, *core_img;
b1bcb2
   size_t kernel_size, total_module_size, core_size, exec_size;
b1bcb2
   size_t memdisk_size = 0, config_size = 0, config_size_pure = 0;
b1bcb2
   size_t prefix_size = 0;
b1bcb2
+  size_t sbat_size = 0;
b1bcb2
   char *kernel_path;
b1bcb2
   size_t offset;
b1bcb2
   struct grub_util_path_list *path_list, *p, *next;
b1bcb2
@@ -1085,6 +1087,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
b1bcb2
       total_module_size += memdisk_size + sizeof (struct grub_module_header);
b1bcb2
     }
b1bcb2
 
b1bcb2
+  if (sbat_path != NULL && image_target->id != IMAGE_EFI)
b1bcb2
+    grub_util_error (_(".sbat section can be embedded into EFI images only"));
b1bcb2
+
b1bcb2
   if (config_path)
b1bcb2
     {
b1bcb2
       config_size_pure = grub_util_get_image_size (config_path) + 1;
b1bcb2
@@ -1446,8 +1451,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
b1bcb2
       break;
b1bcb2
     case IMAGE_EFI:
b1bcb2
       {
b1bcb2
-	char *pe_img, *header;
b1bcb2
+	char *pe_img, *pe_sbat, *header;
b1bcb2
 	struct grub_pe32_section_table *section;
b1bcb2
+	size_t n_sections = 4;
b1bcb2
 	size_t scn_size;
b1bcb2
 	grub_uint32_t vma, raw_data;
b1bcb2
 	size_t pe_size, header_size;
b1bcb2
@@ -1462,8 +1468,15 @@ grub_install_generate_image (const char *dir, const char *prefix,
b1bcb2
 	  header_size = EFI64_HEADER_SIZE;
b1bcb2
 
b1bcb2
 	vma = raw_data = header_size;
b1bcb2
+
b1bcb2
+	if (sbat_path != NULL)
b1bcb2
+	  {
b1bcb2
+	    sbat_size = ALIGN_ADDR (grub_util_get_image_size (sbat_path));
b1bcb2
+	    sbat_size = ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT);
b1bcb2
+	  }
b1bcb2
+
b1bcb2
 	pe_size = ALIGN_UP (header_size + core_size, GRUB_PE32_FILE_ALIGNMENT) +
b1bcb2
-          ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT);
b1bcb2
+          ALIGN_UP (reloc_size, GRUB_PE32_FILE_ALIGNMENT) + sbat_size;
b1bcb2
 	header = pe_img = xcalloc (1, pe_size);
b1bcb2
 
b1bcb2
 	memcpy (pe_img + raw_data, core_img, core_size);
b1bcb2
@@ -1478,7 +1491,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
b1bcb2
 					      + GRUB_PE32_SIGNATURE_SIZE);
b1bcb2
 	c->machine = grub_host_to_target16 (image_target->pe_target);
b1bcb2
 
b1bcb2
-	c->num_sections = grub_host_to_target16 (4);
b1bcb2
+	if (sbat_path != NULL)
b1bcb2
+	  n_sections++;
b1bcb2
+
b1bcb2
+	c->num_sections = grub_host_to_target16 (n_sections);
b1bcb2
 	c->time = grub_host_to_target32 (time (0));
b1bcb2
 	c->characteristics = grub_host_to_target16 (GRUB_PE32_EXECUTABLE_IMAGE
b1bcb2
 						    | GRUB_PE32_LINE_NUMS_STRIPPED
b1bcb2
@@ -1542,9 +1558,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
b1bcb2
 				   GRUB_PE32_SCN_MEM_READ);
b1bcb2
 
b1bcb2
 	scn_size = ALIGN_UP (kernel_size - exec_size, GRUB_PE32_FILE_ALIGNMENT);
b1bcb2
-	PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size +
b1bcb2
+	/* ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT) is done earlier. */
b1bcb2
+	PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size + sbat_size +
b1bcb2
 							       ALIGN_UP (total_module_size,
b1bcb2
-
b1bcb2
+									 GRUB_PE32_FILE_ALIGNMENT));
b1bcb2
 
b1bcb2
 	section = init_pe_section (image_target, section, ".data",
b1bcb2
 				   &vma, scn_size, image_target->section_align,
b1bcb2
@@ -1553,7 +1570,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
b1bcb2
 				   GRUB_PE32_SCN_MEM_READ |
b1bcb2
 				   GRUB_PE32_SCN_MEM_WRITE);
b1bcb2
 
b1bcb2
-	scn_size = pe_size - reloc_size - raw_data;
b1bcb2
+	scn_size = pe_size - reloc_size - sbat_size - raw_data;
b1bcb2
 	section = init_pe_section (image_target, section, "mods",
b1bcb2
 				   &vma, scn_size, image_target->section_align,
b1bcb2
 				   &raw_data, scn_size,
b1bcb2
@@ -1561,6 +1578,19 @@ grub_install_generate_image (const char *dir, const char *prefix,
b1bcb2
 				   GRUB_PE32_SCN_MEM_READ |
b1bcb2
 				   GRUB_PE32_SCN_MEM_WRITE);
b1bcb2
 
b1bcb2
+	if (sbat_path != NULL)
b1bcb2
+	  {
b1bcb2
+	    pe_sbat = pe_img + raw_data;
b1bcb2
+	    grub_util_load_image (sbat_path, pe_sbat);
b1bcb2
+
b1bcb2
+	    section = init_pe_section (image_target, section, ".sbat",
b1bcb2
+				       &vma, sbat_size,
b1bcb2
+				       image_target->section_align,
b1bcb2
+				       &raw_data, sbat_size,
b1bcb2
+				       GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
b1bcb2
+				       GRUB_PE32_SCN_MEM_READ);
b1bcb2
+	  }
b1bcb2
+
b1bcb2
 	scn_size = reloc_size;
b1bcb2
 	PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (vma);
b1bcb2
 	PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (scn_size);
b1bcb2
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
b1bcb2
index aedcd29f905..02ae1c6425e 100644
b1bcb2
--- a/include/grub/util/install.h
b1bcb2
+++ b/include/grub/util/install.h
b1bcb2
@@ -176,7 +176,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
b1bcb2
 			     char *config_path,
b1bcb2
 			     const struct grub_install_image_target_desc *image_target,
b1bcb2
 			     int note,
b1bcb2
-			     grub_compression_t comp);
b1bcb2
+			     grub_compression_t comp,
b1bcb2
+			     const char *sbat_path);
b1bcb2
 
b1bcb2
 const struct grub_install_image_target_desc *
b1bcb2
 grub_install_get_image_target (const char *arg);
b1bcb2
diff --git a/docs/grub.texi b/docs/grub.texi
b1bcb2
index 446574f3ddb..24840d00cf7 100644
b1bcb2
--- a/docs/grub.texi
b1bcb2
+++ b/docs/grub.texi
b1bcb2
@@ -5498,6 +5498,7 @@ environment variables and commands are listed in the same order.
b1bcb2
 @menu
b1bcb2
 * Authentication and authorisation:: Users and access control
b1bcb2
 * Using digital signatures::         Booting digitally signed code
b1bcb2
+* Secure Boot Advanced Targeting::   Embedded information for generation number based revocation
b1bcb2
 * Lockdown::                           Lockdown when booting on a secure setup
b1bcb2
 
b1bcb2
 @end menu
b1bcb2
@@ -5660,6 +5661,26 @@ or BIOS) configuration to cause the machine to boot from a different
b1bcb2
 (attacker-controlled) device.  GRUB is at best only one link in a
b1bcb2
 secure boot chain.
b1bcb2
 
b1bcb2
+
b1bcb2
+@node Secure Boot Advanced Targeting
b1bcb2
+@section Embedded information for generation number based revocation
b1bcb2
+
b1bcb2
+The Secure Boot Advanced Targeting (SBAT) is a mechanism to allow the revocation
b1bcb2
+of components in the boot path by using generation numbers embedded into the EFI
b1bcb2
+binaries. The SBAT metadata is located in an .sbat data section that has set of
b1bcb2
+UTF-8 strings as comma-separated values (CSV). See
b1bcb2
+@uref{https://github.com/rhboot/shim/blob/main/SBAT.md} for more details.
b1bcb2
+
b1bcb2
+To add a data section containing the SBAT information into the binary, the
b1bcb2
+@option{--sbat} option of @command{grub-mkimage} command should be used. The content
b1bcb2
+of a CSV file, encoded with UTF-8, is copied as is to the .sbat data section into
b1bcb2
+the generated EFI binary. The CSV file can be stored anywhere on the file system.
b1bcb2
+
b1bcb2
+@example
b1bcb2
+grub-mkimage -O x86_64-efi -o grubx64.efi -p '(tftp)/grub' --sbat sbat.csv efinet tftp
b1bcb2
+@end example
b1bcb2
+
b1bcb2
+
b1bcb2
 @node Lockdown
b1bcb2
 @section Lockdown when booting on a secure setup
b1bcb2