shim/shim-bsc919675-uninstall-shim-protocols.patch
Gary Ching-Pang Lin 610f2a3193 Accepting request 294902 from home:gary_lin:branches:devel:openSUSE:Factory
- Add shim-update-cryptlib.patch to update Cryptlib to r16559 and
  openssl to 0.9.8zf
- Add shim-bsc919675-uninstall-shim-protocols.patch to uninstall
  the shim protocols at Exit (bsc#919675)
- Add shim-bsc920515-fix-fallback-buffer-length.patch to adjust
  the buffer size for the boot options (bsc#920515) 
- Refresh shim-opensuse-cert-prompt.patch

OBS-URL: https://build.opensuse.org/request/show/294902
OBS-URL: https://build.opensuse.org/package/show/devel:openSUSE:Factory/shim?expand=0&rev=96
2015-04-08 06:34:44 +00:00

146 lines
4.7 KiB
Diff

From 4f8bf8c570dadf8044e7f3f260c55e3e22630998 Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Tue, 3 Mar 2015 16:53:11 +0800
Subject: [PATCH] Uninstall shim protocols at Exit()
Shim uninstalls its own protocol at the end of the program. However,
if the loaded binary, e.g. grub2, calls Exit(), the uninstall function
would never be called, i.e. the shim protocol handle existed even if
shim was gone. This already caused crashes on the dell machines with
the following steps:
1. boot to grub2 and press 'C' for the grub2 shell
2. type "exit" to quit the shell
3. boot to grub2 again and boot an OS
While grub2 uses the shim protocol to verify the OS image, it may get
the old dead shim handle and crash the system.
This commit adds uninstall_shim_protocols() to the hooked exit function
and always hook Exit to clean up the protocol handle.
Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
---
replacements.c | 35 ++++++++++++++++++++++++++++-------
replacements.h | 1 +
shim.c | 5 ++++-
3 files changed, 33 insertions(+), 8 deletions(-)
diff --git a/replacements.c b/replacements.c
index f7623d9..4d96e57 100644
--- a/replacements.c
+++ b/replacements.c
@@ -74,6 +74,10 @@ unhook_system_services(void)
return;
systab->BootServices->Exit = system_exit;
+
+ if (hook_exit_only)
+ return;
+
systab->BootServices->LoadImage = system_load_image;
systab->BootServices->StartImage = system_start_image;
systab->BootServices->ExitBootServices = system_exit_boot_services;
@@ -167,10 +171,24 @@ do_exit(EFI_HANDLE ImageHandle, EFI_STATUS ExitStatus,
{
EFI_STATUS status;
unhook_system_services();
+ uninstall_shim_protocols();
status = systab->BootServices->Exit(ImageHandle, ExitStatus, ExitDataSize, ExitData);
- if (EFI_ERROR(status))
+ if (EFI_ERROR(status)) {
+ EFI_STATUS status2 = install_shim_protocols();
+
+ if (EFI_ERROR(status2)) {
+ Print(L"Something has gone seriously wrong: %r\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);
+ }
return status;
}
@@ -182,6 +200,15 @@ hook_system_services(EFI_SYSTEM_TABLE *local_systab)
/* We need to hook various calls to make this work... */
+ /* we need to hook Exit() so that we can allow users to quit the
+ * bootloader and still e.g. start a new one or run an internal
+ * shell. */
+ system_exit = systab->BootServices->Exit;
+ systab->BootServices->Exit = do_exit;
+
+ if (hook_exit_only)
+ return;
+
/* 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
@@ -201,10 +228,4 @@ hook_system_services(EFI_SYSTEM_TABLE *local_systab)
* and b) we can unwrap when we're done. */
system_exit_boot_services = systab->BootServices->ExitBootServices;
systab->BootServices->ExitBootServices = exit_boot_services;
-
- /* we need to hook Exit() so that we can allow users to quit the
- * bootloader and still e.g. start a new one or run an internal
- * shell. */
- system_exit = systab->BootServices->Exit;
- systab->BootServices->Exit = do_exit;
}
diff --git a/replacements.h b/replacements.h
index bd09424..928144d 100644
--- a/replacements.h
+++ b/replacements.h
@@ -37,6 +37,7 @@ typedef enum {
extern verification_method_t verification_method;
extern int loader_is_participating;
+extern int hook_exit_only;
extern void hook_system_services(EFI_SYSTEM_TABLE *local_systab);
extern void unhook_system_services(void);
diff --git a/shim.c b/shim.c
index d46494a..6fbe427 100644
--- a/shim.c
+++ b/shim.c
@@ -90,6 +90,7 @@ UINT8 *vendor_dbx;
*/
verification_method_t verification_method;
int loader_is_participating;
+int exit_only;
#define EFI_IMAGE_SECURITY_DATABASE_GUID { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f }}
@@ -2100,6 +2101,7 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
/*
* Tell the user that we're in insecure mode if necessary
*/
+ hook_exit_only = 1;
if (user_insecure_mode) {
Print(L"Booting in insecure mode\n");
uefi_call_wrapper(BS->Stall, 1, 2000000);
@@ -2110,11 +2112,12 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
* that anything it boots has performed some
* validation of the next image.
*/
- hook_system_services(systab);
+ hook_exit_only = 0;
loader_is_participating = 0;
}
}
+ hook_system_services(systab);
efi_status = install_shim_protocols();
if (EFI_ERROR(efi_status))
return efi_status;
--
2.1.4