OBS-URL: https://build.opensuse.org/package/show/devel:openSUSE:Factory/shim?expand=0&rev=73
241 lines
7.1 KiB
Diff
241 lines
7.1 KiB
Diff
From 06495f692fa748a553ffbde8bfae2974d8c791c0 Mon Sep 17 00:00:00 2001
|
|
From: Peter Jones <pjones@redhat.com>
|
|
Date: Fri, 14 Feb 2014 15:38:25 -0500
|
|
Subject: [PATCH] Allow fallback to use the system's LoadImage/StartImage .
|
|
|
|
Track use of the system's LoadImage(), and when the next StartImage()
|
|
call is for an image the system verified, allow that to count as
|
|
participating, since it has been verified by the system's db.
|
|
|
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
|
---
|
|
replacements.c | 68 ++++++++++++++++++++++++++++++++++++++++++++-
|
|
replacements.h | 3 ++
|
|
shim.c | 85 ++++++++++++++++++++++++++++++++++-----------------------
|
|
3 files changed, 121 insertions(+), 35 deletions(-)
|
|
|
|
--- a/replacements.c
|
|
+++ b/replacements.c
|
|
@@ -60,26 +60,82 @@
|
|
|
|
static EFI_SYSTEM_TABLE *systab;
|
|
|
|
+static typeof(systab->BootServices->LoadImage) system_load_image;
|
|
static typeof(systab->BootServices->StartImage) system_start_image;
|
|
static typeof(systab->BootServices->Exit) system_exit;
|
|
static typeof(systab->BootServices->ExitBootServices) system_exit_boot_services;
|
|
|
|
+static EFI_HANDLE last_loaded_image;
|
|
+
|
|
void
|
|
unhook_system_services(void)
|
|
{
|
|
systab->BootServices->Exit = system_exit;
|
|
+ systab->BootServices->LoadImage = system_load_image;
|
|
systab->BootServices->StartImage = system_start_image;
|
|
systab->BootServices->ExitBootServices = system_exit_boot_services;
|
|
}
|
|
|
|
static EFI_STATUS EFIAPI
|
|
+load_image(BOOLEAN BootPolicy, EFI_HANDLE ParentImageHandle,
|
|
+ EFI_DEVICE_PATH *DevicePath, VOID *SourceBuffer,
|
|
+ UINTN SourceSize, EFI_HANDLE *ImageHandle)
|
|
+{
|
|
+ EFI_STATUS status;
|
|
+ unhook_system_services();
|
|
+
|
|
+ status = systab->BootServices->LoadImage(BootPolicy,
|
|
+ ParentImageHandle, DevicePath,
|
|
+ SourceBuffer, SourceSize, ImageHandle);
|
|
+ hook_system_services(systab);
|
|
+ if (EFI_ERROR(status))
|
|
+ last_loaded_image = NULL;
|
|
+ else
|
|
+ last_loaded_image = *ImageHandle;
|
|
+ return status;
|
|
+}
|
|
+
|
|
+static EFI_STATUS EFIAPI
|
|
start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 **exit_data)
|
|
{
|
|
EFI_STATUS status;
|
|
unhook_system_services();
|
|
+
|
|
+ /* We have to uninstall shim's protocol here, because if we're
|
|
+ * On the fallback.efi path, then our call pathway is:
|
|
+ *
|
|
+ * shim->fallback->shim->grub
|
|
+ * ^ ^ ^
|
|
+ * | | \- gets protocol #0
|
|
+ * | \- installs its protocol (#1)
|
|
+ * \- installs its protocol (#0)
|
|
+ * and if we haven't removed this, then grub will get the *first*
|
|
+ * shim's protocol, but it'll get the second shim's systab
|
|
+ * replacements. So even though it will participate and verify
|
|
+ * the kernel, the systab never finds out.
|
|
+ */
|
|
+ if (image_handle == last_loaded_image) {
|
|
+ loader_is_participating = 1;
|
|
+ uninstall_shim_protocols();
|
|
+ }
|
|
status = systab->BootServices->StartImage(image_handle, exit_data_size, exit_data);
|
|
- if (EFI_ERROR(status))
|
|
+ if (EFI_ERROR(status)) {
|
|
+ if (image_handle == last_loaded_image) {
|
|
+ EFI_STATUS status2 = install_shim_protocols();
|
|
+
|
|
+ if (EFI_ERROR(status2)) {
|
|
+ Print(L"Something has gone seriously wrong: %d\n",
|
|
+ status2);
|
|
+ Print(L"shim cannot continue, sorry.\n");
|
|
+ systab->BootServices->Stall(5000000);
|
|
+ systab->RuntimeServices->ResetSystem(
|
|
+ EfiResetShutdown,
|
|
+ EFI_SECURITY_VIOLATION, 0, NULL);
|
|
+ }
|
|
+ }
|
|
hook_system_services(systab);
|
|
+ loader_is_participating = 0;
|
|
+ }
|
|
return status;
|
|
}
|
|
|
|
@@ -123,6 +179,16 @@ hook_system_services(EFI_SYSTEM_TABLE *l
|
|
|
|
/* We need to hook various calls to make this work... */
|
|
|
|
+ /* We need LoadImage() hooked so that fallback.c can load shim
|
|
+ * without having to fake LoadImage as well. This allows it
|
|
+ * to call the system LoadImage(), and have us track the output
|
|
+ * and mark loader_is_participating in start_image. This means
|
|
+ * anything added by fallback has to be verified by the system db,
|
|
+ * which we want to preserve anyway, since that's all launching
|
|
+ * through BDS gives us. */
|
|
+ system_load_image = systab->BootServices->LoadImage;
|
|
+ systab->BootServices->LoadImage = load_image;
|
|
+
|
|
/* we need StartImage() so that we can allow chain booting to an
|
|
* image trusted by the firmware */
|
|
system_start_image = systab->BootServices->StartImage;
|
|
--- a/replacements.h
|
|
+++ b/replacements.h
|
|
@@ -41,4 +41,7 @@ extern int loader_is_participating;
|
|
extern void hook_system_services(EFI_SYSTEM_TABLE *local_systab);
|
|
extern void unhook_system_services(void);
|
|
|
|
+extern EFI_STATUS install_shim_protocols(void);
|
|
+extern void uninstall_shim_protocols(void);
|
|
+
|
|
#endif /* SHIM_REPLACEMENTS_H */
|
|
--- a/shim.c
|
|
+++ b/shim.c
|
|
@@ -1719,11 +1719,56 @@ EFI_STATUS set_second_stage (EFI_HANDLE
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
-EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
|
|
+static SHIM_LOCK shim_lock_interface;
|
|
+static EFI_HANDLE shim_lock_handle;
|
|
+
|
|
+EFI_STATUS
|
|
+install_shim_protocols(void)
|
|
+{
|
|
+ EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
|
+ EFI_STATUS efi_status;
|
|
+ /*
|
|
+ * Install the protocol
|
|
+ */
|
|
+ efi_status = uefi_call_wrapper(BS->InstallProtocolInterface, 4,
|
|
+ &shim_lock_handle, &shim_lock_guid,
|
|
+ EFI_NATIVE_INTERFACE, &shim_lock_interface);
|
|
+ if (EFI_ERROR(efi_status)) {
|
|
+ console_error(L"Could not install security protocol",
|
|
+ efi_status);
|
|
+ return efi_status;
|
|
+ }
|
|
+
|
|
+#if defined(OVERRIDE_SECURITY_POLICY)
|
|
+ /*
|
|
+ * Install the security protocol hook
|
|
+ */
|
|
+ security_policy_install(shim_verify);
|
|
+#endif
|
|
+
|
|
+ return EFI_SUCCESS;
|
|
+}
|
|
+
|
|
+void
|
|
+uninstall_shim_protocols(void)
|
|
{
|
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
|
- static SHIM_LOCK shim_lock_interface;
|
|
- EFI_HANDLE handle = NULL;
|
|
+#if defined(OVERRIDE_SECURITY_POLICY)
|
|
+ /*
|
|
+ * Clean up the security protocol hook
|
|
+ */
|
|
+ security_policy_uninstall();
|
|
+#endif
|
|
+
|
|
+ /*
|
|
+ * If we're back here then clean everything up before exiting
|
|
+ */
|
|
+ uefi_call_wrapper(BS->UninstallProtocolInterface, 3, shim_lock_handle,
|
|
+ &shim_lock_guid, &shim_lock_interface);
|
|
+}
|
|
+
|
|
+EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
|
|
+{
|
|
EFI_STATUS efi_status;
|
|
|
|
verification_method = VERIFIED_BY_NOTHING;
|
|
@@ -1776,24 +1821,9 @@ EFI_STATUS efi_main (EFI_HANDLE image_ha
|
|
loader_is_participating = 0;
|
|
}
|
|
|
|
- /*
|
|
- * Install the protocol
|
|
- */
|
|
- efi_status = uefi_call_wrapper(BS->InstallProtocolInterface, 4,
|
|
- &handle, &shim_lock_guid, EFI_NATIVE_INTERFACE,
|
|
- &shim_lock_interface);
|
|
- if (EFI_ERROR(efi_status)) {
|
|
- console_error(L"Could not install security protocol",
|
|
- efi_status);
|
|
+ efi_status = install_shim_protocols();
|
|
+ if (EFI_ERROR(efi_status))
|
|
return efi_status;
|
|
- }
|
|
-
|
|
-#if defined(OVERRIDE_SECURITY_POLICY)
|
|
- /*
|
|
- * Install the security protocol hook
|
|
- */
|
|
- security_policy_install(shim_verify);
|
|
-#endif
|
|
|
|
/*
|
|
* Enter MokManager if necessary
|
|
@@ -1820,20 +1850,7 @@ EFI_STATUS efi_main (EFI_HANDLE image_ha
|
|
|
|
efi_status = init_grub(image_handle);
|
|
|
|
-#if defined(OVERRIDE_SECURITY_POLICY)
|
|
- /*
|
|
- * Clean up the security protocol hook
|
|
- */
|
|
- security_policy_uninstall();
|
|
-#endif
|
|
-
|
|
- /*
|
|
- * If we're back here then clean everything up before exiting
|
|
- */
|
|
- uefi_call_wrapper(BS->UninstallProtocolInterface, 3, handle,
|
|
- &shim_lock_guid, &shim_lock_interface);
|
|
-
|
|
-
|
|
+ uninstall_shim_protocols();
|
|
/*
|
|
* Remove our hooks from system services.
|
|
*/
|