1*4882a593SmuzhiyunFrom 968de8c23c1cba0f18230f778ebcf6c412ec8ec5 Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: Dimitri John Ledkov <xnox@ubuntu.com> 3*4882a593SmuzhiyunDate: Sat, 20 Feb 2021 17:10:34 +0000 4*4882a593SmuzhiyunSubject: [PATCH] shim_lock: Only skip loading shim_lock verifier with explicit 5*4882a593Smuzhiyun consent 6*4882a593Smuzhiyun 7*4882a593SmuzhiyunCommit 32ddc42c (efi: Only register shim_lock verifier if shim_lock 8*4882a593Smuzhiyunprotocol is found and SB enabled) reintroduced CVE-2020-15705 which 9*4882a593Smuzhiyunpreviously only existed in the out-of-tree linuxefi patches and was 10*4882a593Smuzhiyunfixed as part of the BootHole patch series. 11*4882a593Smuzhiyun 12*4882a593SmuzhiyunUnder Secure Boot enforce loading shim_lock verifier. Allow skipping 13*4882a593Smuzhiyunshim_lock verifier if SecureBoot/MokSBState EFI variables indicate 14*4882a593Smuzhiyunskipping validations, or if GRUB image is built with --disable-shim-lock. 15*4882a593Smuzhiyun 16*4882a593SmuzhiyunFixes: 132ddc42c (efi: Only register shim_lock verifier if shim_lock 17*4882a593Smuzhiyun protocol is found and SB enabled) 18*4882a593SmuzhiyunFixes: CVE-2020-15705 19*4882a593SmuzhiyunFixes: CVE-2021-3418 20*4882a593Smuzhiyun 21*4882a593SmuzhiyunReported-by: Dimitri John Ledkov <xnox@ubuntu.com> 22*4882a593SmuzhiyunSigned-off-by: Dimitri John Ledkov <xnox@ubuntu.com> 23*4882a593SmuzhiyunReviewed-by: Daniel Kiper <daniel.kiper@oracle.com> 24*4882a593SmuzhiyunSigned-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com> 25*4882a593Smuzhiyun--- 26*4882a593Smuzhiyun docs/grub.texi | 5 ++++- 27*4882a593Smuzhiyun grub-core/kern/efi/sb.c | 17 ++++++++++++++++- 28*4882a593Smuzhiyun include/grub/kernel.h | 3 ++- 29*4882a593Smuzhiyun include/grub/util/install.h | 7 +++++-- 30*4882a593Smuzhiyun util/grub-install-common.c | 12 +++++++++--- 31*4882a593Smuzhiyun util/grub-mkimage.c | 8 +++++++- 32*4882a593Smuzhiyun util/mkimage.c | 15 ++++++++++++++- 33*4882a593Smuzhiyun 7 files changed, 57 insertions(+), 10 deletions(-) 34*4882a593Smuzhiyun 35*4882a593Smuzhiyundiff --git a/docs/grub.texi b/docs/grub.texi 36*4882a593Smuzhiyunindex bff6dfc..e302797 100644 37*4882a593Smuzhiyun--- a/docs/grub.texi 38*4882a593Smuzhiyun+++ b/docs/grub.texi 39*4882a593Smuzhiyun@@ -5787,7 +5787,10 @@ secure boot chain. 40*4882a593Smuzhiyun The GRUB, except the @command{chainloader} command, works with the UEFI secure 41*4882a593Smuzhiyun boot and the shim. This functionality is provided by the shim_lock verifier. It 42*4882a593Smuzhiyun is built into the @file{core.img} and is registered if the UEFI secure boot is 43*4882a593Smuzhiyun-enabled. 44*4882a593Smuzhiyun+enabled. The @samp{shim_lock} variable is set to @samp{y} when shim_lock verifier 45*4882a593Smuzhiyun+is registered. If it is desired to use UEFI secure boot without shim, one can 46*4882a593Smuzhiyun+disable shim_lock by disabling shim verification with MokSbState UEFI variable 47*4882a593Smuzhiyun+or by building grub image with @samp{--disable-shim-lock} option. 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun All GRUB modules not stored in the @file{core.img}, OS kernels, ACPI tables, 50*4882a593Smuzhiyun Device Trees, etc. have to be signed, e.g, using PGP. Additionally, the commands 51*4882a593Smuzhiyundiff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c 52*4882a593Smuzhiyunindex 5d7210a..41dadcd 100644 53*4882a593Smuzhiyun--- a/grub-core/kern/efi/sb.c 54*4882a593Smuzhiyun+++ b/grub-core/kern/efi/sb.c 55*4882a593Smuzhiyun@@ -21,9 +21,11 @@ 56*4882a593Smuzhiyun #include <grub/efi/efi.h> 57*4882a593Smuzhiyun #include <grub/efi/pe32.h> 58*4882a593Smuzhiyun #include <grub/efi/sb.h> 59*4882a593Smuzhiyun+#include <grub/env.h> 60*4882a593Smuzhiyun #include <grub/err.h> 61*4882a593Smuzhiyun #include <grub/file.h> 62*4882a593Smuzhiyun #include <grub/i386/linux.h> 63*4882a593Smuzhiyun+#include <grub/kernel.h> 64*4882a593Smuzhiyun #include <grub/mm.h> 65*4882a593Smuzhiyun #include <grub/types.h> 66*4882a593Smuzhiyun #include <grub/verify.h> 67*4882a593Smuzhiyun@@ -160,14 +162,27 @@ struct grub_file_verifier shim_lock_verifier = 68*4882a593Smuzhiyun void 69*4882a593Smuzhiyun grub_shim_lock_verifier_setup (void) 70*4882a593Smuzhiyun { 71*4882a593Smuzhiyun+ struct grub_module_header *header; 72*4882a593Smuzhiyun grub_efi_shim_lock_protocol_t *sl = 73*4882a593Smuzhiyun grub_efi_locate_protocol (&shim_lock_guid, 0); 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun+ /* shim_lock is missing, check if GRUB image is built with --disable-shim-lock. */ 76*4882a593Smuzhiyun if (!sl) 77*4882a593Smuzhiyun- return; 78*4882a593Smuzhiyun+ { 79*4882a593Smuzhiyun+ FOR_MODULES (header) 80*4882a593Smuzhiyun+ { 81*4882a593Smuzhiyun+ if (header->type == OBJ_TYPE_DISABLE_SHIM_LOCK) 82*4882a593Smuzhiyun+ return; 83*4882a593Smuzhiyun+ } 84*4882a593Smuzhiyun+ } 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun+ /* Secure Boot is off. Do not load shim_lock. */ 87*4882a593Smuzhiyun if (grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED) 88*4882a593Smuzhiyun return; 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun+ /* Enforce shim_lock_verifier. */ 91*4882a593Smuzhiyun grub_verifier_register (&shim_lock_verifier); 92*4882a593Smuzhiyun+ 93*4882a593Smuzhiyun+ grub_env_set ("shim_lock", "y"); 94*4882a593Smuzhiyun+ grub_env_export ("shim_lock"); 95*4882a593Smuzhiyun } 96*4882a593Smuzhiyundiff --git a/include/grub/kernel.h b/include/grub/kernel.h 97*4882a593Smuzhiyunindex 133a37c..abbca5e 100644 98*4882a593Smuzhiyun--- a/include/grub/kernel.h 99*4882a593Smuzhiyun+++ b/include/grub/kernel.h 100*4882a593Smuzhiyun@@ -29,7 +29,8 @@ enum 101*4882a593Smuzhiyun OBJ_TYPE_CONFIG, 102*4882a593Smuzhiyun OBJ_TYPE_PREFIX, 103*4882a593Smuzhiyun OBJ_TYPE_PUBKEY, 104*4882a593Smuzhiyun- OBJ_TYPE_DTB 105*4882a593Smuzhiyun+ OBJ_TYPE_DTB, 106*4882a593Smuzhiyun+ OBJ_TYPE_DISABLE_SHIM_LOCK 107*4882a593Smuzhiyun }; 108*4882a593Smuzhiyun 109*4882a593Smuzhiyun /* The module header. */ 110*4882a593Smuzhiyundiff --git a/include/grub/util/install.h b/include/grub/util/install.h 111*4882a593Smuzhiyunindex 8cb5056..11a8df8 100644 112*4882a593Smuzhiyun--- a/include/grub/util/install.h 113*4882a593Smuzhiyun+++ b/include/grub/util/install.h 114*4882a593Smuzhiyun@@ -65,6 +65,8 @@ 115*4882a593Smuzhiyun N_("embed FILE as public key for signature checking"), 0}, \ 116*4882a593Smuzhiyun { "sbat", GRUB_INSTALL_OPTIONS_SBAT, N_("FILE"), 0, \ 117*4882a593Smuzhiyun N_("SBAT metadata"), 0 }, \ 118*4882a593Smuzhiyun+ { "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, \ 119*4882a593Smuzhiyun+ N_("disable shim_lock verifier"), 0 }, \ 120*4882a593Smuzhiyun { "verbose", 'v', 0, 0, \ 121*4882a593Smuzhiyun N_("print verbose messages."), 1 } 122*4882a593Smuzhiyun 123*4882a593Smuzhiyun@@ -125,7 +127,8 @@ enum grub_install_options { 124*4882a593Smuzhiyun GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE, 125*4882a593Smuzhiyun GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS, 126*4882a593Smuzhiyun GRUB_INSTALL_OPTIONS_DTB, 127*4882a593Smuzhiyun- GRUB_INSTALL_OPTIONS_SBAT 128*4882a593Smuzhiyun+ GRUB_INSTALL_OPTIONS_SBAT, 129*4882a593Smuzhiyun+ GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK 130*4882a593Smuzhiyun }; 131*4882a593Smuzhiyun 132*4882a593Smuzhiyun extern char *grub_install_source_directory; 133*4882a593Smuzhiyun@@ -187,7 +190,7 @@ grub_install_generate_image (const char *dir, const char *prefix, 134*4882a593Smuzhiyun const struct grub_install_image_target_desc *image_target, 135*4882a593Smuzhiyun int note, 136*4882a593Smuzhiyun grub_compression_t comp, const char *dtb_file, 137*4882a593Smuzhiyun- const char *sbat_path); 138*4882a593Smuzhiyun+ const char *sbat_path, const int disable_shim_lock); 139*4882a593Smuzhiyun 140*4882a593Smuzhiyun const struct grub_install_image_target_desc * 141*4882a593Smuzhiyun grub_install_get_image_target (const char *arg); 142*4882a593Smuzhiyundiff --git a/util/grub-install-common.c b/util/grub-install-common.c 143*4882a593Smuzhiyunindex 1fcccd2..13d9fe9 100644 144*4882a593Smuzhiyun--- a/util/grub-install-common.c 145*4882a593Smuzhiyun+++ b/util/grub-install-common.c 146*4882a593Smuzhiyun@@ -308,6 +308,7 @@ handle_install_list (struct install_list *il, const char *val, 147*4882a593Smuzhiyun static char **pubkeys; 148*4882a593Smuzhiyun static size_t npubkeys; 149*4882a593Smuzhiyun static char *sbat; 150*4882a593Smuzhiyun+static int disable_shim_lock; 151*4882a593Smuzhiyun static grub_compression_t compression; 152*4882a593Smuzhiyun 153*4882a593Smuzhiyun int 154*4882a593Smuzhiyun@@ -344,6 +345,9 @@ grub_install_parse (int key, char *arg) 155*4882a593Smuzhiyun 156*4882a593Smuzhiyun sbat = xstrdup (arg); 157*4882a593Smuzhiyun return 1; 158*4882a593Smuzhiyun+ case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK: 159*4882a593Smuzhiyun+ disable_shim_lock = 1; 160*4882a593Smuzhiyun+ return 1; 161*4882a593Smuzhiyun 162*4882a593Smuzhiyun case GRUB_INSTALL_OPTIONS_VERBOSITY: 163*4882a593Smuzhiyun verbosity++; 164*4882a593Smuzhiyun@@ -506,10 +510,11 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, 165*4882a593Smuzhiyun " --output '%s' " 166*4882a593Smuzhiyun " --dtb '%s' " 167*4882a593Smuzhiyun "--sbat '%s' " 168*4882a593Smuzhiyun- "--format '%s' --compression '%s' %s %s\n", 169*4882a593Smuzhiyun+ "--format '%s' --compression '%s' %s %s %s\n", 170*4882a593Smuzhiyun dir, prefix, 171*4882a593Smuzhiyun outname, dtb ? : "", sbat ? : "", mkimage_target, 172*4882a593Smuzhiyun- compnames[compression], note ? "--note" : "", s); 173*4882a593Smuzhiyun+ compnames[compression], note ? "--note" : "", 174*4882a593Smuzhiyun+ disable_shim_lock ? "--disable-shim-lock" : "", s); 175*4882a593Smuzhiyun free (s); 176*4882a593Smuzhiyun 177*4882a593Smuzhiyun tgt = grub_install_get_image_target (mkimage_target); 178*4882a593Smuzhiyun@@ -519,7 +524,8 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, 179*4882a593Smuzhiyun grub_install_generate_image (dir, prefix, fp, outname, 180*4882a593Smuzhiyun modules.entries, memdisk_path, 181*4882a593Smuzhiyun pubkeys, npubkeys, config_path, tgt, 182*4882a593Smuzhiyun- note, compression, dtb, sbat); 183*4882a593Smuzhiyun+ note, compression, dtb, sbat, 184*4882a593Smuzhiyun+ disable_shim_lock); 185*4882a593Smuzhiyun while (dc--) 186*4882a593Smuzhiyun grub_install_pop_module (); 187*4882a593Smuzhiyun } 188*4882a593Smuzhiyundiff --git a/util/grub-mkimage.c b/util/grub-mkimage.c 189*4882a593Smuzhiyunindex 75b8847..c0d5599 100644 190*4882a593Smuzhiyun--- a/util/grub-mkimage.c 191*4882a593Smuzhiyun+++ b/util/grub-mkimage.c 192*4882a593Smuzhiyun@@ -82,6 +82,7 @@ static struct argp_option options[] = { 193*4882a593Smuzhiyun {"format", 'O', N_("FORMAT"), 0, 0, 0}, 194*4882a593Smuzhiyun {"compression", 'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0}, 195*4882a593Smuzhiyun {"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0}, 196*4882a593Smuzhiyun+ {"disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, N_("disable shim_lock verifier"), 0}, 197*4882a593Smuzhiyun {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, 198*4882a593Smuzhiyun { 0, 0, 0, 0, 0, 0 } 199*4882a593Smuzhiyun }; 200*4882a593Smuzhiyun@@ -126,6 +127,7 @@ struct arguments 201*4882a593Smuzhiyun char *config; 202*4882a593Smuzhiyun char *sbat; 203*4882a593Smuzhiyun int note; 204*4882a593Smuzhiyun+ int disable_shim_lock; 205*4882a593Smuzhiyun const struct grub_install_image_target_desc *image_target; 206*4882a593Smuzhiyun grub_compression_t comp; 207*4882a593Smuzhiyun }; 208*4882a593Smuzhiyun@@ -233,6 +235,10 @@ argp_parser (int key, char *arg, struct argp_state *state) 209*4882a593Smuzhiyun arguments->sbat = xstrdup (arg); 210*4882a593Smuzhiyun break; 211*4882a593Smuzhiyun 212*4882a593Smuzhiyun+ case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK: 213*4882a593Smuzhiyun+ arguments->disable_shim_lock = 1; 214*4882a593Smuzhiyun+ break; 215*4882a593Smuzhiyun+ 216*4882a593Smuzhiyun case 'v': 217*4882a593Smuzhiyun verbosity++; 218*4882a593Smuzhiyun break; 219*4882a593Smuzhiyun@@ -319,7 +325,7 @@ main (int argc, char *argv[]) 220*4882a593Smuzhiyun arguments.npubkeys, arguments.config, 221*4882a593Smuzhiyun arguments.image_target, arguments.note, 222*4882a593Smuzhiyun arguments.comp, arguments.dtb, 223*4882a593Smuzhiyun- arguments.sbat); 224*4882a593Smuzhiyun+ arguments.sbat, arguments.disable_shim_lock); 225*4882a593Smuzhiyun 226*4882a593Smuzhiyun if (grub_util_file_sync (fp) < 0) 227*4882a593Smuzhiyun grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout", 228*4882a593Smuzhiyundiff --git a/util/mkimage.c b/util/mkimage.c 229*4882a593Smuzhiyunindex b354ec1..a26cf76 100644 230*4882a593Smuzhiyun--- a/util/mkimage.c 231*4882a593Smuzhiyun+++ b/util/mkimage.c 232*4882a593Smuzhiyun@@ -870,7 +870,7 @@ grub_install_generate_image (const char *dir, const char *prefix, 233*4882a593Smuzhiyun size_t npubkeys, char *config_path, 234*4882a593Smuzhiyun const struct grub_install_image_target_desc *image_target, 235*4882a593Smuzhiyun int note, grub_compression_t comp, const char *dtb_path, 236*4882a593Smuzhiyun- const char *sbat_path) 237*4882a593Smuzhiyun+ const char *sbat_path, int disable_shim_lock) 238*4882a593Smuzhiyun { 239*4882a593Smuzhiyun char *kernel_img, *core_img; 240*4882a593Smuzhiyun size_t total_module_size, core_size; 241*4882a593Smuzhiyun@@ -929,6 +929,9 @@ grub_install_generate_image (const char *dir, const char *prefix, 242*4882a593Smuzhiyun if (sbat_path != NULL && image_target->id != IMAGE_EFI) 243*4882a593Smuzhiyun grub_util_error (_(".sbat section can be embedded into EFI images only")); 244*4882a593Smuzhiyun 245*4882a593Smuzhiyun+ if (disable_shim_lock) 246*4882a593Smuzhiyun+ total_module_size += sizeof (struct grub_module_header); 247*4882a593Smuzhiyun+ 248*4882a593Smuzhiyun if (config_path) 249*4882a593Smuzhiyun { 250*4882a593Smuzhiyun config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1); 251*4882a593Smuzhiyun@@ -1065,6 +1068,16 @@ grub_install_generate_image (const char *dir, const char *prefix, 252*4882a593Smuzhiyun offset += dtb_size; 253*4882a593Smuzhiyun } 254*4882a593Smuzhiyun 255*4882a593Smuzhiyun+ if (disable_shim_lock) 256*4882a593Smuzhiyun+ { 257*4882a593Smuzhiyun+ struct grub_module_header *header; 258*4882a593Smuzhiyun+ 259*4882a593Smuzhiyun+ header = (struct grub_module_header *) (kernel_img + offset); 260*4882a593Smuzhiyun+ header->type = grub_host_to_target32 (OBJ_TYPE_DISABLE_SHIM_LOCK); 261*4882a593Smuzhiyun+ header->size = grub_host_to_target32 (sizeof (*header)); 262*4882a593Smuzhiyun+ offset += sizeof (*header); 263*4882a593Smuzhiyun+ } 264*4882a593Smuzhiyun+ 265*4882a593Smuzhiyun if (config_path) 266*4882a593Smuzhiyun { 267*4882a593Smuzhiyun struct grub_module_header *header; 268*4882a593Smuzhiyun-- 269*4882a593Smuzhiyun2.14.2 270*4882a593Smuzhiyun 271