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