1*4882a593SmuzhiyunFrom b11547137703bbc642114a816233a5b6fed61b06 Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: Peter Jones <pjones@redhat.com> 3*4882a593SmuzhiyunDate: Mon, 15 Feb 2021 17:07:00 +0100 4*4882a593SmuzhiyunSubject: [PATCH] util/mkimage: Add an option to import SBAT metadata into a 5*4882a593Smuzhiyun .sbat section 6*4882a593Smuzhiyun 7*4882a593SmuzhiyunAdd a --sbat option to the grub-mkimage tool which allows us to import 8*4882a593Smuzhiyunan SBAT metadata formatted as a CSV file into a .sbat section of the 9*4882a593SmuzhiyunEFI binary. 10*4882a593Smuzhiyun 11*4882a593SmuzhiyunSigned-off-by: Peter Jones <pjones@redhat.com> 12*4882a593SmuzhiyunSigned-off-by: Javier Martinez Canillas <javierm@redhat.com> 13*4882a593SmuzhiyunReviewed-by: Daniel Kiper <daniel.kiper@oracle.com> 14*4882a593SmuzhiyunSigned-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com> 15*4882a593Smuzhiyun--- 16*4882a593Smuzhiyun docs/grub.texi | 19 +++++++++++++++++++ 17*4882a593Smuzhiyun include/grub/util/install.h | 3 ++- 18*4882a593Smuzhiyun include/grub/util/mkimage.h | 1 + 19*4882a593Smuzhiyun util/grub-install-common.c | 2 +- 20*4882a593Smuzhiyun util/grub-mkimage.c | 15 ++++++++++++++- 21*4882a593Smuzhiyun util/mkimage.c | 43 ++++++++++++++++++++++++++++++++++++------- 22*4882a593Smuzhiyun 6 files changed, 73 insertions(+), 10 deletions(-) 23*4882a593Smuzhiyun 24*4882a593Smuzhiyundiff --git a/docs/grub.texi b/docs/grub.texi 25*4882a593Smuzhiyunindex 8518cc0..bff6dfc 100644 26*4882a593Smuzhiyun--- a/docs/grub.texi 27*4882a593Smuzhiyun+++ b/docs/grub.texi 28*4882a593Smuzhiyun@@ -5616,6 +5616,7 @@ environment variables and commands are listed in the same order. 29*4882a593Smuzhiyun * Authentication and authorisation:: Users and access control 30*4882a593Smuzhiyun * Using digital signatures:: Booting digitally signed code 31*4882a593Smuzhiyun * UEFI secure boot and shim:: Booting digitally signed PE files 32*4882a593Smuzhiyun+* Secure Boot Advanced Targeting:: Embedded information for generation number based revocation 33*4882a593Smuzhiyun * Measured Boot:: Measuring boot components 34*4882a593Smuzhiyun * Lockdown:: Lockdown when booting on a secure setup 35*4882a593Smuzhiyun @end menu 36*4882a593Smuzhiyun@@ -5795,6 +5796,24 @@ and @command{memrw} will not be available when the UEFI secure boot is enabled. 37*4882a593Smuzhiyun This is done for security reasons and are enforced by the GRUB Lockdown mechanism 38*4882a593Smuzhiyun (@pxref{Lockdown}). 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun+@node Secure Boot Advanced Targeting 41*4882a593Smuzhiyun+@section Embedded information for generation number based revocation 42*4882a593Smuzhiyun+ 43*4882a593Smuzhiyun+The Secure Boot Advanced Targeting (SBAT) is a mechanism to allow the revocation 44*4882a593Smuzhiyun+of components in the boot path by using generation numbers embedded into the EFI 45*4882a593Smuzhiyun+binaries. The SBAT metadata is located in an .sbat data section that has set of 46*4882a593Smuzhiyun+UTF-8 strings as comma-separated values (CSV). See 47*4882a593Smuzhiyun+@uref{https://github.com/rhboot/shim/blob/main/SBAT.md} for more details. 48*4882a593Smuzhiyun+ 49*4882a593Smuzhiyun+To add a data section containing the SBAT information into the binary, the 50*4882a593Smuzhiyun+@option{--sbat} option of @command{grub-mkimage} command should be used. The content 51*4882a593Smuzhiyun+of a CSV file, encoded with UTF-8, is copied as is to the .sbat data section into 52*4882a593Smuzhiyun+the generated EFI binary. The CSV file can be stored anywhere on the file system. 53*4882a593Smuzhiyun+ 54*4882a593Smuzhiyun+@example 55*4882a593Smuzhiyun+grub-mkimage -O x86_64-efi -o grubx64.efi -p '(tftp)/grub' --sbat sbat.csv efinet tftp 56*4882a593Smuzhiyun+@end example 57*4882a593Smuzhiyun+ 58*4882a593Smuzhiyun @node Measured Boot 59*4882a593Smuzhiyun @section Measuring boot components 60*4882a593Smuzhiyun 61*4882a593Smuzhiyundiff --git a/include/grub/util/install.h b/include/grub/util/install.h 62*4882a593Smuzhiyunindex 2631b10..c03befd 100644 63*4882a593Smuzhiyun--- a/include/grub/util/install.h 64*4882a593Smuzhiyun+++ b/include/grub/util/install.h 65*4882a593Smuzhiyun@@ -183,7 +183,8 @@ grub_install_generate_image (const char *dir, const char *prefix, 66*4882a593Smuzhiyun char *config_path, 67*4882a593Smuzhiyun const struct grub_install_image_target_desc *image_target, 68*4882a593Smuzhiyun int note, 69*4882a593Smuzhiyun- grub_compression_t comp, const char *dtb_file); 70*4882a593Smuzhiyun+ grub_compression_t comp, const char *dtb_file, 71*4882a593Smuzhiyun+ const char *sbat_path); 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun const struct grub_install_image_target_desc * 74*4882a593Smuzhiyun grub_install_get_image_target (const char *arg); 75*4882a593Smuzhiyundiff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h 76*4882a593Smuzhiyunindex ba9f568..3819a67 100644 77*4882a593Smuzhiyun--- a/include/grub/util/mkimage.h 78*4882a593Smuzhiyun+++ b/include/grub/util/mkimage.h 79*4882a593Smuzhiyun@@ -24,6 +24,7 @@ struct grub_mkimage_layout 80*4882a593Smuzhiyun size_t exec_size; 81*4882a593Smuzhiyun size_t kernel_size; 82*4882a593Smuzhiyun size_t bss_size; 83*4882a593Smuzhiyun+ size_t sbat_size; 84*4882a593Smuzhiyun grub_uint64_t start_address; 85*4882a593Smuzhiyun void *reloc_section; 86*4882a593Smuzhiyun size_t reloc_size; 87*4882a593Smuzhiyundiff --git a/util/grub-install-common.c b/util/grub-install-common.c 88*4882a593Smuzhiyunindex 0295d40..5d43ed1 100644 89*4882a593Smuzhiyun--- a/util/grub-install-common.c 90*4882a593Smuzhiyun+++ b/util/grub-install-common.c 91*4882a593Smuzhiyun@@ -511,7 +511,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, 92*4882a593Smuzhiyun grub_install_generate_image (dir, prefix, fp, outname, 93*4882a593Smuzhiyun modules.entries, memdisk_path, 94*4882a593Smuzhiyun pubkeys, npubkeys, config_path, tgt, 95*4882a593Smuzhiyun- note, compression, dtb); 96*4882a593Smuzhiyun+ note, compression, dtb, NULL); 97*4882a593Smuzhiyun while (dc--) 98*4882a593Smuzhiyun grub_install_pop_module (); 99*4882a593Smuzhiyun } 100*4882a593Smuzhiyundiff --git a/util/grub-mkimage.c b/util/grub-mkimage.c 101*4882a593Smuzhiyunindex 912564e..75b8847 100644 102*4882a593Smuzhiyun--- a/util/grub-mkimage.c 103*4882a593Smuzhiyun+++ b/util/grub-mkimage.c 104*4882a593Smuzhiyun@@ -81,6 +81,7 @@ static struct argp_option options[] = { 105*4882a593Smuzhiyun {"output", 'o', N_("FILE"), 0, N_("output a generated image to FILE [default=stdout]"), 0}, 106*4882a593Smuzhiyun {"format", 'O', N_("FORMAT"), 0, 0, 0}, 107*4882a593Smuzhiyun {"compression", 'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0}, 108*4882a593Smuzhiyun+ {"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0}, 109*4882a593Smuzhiyun {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, 110*4882a593Smuzhiyun { 0, 0, 0, 0, 0, 0 } 111*4882a593Smuzhiyun }; 112*4882a593Smuzhiyun@@ -123,6 +124,7 @@ struct arguments 113*4882a593Smuzhiyun size_t npubkeys; 114*4882a593Smuzhiyun char *font; 115*4882a593Smuzhiyun char *config; 116*4882a593Smuzhiyun+ char *sbat; 117*4882a593Smuzhiyun int note; 118*4882a593Smuzhiyun const struct grub_install_image_target_desc *image_target; 119*4882a593Smuzhiyun grub_compression_t comp; 120*4882a593Smuzhiyun@@ -224,6 +226,13 @@ argp_parser (int key, char *arg, struct argp_state *state) 121*4882a593Smuzhiyun arguments->prefix = xstrdup (arg); 122*4882a593Smuzhiyun break; 123*4882a593Smuzhiyun 124*4882a593Smuzhiyun+ case 's': 125*4882a593Smuzhiyun+ if (arguments->sbat) 126*4882a593Smuzhiyun+ free (arguments->sbat); 127*4882a593Smuzhiyun+ 128*4882a593Smuzhiyun+ arguments->sbat = xstrdup (arg); 129*4882a593Smuzhiyun+ break; 130*4882a593Smuzhiyun+ 131*4882a593Smuzhiyun case 'v': 132*4882a593Smuzhiyun verbosity++; 133*4882a593Smuzhiyun break; 134*4882a593Smuzhiyun@@ -309,7 +318,8 @@ main (int argc, char *argv[]) 135*4882a593Smuzhiyun arguments.memdisk, arguments.pubkeys, 136*4882a593Smuzhiyun arguments.npubkeys, arguments.config, 137*4882a593Smuzhiyun arguments.image_target, arguments.note, 138*4882a593Smuzhiyun- arguments.comp, arguments.dtb); 139*4882a593Smuzhiyun+ arguments.comp, arguments.dtb, 140*4882a593Smuzhiyun+ arguments.sbat); 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun if (grub_util_file_sync (fp) < 0) 143*4882a593Smuzhiyun grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout", 144*4882a593Smuzhiyun@@ -328,5 +338,8 @@ main (int argc, char *argv[]) 145*4882a593Smuzhiyun if (arguments.output) 146*4882a593Smuzhiyun free (arguments.output); 147*4882a593Smuzhiyun 148*4882a593Smuzhiyun+ if (arguments.sbat) 149*4882a593Smuzhiyun+ free (arguments.sbat); 150*4882a593Smuzhiyun+ 151*4882a593Smuzhiyun return 0; 152*4882a593Smuzhiyun } 153*4882a593Smuzhiyundiff --git a/util/mkimage.c b/util/mkimage.c 154*4882a593Smuzhiyunindex 8b475a6..b354ec1 100644 155*4882a593Smuzhiyun--- a/util/mkimage.c 156*4882a593Smuzhiyun+++ b/util/mkimage.c 157*4882a593Smuzhiyun@@ -869,12 +869,13 @@ grub_install_generate_image (const char *dir, const char *prefix, 158*4882a593Smuzhiyun char *memdisk_path, char **pubkey_paths, 159*4882a593Smuzhiyun size_t npubkeys, char *config_path, 160*4882a593Smuzhiyun const struct grub_install_image_target_desc *image_target, 161*4882a593Smuzhiyun- int note, grub_compression_t comp, const char *dtb_path) 162*4882a593Smuzhiyun+ int note, grub_compression_t comp, const char *dtb_path, 163*4882a593Smuzhiyun+ const char *sbat_path) 164*4882a593Smuzhiyun { 165*4882a593Smuzhiyun char *kernel_img, *core_img; 166*4882a593Smuzhiyun size_t total_module_size, core_size; 167*4882a593Smuzhiyun size_t memdisk_size = 0, config_size = 0; 168*4882a593Smuzhiyun- size_t prefix_size = 0, dtb_size = 0; 169*4882a593Smuzhiyun+ size_t prefix_size = 0, dtb_size = 0, sbat_size = 0; 170*4882a593Smuzhiyun char *kernel_path; 171*4882a593Smuzhiyun size_t offset; 172*4882a593Smuzhiyun struct grub_util_path_list *path_list, *p; 173*4882a593Smuzhiyun@@ -925,6 +926,9 @@ grub_install_generate_image (const char *dir, const char *prefix, 174*4882a593Smuzhiyun total_module_size += dtb_size + sizeof (struct grub_module_header); 175*4882a593Smuzhiyun } 176*4882a593Smuzhiyun 177*4882a593Smuzhiyun+ if (sbat_path != NULL && image_target->id != IMAGE_EFI) 178*4882a593Smuzhiyun+ grub_util_error (_(".sbat section can be embedded into EFI images only")); 179*4882a593Smuzhiyun+ 180*4882a593Smuzhiyun if (config_path) 181*4882a593Smuzhiyun { 182*4882a593Smuzhiyun config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1); 183*4882a593Smuzhiyun@@ -1289,8 +1293,9 @@ grub_install_generate_image (const char *dir, const char *prefix, 184*4882a593Smuzhiyun break; 185*4882a593Smuzhiyun case IMAGE_EFI: 186*4882a593Smuzhiyun { 187*4882a593Smuzhiyun- char *pe_img, *header; 188*4882a593Smuzhiyun+ char *pe_img, *pe_sbat, *header; 189*4882a593Smuzhiyun struct grub_pe32_section_table *section; 190*4882a593Smuzhiyun+ size_t n_sections = 4; 191*4882a593Smuzhiyun size_t scn_size; 192*4882a593Smuzhiyun grub_uint32_t vma, raw_data; 193*4882a593Smuzhiyun size_t pe_size, header_size; 194*4882a593Smuzhiyun@@ -1305,8 +1310,15 @@ grub_install_generate_image (const char *dir, const char *prefix, 195*4882a593Smuzhiyun header_size = EFI64_HEADER_SIZE; 196*4882a593Smuzhiyun 197*4882a593Smuzhiyun vma = raw_data = header_size; 198*4882a593Smuzhiyun+ 199*4882a593Smuzhiyun+ if (sbat_path != NULL) 200*4882a593Smuzhiyun+ { 201*4882a593Smuzhiyun+ sbat_size = ALIGN_ADDR (grub_util_get_image_size (sbat_path)); 202*4882a593Smuzhiyun+ sbat_size = ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT); 203*4882a593Smuzhiyun+ } 204*4882a593Smuzhiyun+ 205*4882a593Smuzhiyun pe_size = ALIGN_UP (header_size + core_size, GRUB_PE32_FILE_ALIGNMENT) + 206*4882a593Smuzhiyun- ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT); 207*4882a593Smuzhiyun+ ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT) + sbat_size; 208*4882a593Smuzhiyun header = pe_img = xcalloc (1, pe_size); 209*4882a593Smuzhiyun 210*4882a593Smuzhiyun memcpy (pe_img + raw_data, core_img, core_size); 211*4882a593Smuzhiyun@@ -1321,7 +1333,10 @@ grub_install_generate_image (const char *dir, const char *prefix, 212*4882a593Smuzhiyun + GRUB_PE32_SIGNATURE_SIZE); 213*4882a593Smuzhiyun c->machine = grub_host_to_target16 (image_target->pe_target); 214*4882a593Smuzhiyun 215*4882a593Smuzhiyun- c->num_sections = grub_host_to_target16 (4); 216*4882a593Smuzhiyun+ if (sbat_path != NULL) 217*4882a593Smuzhiyun+ n_sections++; 218*4882a593Smuzhiyun+ 219*4882a593Smuzhiyun+ c->num_sections = grub_host_to_target16 (n_sections); 220*4882a593Smuzhiyun c->time = grub_host_to_target32 (STABLE_EMBEDDING_TIMESTAMP); 221*4882a593Smuzhiyun c->characteristics = grub_host_to_target16 (GRUB_PE32_EXECUTABLE_IMAGE 222*4882a593Smuzhiyun | GRUB_PE32_LINE_NUMS_STRIPPED 223*4882a593Smuzhiyun@@ -1383,7 +1398,8 @@ grub_install_generate_image (const char *dir, const char *prefix, 224*4882a593Smuzhiyun GRUB_PE32_SCN_MEM_READ); 225*4882a593Smuzhiyun 226*4882a593Smuzhiyun scn_size = ALIGN_UP (layout.kernel_size - layout.exec_size, GRUB_PE32_FILE_ALIGNMENT); 227*4882a593Smuzhiyun- PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size + 228*4882a593Smuzhiyun+ /* ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT) is done earlier. */ 229*4882a593Smuzhiyun+ PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size + sbat_size + 230*4882a593Smuzhiyun ALIGN_UP (total_module_size, 231*4882a593Smuzhiyun GRUB_PE32_FILE_ALIGNMENT)); 232*4882a593Smuzhiyun 233*4882a593Smuzhiyun@@ -1394,7 +1410,7 @@ grub_install_generate_image (const char *dir, const char *prefix, 234*4882a593Smuzhiyun GRUB_PE32_SCN_MEM_READ | 235*4882a593Smuzhiyun GRUB_PE32_SCN_MEM_WRITE); 236*4882a593Smuzhiyun 237*4882a593Smuzhiyun- scn_size = pe_size - layout.reloc_size - raw_data; 238*4882a593Smuzhiyun+ scn_size = pe_size - layout.reloc_size - sbat_size - raw_data; 239*4882a593Smuzhiyun section = init_pe_section (image_target, section, "mods", 240*4882a593Smuzhiyun &vma, scn_size, image_target->section_align, 241*4882a593Smuzhiyun &raw_data, scn_size, 242*4882a593Smuzhiyun@@ -1402,6 +1418,19 @@ grub_install_generate_image (const char *dir, const char *prefix, 243*4882a593Smuzhiyun GRUB_PE32_SCN_MEM_READ | 244*4882a593Smuzhiyun GRUB_PE32_SCN_MEM_WRITE); 245*4882a593Smuzhiyun 246*4882a593Smuzhiyun+ if (sbat_path != NULL) 247*4882a593Smuzhiyun+ { 248*4882a593Smuzhiyun+ pe_sbat = pe_img + raw_data; 249*4882a593Smuzhiyun+ grub_util_load_image (sbat_path, pe_sbat); 250*4882a593Smuzhiyun+ 251*4882a593Smuzhiyun+ section = init_pe_section (image_target, section, ".sbat", 252*4882a593Smuzhiyun+ &vma, sbat_size, 253*4882a593Smuzhiyun+ image_target->section_align, 254*4882a593Smuzhiyun+ &raw_data, sbat_size, 255*4882a593Smuzhiyun+ GRUB_PE32_SCN_CNT_INITIALIZED_DATA | 256*4882a593Smuzhiyun+ GRUB_PE32_SCN_MEM_READ); 257*4882a593Smuzhiyun+ } 258*4882a593Smuzhiyun+ 259*4882a593Smuzhiyun scn_size = layout.reloc_size; 260*4882a593Smuzhiyun PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (vma); 261*4882a593Smuzhiyun PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (scn_size); 262*4882a593Smuzhiyun-- 263*4882a593Smuzhiyun2.14.2 264*4882a593Smuzhiyun 265