1*4882a593SmuzhiyunFrom 8f73052885892bc0dbc01e297f79d7cf4925e491 Mon Sep 17 00:00:00 2001
2*4882a593SmuzhiyunFrom: Javier Martinez Canillas <javierm@redhat.com>
3*4882a593SmuzhiyunDate: Mon, 28 Sep 2020 20:08:33 +0200
4*4882a593SmuzhiyunSubject: [PATCH] efi: Use grub_is_lockdown() instead of hardcoding a disabled
5*4882a593Smuzhiyun modules list
6*4882a593Smuzhiyun
7*4882a593SmuzhiyunNow the GRUB can check if it has been locked down and this can be used to
8*4882a593Smuzhiyunprevent executing commands that can be utilized to circumvent the UEFI
9*4882a593SmuzhiyunSecure Boot mechanisms. So, instead of hardcoding a list of modules that
10*4882a593Smuzhiyunhave to be disabled, prevent the usage of commands that can be dangerous.
11*4882a593Smuzhiyun
12*4882a593SmuzhiyunThis not only allows the commands to be disabled on other platforms, but
13*4882a593Smuzhiyunalso properly separate the concerns. Since the shim_lock verifier logic
14*4882a593Smuzhiyunshould be only about preventing to run untrusted binaries and not about
15*4882a593Smuzhiyundefining these kind of policies.
16*4882a593Smuzhiyun
17*4882a593SmuzhiyunSigned-off-by: Javier Martinez Canillas <javierm@redhat.com>
18*4882a593SmuzhiyunReviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
19*4882a593SmuzhiyunSigned-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
20*4882a593Smuzhiyun---
21*4882a593Smuzhiyun docs/grub.texi                  | 15 +++++++++------
22*4882a593Smuzhiyun grub-core/commands/i386/wrmsr.c |  5 +++--
23*4882a593Smuzhiyun grub-core/commands/iorw.c       | 19 ++++++++++---------
24*4882a593Smuzhiyun grub-core/commands/memrw.c      | 19 ++++++++++---------
25*4882a593Smuzhiyun grub-core/kern/efi/sb.c         | 41 -----------------------------------------
26*4882a593Smuzhiyun 5 files changed, 32 insertions(+), 67 deletions(-)
27*4882a593Smuzhiyun
28*4882a593Smuzhiyundiff --git a/docs/grub.texi b/docs/grub.texi
29*4882a593Smuzhiyunindex bdbb329..bbe60a4 100644
30*4882a593Smuzhiyun--- a/docs/grub.texi
31*4882a593Smuzhiyun+++ b/docs/grub.texi
32*4882a593Smuzhiyun@@ -5256,6 +5256,9 @@ only applies to the particular cpu/core/thread that runs the command.
33*4882a593Smuzhiyun Also, if you specify a reserved or unimplemented MSR address, it will
34*4882a593Smuzhiyun cause a general protection exception (which is not currently being handled)
35*4882a593Smuzhiyun and the system will reboot.
36*4882a593Smuzhiyun+
37*4882a593Smuzhiyun+Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}).
38*4882a593Smuzhiyun+      This is done to prevent subverting various security mechanisms.
39*4882a593Smuzhiyun @end deffn
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun @node xen_hypervisor
42*4882a593Smuzhiyun@@ -5752,12 +5755,12 @@ boot and the shim. This functionality is provided by the shim_lock verifier. It
43*4882a593Smuzhiyun is built into the @file{core.img} and is registered if the UEFI secure boot is
44*4882a593Smuzhiyun enabled.
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun-All modules not stored in the @file{core.img} and the ACPI tables for the
47*4882a593Smuzhiyun-@command{acpi} command have to be signed, e.g. using PGP. Additionally, the
48*4882a593Smuzhiyun-@command{iorw}, the @command{memrw} and the @command{wrmsr} commands are
49*4882a593Smuzhiyun-prohibited if the UEFI secure boot is enabled. This is done due to
50*4882a593Smuzhiyun-security reasons. All above mentioned requirements are enforced by the
51*4882a593Smuzhiyun-shim_lock verifier logic.
52*4882a593Smuzhiyun+All GRUB modules not stored in the @file{core.img}, OS kernels, ACPI tables,
53*4882a593Smuzhiyun+Device Trees, etc. have to be signed, e.g, using PGP. Additionally, the commands
54*4882a593Smuzhiyun+that can be used to subvert the UEFI secure boot mechanism, such as @command{iorw}
55*4882a593Smuzhiyun+and @command{memrw} will not be available when the UEFI secure boot is enabled.
56*4882a593Smuzhiyun+This is done for security reasons and are enforced by the GRUB Lockdown mechanism
57*4882a593Smuzhiyun+(@pxref{Lockdown}).
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun @node Measured Boot
60*4882a593Smuzhiyun @section Measuring boot components
61*4882a593Smuzhiyundiff --git a/grub-core/commands/i386/wrmsr.c b/grub-core/commands/i386/wrmsr.c
62*4882a593Smuzhiyunindex 9c5e510..56a29c2 100644
63*4882a593Smuzhiyun--- a/grub-core/commands/i386/wrmsr.c
64*4882a593Smuzhiyun+++ b/grub-core/commands/i386/wrmsr.c
65*4882a593Smuzhiyun@@ -24,6 +24,7 @@
66*4882a593Smuzhiyun #include <grub/env.h>
67*4882a593Smuzhiyun #include <grub/command.h>
68*4882a593Smuzhiyun #include <grub/extcmd.h>
69*4882a593Smuzhiyun+#include <grub/lockdown.h>
70*4882a593Smuzhiyun #include <grub/i18n.h>
71*4882a593Smuzhiyun #include <grub/i386/cpuid.h>
72*4882a593Smuzhiyun #include <grub/i386/wrmsr.h>
73*4882a593Smuzhiyun@@ -83,8 +84,8 @@ grub_cmd_msr_write (grub_command_t cmd __attribute__ ((unused)), int argc, char
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun GRUB_MOD_INIT(wrmsr)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun-  cmd_write = grub_register_command ("wrmsr", grub_cmd_msr_write, N_("ADDR VALUE"),
78*4882a593Smuzhiyun-				     N_("Write a value to a CPU model specific register."));
79*4882a593Smuzhiyun+  cmd_write = grub_register_command_lockdown ("wrmsr", grub_cmd_msr_write, N_("ADDR VALUE"),
80*4882a593Smuzhiyun+                                              N_("Write a value to a CPU model specific register."));
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun GRUB_MOD_FINI(wrmsr)
84*4882a593Smuzhiyundiff --git a/grub-core/commands/iorw.c b/grub-core/commands/iorw.c
85*4882a593Smuzhiyunindex a0c164e..584baec 100644
86*4882a593Smuzhiyun--- a/grub-core/commands/iorw.c
87*4882a593Smuzhiyun+++ b/grub-core/commands/iorw.c
88*4882a593Smuzhiyun@@ -23,6 +23,7 @@
89*4882a593Smuzhiyun #include <grub/env.h>
90*4882a593Smuzhiyun #include <grub/cpu/io.h>
91*4882a593Smuzhiyun #include <grub/i18n.h>
92*4882a593Smuzhiyun+#include <grub/lockdown.h>
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun GRUB_MOD_LICENSE ("GPLv3+");
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun@@ -131,17 +132,17 @@ GRUB_MOD_INIT(memrw)
97*4882a593Smuzhiyun 			  N_("PORT"), N_("Read 32-bit value from PORT."),
98*4882a593Smuzhiyun 			  options);
99*4882a593Smuzhiyun   cmd_write_byte =
100*4882a593Smuzhiyun-    grub_register_command ("outb", grub_cmd_write,
101*4882a593Smuzhiyun-			   N_("PORT VALUE [MASK]"),
102*4882a593Smuzhiyun-			   N_("Write 8-bit VALUE to PORT."));
103*4882a593Smuzhiyun+    grub_register_command_lockdown ("outb", grub_cmd_write,
104*4882a593Smuzhiyun+                                    N_("PORT VALUE [MASK]"),
105*4882a593Smuzhiyun+                                    N_("Write 8-bit VALUE to PORT."));
106*4882a593Smuzhiyun   cmd_write_word =
107*4882a593Smuzhiyun-    grub_register_command ("outw", grub_cmd_write,
108*4882a593Smuzhiyun-			   N_("PORT VALUE [MASK]"),
109*4882a593Smuzhiyun-			   N_("Write 16-bit VALUE to PORT."));
110*4882a593Smuzhiyun+    grub_register_command_lockdown ("outw", grub_cmd_write,
111*4882a593Smuzhiyun+                                    N_("PORT VALUE [MASK]"),
112*4882a593Smuzhiyun+                                    N_("Write 16-bit VALUE to PORT."));
113*4882a593Smuzhiyun   cmd_write_dword =
114*4882a593Smuzhiyun-    grub_register_command ("outl", grub_cmd_write,
115*4882a593Smuzhiyun-			   N_("ADDR VALUE [MASK]"),
116*4882a593Smuzhiyun-			   N_("Write 32-bit VALUE to PORT."));
117*4882a593Smuzhiyun+    grub_register_command_lockdown ("outl", grub_cmd_write,
118*4882a593Smuzhiyun+                                    N_("ADDR VALUE [MASK]"),
119*4882a593Smuzhiyun+                                    N_("Write 32-bit VALUE to PORT."));
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun GRUB_MOD_FINI(memrw)
123*4882a593Smuzhiyundiff --git a/grub-core/commands/memrw.c b/grub-core/commands/memrw.c
124*4882a593Smuzhiyunindex 98769ea..d401a6d 100644
125*4882a593Smuzhiyun--- a/grub-core/commands/memrw.c
126*4882a593Smuzhiyun+++ b/grub-core/commands/memrw.c
127*4882a593Smuzhiyun@@ -22,6 +22,7 @@
128*4882a593Smuzhiyun #include <grub/extcmd.h>
129*4882a593Smuzhiyun #include <grub/env.h>
130*4882a593Smuzhiyun #include <grub/i18n.h>
131*4882a593Smuzhiyun+#include <grub/lockdown.h>
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun GRUB_MOD_LICENSE ("GPLv3+");
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun@@ -133,17 +134,17 @@ GRUB_MOD_INIT(memrw)
136*4882a593Smuzhiyun 			  N_("ADDR"), N_("Read 32-bit value from ADDR."),
137*4882a593Smuzhiyun 			  options);
138*4882a593Smuzhiyun   cmd_write_byte =
139*4882a593Smuzhiyun-    grub_register_command ("write_byte", grub_cmd_write,
140*4882a593Smuzhiyun-			   N_("ADDR VALUE [MASK]"),
141*4882a593Smuzhiyun-			   N_("Write 8-bit VALUE to ADDR."));
142*4882a593Smuzhiyun+    grub_register_command_lockdown ("write_byte", grub_cmd_write,
143*4882a593Smuzhiyun+                                    N_("ADDR VALUE [MASK]"),
144*4882a593Smuzhiyun+                                    N_("Write 8-bit VALUE to ADDR."));
145*4882a593Smuzhiyun   cmd_write_word =
146*4882a593Smuzhiyun-    grub_register_command ("write_word", grub_cmd_write,
147*4882a593Smuzhiyun-			   N_("ADDR VALUE [MASK]"),
148*4882a593Smuzhiyun-			   N_("Write 16-bit VALUE to ADDR."));
149*4882a593Smuzhiyun+    grub_register_command_lockdown ("write_word", grub_cmd_write,
150*4882a593Smuzhiyun+                                    N_("ADDR VALUE [MASK]"),
151*4882a593Smuzhiyun+                                    N_("Write 16-bit VALUE to ADDR."));
152*4882a593Smuzhiyun   cmd_write_dword =
153*4882a593Smuzhiyun-    grub_register_command ("write_dword", grub_cmd_write,
154*4882a593Smuzhiyun-			   N_("ADDR VALUE [MASK]"),
155*4882a593Smuzhiyun-			   N_("Write 32-bit VALUE to ADDR."));
156*4882a593Smuzhiyun+    grub_register_command_lockdown ("write_dword", grub_cmd_write,
157*4882a593Smuzhiyun+                                    N_("ADDR VALUE [MASK]"),
158*4882a593Smuzhiyun+                                    N_("Write 32-bit VALUE to ADDR."));
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun GRUB_MOD_FINI(memrw)
162*4882a593Smuzhiyundiff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
163*4882a593Smuzhiyunindex ce3b7f6..5d7210a 100644
164*4882a593Smuzhiyun--- a/grub-core/kern/efi/sb.c
165*4882a593Smuzhiyun+++ b/grub-core/kern/efi/sb.c
166*4882a593Smuzhiyun@@ -30,9 +30,6 @@
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun static grub_efi_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun-/* List of modules which cannot be loaded if UEFI secure boot mode is enabled. */
171*4882a593Smuzhiyun-static const char * const disabled_mods[] = {"iorw", "memrw", NULL};
172*4882a593Smuzhiyun-
173*4882a593Smuzhiyun /*
174*4882a593Smuzhiyun  * Determine whether we're in secure boot mode.
175*4882a593Smuzhiyun  *
176*4882a593Smuzhiyun@@ -121,53 +118,15 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
177*4882a593Smuzhiyun 			 void **context __attribute__ ((unused)),
178*4882a593Smuzhiyun 			 enum grub_verify_flags *flags)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun-  const char *b, *e;
181*4882a593Smuzhiyun-  int i;
182*4882a593Smuzhiyun-
183*4882a593Smuzhiyun   *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun   switch (type & GRUB_FILE_TYPE_MASK)
186*4882a593Smuzhiyun     {
187*4882a593Smuzhiyun-    case GRUB_FILE_TYPE_GRUB_MODULE:
188*4882a593Smuzhiyun-      /* Establish GRUB module name. */
189*4882a593Smuzhiyun-      b = grub_strrchr (io->name, '/');
190*4882a593Smuzhiyun-      e = grub_strrchr (io->name, '.');
191*4882a593Smuzhiyun-
192*4882a593Smuzhiyun-      b = b ? (b + 1) : io->name;
193*4882a593Smuzhiyun-      e = e ? e : io->name + grub_strlen (io->name);
194*4882a593Smuzhiyun-      e = (e > b) ? e : io->name + grub_strlen (io->name);
195*4882a593Smuzhiyun-
196*4882a593Smuzhiyun-      for (i = 0; disabled_mods[i]; i++)
197*4882a593Smuzhiyun-	if (!grub_strncmp (b, disabled_mods[i], grub_strlen (b) - grub_strlen (e)))
198*4882a593Smuzhiyun-	  {
199*4882a593Smuzhiyun-	    grub_error (GRUB_ERR_ACCESS_DENIED,
200*4882a593Smuzhiyun-			N_("module cannot be loaded in UEFI secure boot mode: %s"),
201*4882a593Smuzhiyun-			io->name);
202*4882a593Smuzhiyun-	    return GRUB_ERR_ACCESS_DENIED;
203*4882a593Smuzhiyun-	  }
204*4882a593Smuzhiyun-
205*4882a593Smuzhiyun-      /* Fall through. */
206*4882a593Smuzhiyun-
207*4882a593Smuzhiyun-    case GRUB_FILE_TYPE_ACPI_TABLE:
208*4882a593Smuzhiyun-    case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE:
209*4882a593Smuzhiyun-      *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH;
210*4882a593Smuzhiyun-
211*4882a593Smuzhiyun-      return GRUB_ERR_NONE;
212*4882a593Smuzhiyun-
213*4882a593Smuzhiyun     case GRUB_FILE_TYPE_LINUX_KERNEL:
214*4882a593Smuzhiyun     case GRUB_FILE_TYPE_MULTIBOOT_KERNEL:
215*4882a593Smuzhiyun     case GRUB_FILE_TYPE_BSD_KERNEL:
216*4882a593Smuzhiyun     case GRUB_FILE_TYPE_XNU_KERNEL:
217*4882a593Smuzhiyun     case GRUB_FILE_TYPE_PLAN9_KERNEL:
218*4882a593Smuzhiyun-      for (i = 0; disabled_mods[i]; i++)
219*4882a593Smuzhiyun-	if (grub_dl_get (disabled_mods[i]))
220*4882a593Smuzhiyun-	  {
221*4882a593Smuzhiyun-	    grub_error (GRUB_ERR_ACCESS_DENIED,
222*4882a593Smuzhiyun-			N_("cannot boot due to dangerous module in memory: %s"),
223*4882a593Smuzhiyun-			disabled_mods[i]);
224*4882a593Smuzhiyun-	    return GRUB_ERR_ACCESS_DENIED;
225*4882a593Smuzhiyun-	  }
226*4882a593Smuzhiyun-
227*4882a593Smuzhiyun       *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun       /* Fall through. */
230*4882a593Smuzhiyun--
231*4882a593Smuzhiyun2.14.2
232*4882a593Smuzhiyun
233