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