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