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