Automatically call linuxefi from linux if secure boot is enabled and

the kernel is signed, to hand over to the kernel without calling
ExitBootServices.  Otherwise, linux will fall through to previous
code, call ExitBootServices itself, and boot the kernel normally.
This commit is contained in:
Colin Watson 2013-01-29 06:12:13 +00:00
parent 6c50d31a9a
commit 0d39b369ff
5 changed files with 136 additions and 1 deletions

4
debian/changelog vendored
View File

@ -15,6 +15,10 @@ grub2 (2.00-13) UNRELEASED; urgency=low
with EFI handover patches, avoiding ExitBootServices.
- Temporarily make linuxefi refuse to validate kernels in the absence of
a shim, until we get some other details worked out.
- Automatically call linuxefi from linux if secure boot is enabled and
the kernel is signed, to hand over to the kernel without calling
ExitBootServices. Otherwise, linux will fall through to previous
code, call ExitBootServices itself, and boot the kernel normally.
-- Colin Watson <cjwatson@debian.org> Mon, 28 Jan 2013 11:08:07 +0000

View File

@ -0,0 +1,87 @@
Description: If running under UEFI secure boot, attempt to use linuxefi loader
Author: Colin Watson <cjwatson@ubuntu.com>
Author: Steve Langasek <steve.langasek@canonical.com>
Forwarded: no
Last-Update: 2012-10-05
Index: b/grub-core/loader/i386/efi/linux.c
===================================================================
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -234,7 +234,7 @@
if (! grub_linuxefi_secure_validate (kernel, filelen))
{
- grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
+ grub_error (GRUB_ERR_ACCESS_DENIED, N_("%s has invalid signature"), argv[0]);
grub_free (kernel);
goto fail;
}
Index: b/grub-core/loader/i386/linux.c
===================================================================
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -75,6 +75,8 @@
static struct linux_kernel_params linux_params;
static char *linux_cmdline;
#ifdef GRUB_MACHINE_EFI
+static int using_linuxefi;
+static grub_command_t initrdefi_cmd;
static grub_efi_uintn_t efi_mmap_size;
#else
static const grub_size_t efi_mmap_size = 0;
@@ -684,6 +686,41 @@
grub_dl_ref (my_mod);
+#ifdef GRUB_MACHINE_EFI
+ using_linuxefi = 0;
+ if (grub_efi_secure_boot ())
+ {
+ /* Try linuxefi first, which will require a successful signature check
+ and then hand over to the kernel without calling ExitBootServices.
+ If that fails, however, fall back to calling ExitBootServices
+ ourselves and then booting an unsigned kernel. */
+ grub_dl_t mod;
+ grub_command_t linuxefi_cmd;
+
+ grub_dprintf ("linux", "Secure Boot enabled: trying linuxefi\n");
+
+ mod = grub_dl_load ("linuxefi");
+ if (mod)
+ {
+ grub_dl_ref (mod);
+ linuxefi_cmd = grub_command_find ("linuxefi");
+ initrdefi_cmd = grub_command_find ("initrdefi");
+ if (linuxefi_cmd && initrdefi_cmd)
+ {
+ (linuxefi_cmd->func) (linuxefi_cmd, argc, argv);
+ if (grub_errno == GRUB_ERR_NONE)
+ {
+ grub_dprintf ("linux", "Handing off to linuxefi\n");
+ using_linuxefi = 1;
+ return GRUB_ERR_NONE;
+ }
+ grub_dprintf ("linux", "linuxefi failed (%d)\n", grub_errno);
+ grub_errno = GRUB_ERR_NONE;
+ }
+ }
+ }
+#endif
+
if (argc == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
@@ -1050,6 +1087,12 @@
int nfiles = 0;
grub_uint8_t *ptr;
+#ifdef GRUB_MACHINE_EFI
+ /* If we're using linuxefi, just forward to initrdefi. */
+ if (using_linuxefi && initrdefi_cmd)
+ return (initrdefi_cmd->func) (initrdefi_cmd, argc, argv);
+#endif
+
if (argc == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));

View File

@ -40,3 +40,4 @@ linuxefi.patch
linuxefi_amd64_only.patch
linuxefi_debug.patch
linuxefi_require_shim.patch
linuxefi_non_sb_fallback.patch

View File

@ -234,7 +234,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (! grub_linuxefi_secure_validate (kernel, filelen))
{
grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
grub_error (GRUB_ERR_ACCESS_DENIED, N_("%s has invalid signature"), argv[0]);
grub_free (kernel);
goto fail;
}

View File

@ -75,6 +75,8 @@ static grub_size_t maximal_cmdline_size;
static struct linux_kernel_params linux_params;
static char *linux_cmdline;
#ifdef GRUB_MACHINE_EFI
static int using_linuxefi;
static grub_command_t initrdefi_cmd;
static grub_efi_uintn_t efi_mmap_size;
#else
static const grub_size_t efi_mmap_size = 0;
@ -684,6 +686,41 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dl_ref (my_mod);
#ifdef GRUB_MACHINE_EFI
using_linuxefi = 0;
if (grub_efi_secure_boot ())
{
/* Try linuxefi first, which will require a successful signature check
and then hand over to the kernel without calling ExitBootServices.
If that fails, however, fall back to calling ExitBootServices
ourselves and then booting an unsigned kernel. */
grub_dl_t mod;
grub_command_t linuxefi_cmd;
grub_dprintf ("linux", "Secure Boot enabled: trying linuxefi\n");
mod = grub_dl_load ("linuxefi");
if (mod)
{
grub_dl_ref (mod);
linuxefi_cmd = grub_command_find ("linuxefi");
initrdefi_cmd = grub_command_find ("initrdefi");
if (linuxefi_cmd && initrdefi_cmd)
{
(linuxefi_cmd->func) (linuxefi_cmd, argc, argv);
if (grub_errno == GRUB_ERR_NONE)
{
grub_dprintf ("linux", "Handing off to linuxefi\n");
using_linuxefi = 1;
return GRUB_ERR_NONE;
}
grub_dprintf ("linux", "linuxefi failed (%d)\n", grub_errno);
grub_errno = GRUB_ERR_NONE;
}
}
}
#endif
if (argc == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
@ -1050,6 +1087,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
int nfiles = 0;
grub_uint8_t *ptr;
#ifdef GRUB_MACHINE_EFI
/* If we're using linuxefi, just forward to initrdefi. */
if (using_linuxefi && initrdefi_cmd)
return (initrdefi_cmd->func) (initrdefi_cmd, argc, argv);
#endif
if (argc == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));