diff --git a/debian/changelog b/debian/changelog index 44e5999ce..f3c51a2a7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,10 @@ grub2 (2.00-10) UNRELEASED; urgency=low * Remove /boot/grub/unicode.pf2 on purge of grub-efi-{amd64,i386} (closes: #697183). * Build with GCC 4.7. + * Merge from Ubuntu: + - Don't permit loading modules on UEFI Secure Boot (since in such a + setup the GRUB core image must be signed but it has no provision for + verifying module signatures). -- Colin Watson Wed, 02 Jan 2013 08:58:20 +0000 diff --git a/debian/patches/no_insmod_on_sb.patch b/debian/patches/no_insmod_on_sb.patch new file mode 100644 index 000000000..9b6e18974 --- /dev/null +++ b/debian/patches/no_insmod_on_sb.patch @@ -0,0 +1,89 @@ +Description: Don't permit loading modules on UEFI secure boot +Author: Matthew Garrett +Author: Colin Watson +Origin: vendor, http://pkgs.fedoraproject.org/cgit/grub2.git/tree/grub-2.00-no-insmod-on-sb.patch +Forwarded: no +Last-Update: 2013-01-02 + +Index: b/grub-core/kern/dl.c +=================================================================== +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -42,6 +42,10 @@ + #include + #endif + ++#ifdef GRUB_MACHINE_EFI ++#include ++#endif ++ + + + #pragma GCC diagnostic ignored "-Wcast-align" +@@ -668,6 +672,15 @@ + void *core = 0; + grub_dl_t mod = 0; + ++#ifdef GRUB_MACHINE_EFI ++ if (grub_efi_secure_boot ()) ++ { ++ grub_error (GRUB_ERR_ACCESS_DENIED, ++ "Secure Boot forbids loading module from %s", filename); ++ return 0; ++ } ++#endif ++ + file = grub_file_open (filename); + if (! file) + return 0; +Index: b/grub-core/kern/efi/efi.c +=================================================================== +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -259,6 +259,34 @@ + return NULL; + } + ++grub_efi_boolean_t ++grub_efi_secure_boot (void) ++{ ++ grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID; ++ grub_size_t datasize; ++ char *secure_boot = NULL; ++ char *setup_mode = NULL; ++ grub_efi_boolean_t ret = 0; ++ ++ secure_boot = grub_efi_get_variable ("SecureBoot", &efi_var_guid, &datasize); ++ ++ if (datasize != 1 || !secure_boot) ++ goto out; ++ ++ setup_mode = grub_efi_get_variable ("SetupMode", &efi_var_guid, &datasize); ++ ++ if (datasize != 1 || !setup_mode) ++ goto out; ++ ++ if (*secure_boot && !*setup_mode) ++ ret = 1; ++ ++ out: ++ grub_free (secure_boot); ++ grub_free (setup_mode); ++ return ret; ++} ++ + #pragma GCC diagnostic ignored "-Wcast-align" + + /* Search the mods section from the PE32/PE32+ image. This code uses +Index: b/include/grub/efi/efi.h +=================================================================== +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -69,6 +69,7 @@ + const grub_efi_guid_t *guid, + void *data, + grub_size_t datasize); ++grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void); + int + EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1, + const grub_efi_device_path_t *dp2); diff --git a/debian/patches/series b/debian/patches/series index 9bc24cf24..030d2d7f3 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -30,3 +30,4 @@ mkconfig_nonexistent_loopback.patch mount_readdir_symlink_failures.patch initrd_addr_min.patch gnulib_gets.patch +no_insmod_on_sb.patch diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 5b0aa6582..943eb0e62 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -42,6 +42,10 @@ #include #endif +#ifdef GRUB_MACHINE_EFI +#include +#endif + #pragma GCC diagnostic ignored "-Wcast-align" @@ -668,6 +672,15 @@ grub_dl_load_file (const char *filename) void *core = 0; grub_dl_t mod = 0; +#ifdef GRUB_MACHINE_EFI + if (grub_efi_secure_boot ()) + { + grub_error (GRUB_ERR_ACCESS_DENIED, + "Secure Boot forbids loading module from %s", filename); + return 0; + } +#endif + file = grub_file_open (filename); if (! file) return 0; diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index e8a62ec7b..f0e48dc19 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -259,6 +259,34 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, return NULL; } +grub_efi_boolean_t +grub_efi_secure_boot (void) +{ + grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID; + grub_size_t datasize; + char *secure_boot = NULL; + char *setup_mode = NULL; + grub_efi_boolean_t ret = 0; + + secure_boot = grub_efi_get_variable ("SecureBoot", &efi_var_guid, &datasize); + + if (datasize != 1 || !secure_boot) + goto out; + + setup_mode = grub_efi_get_variable ("SetupMode", &efi_var_guid, &datasize); + + if (datasize != 1 || !setup_mode) + goto out; + + if (*secure_boot && !*setup_mode) + ret = 1; + + out: + grub_free (secure_boot); + grub_free (setup_mode); + return ret; +} + #pragma GCC diagnostic ignored "-Wcast-align" /* Search the mods section from the PE32/PE32+ image. This code uses diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h index 489cf9e6d..db2169e76 100644 --- a/include/grub/efi/efi.h +++ b/include/grub/efi/efi.h @@ -69,6 +69,7 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var, const grub_efi_guid_t *guid, void *data, grub_size_t datasize); +grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void); int EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1, const grub_efi_device_path_t *dp2);