From cce479bdc03c42b46414ad5e8d625541ba34f7e0403e2a83dadc05c8b6e9ec3d Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Mon, 8 Mar 2021 03:42:43 +0000 Subject: [PATCH] Accepting request 877543 from home:gary_lin:branches:devel:openSUSE:Factory - Add shim-bsc1182776-fix-crash-at-exit.patch to fix the potential crash at Exit() (bsc#1182776) OBS-URL: https://build.opensuse.org/request/show/877543 OBS-URL: https://build.opensuse.org/package/show/devel:openSUSE:Factory/shim?expand=0&rev=171 --- shim-bsc1182776-fix-crash-at-exit.patch | 181 ++++++++++++++++++++++++ shim.changes | 6 + shim.spec | 3 + 3 files changed, 190 insertions(+) create mode 100644 shim-bsc1182776-fix-crash-at-exit.patch diff --git a/shim-bsc1182776-fix-crash-at-exit.patch b/shim-bsc1182776-fix-crash-at-exit.patch new file mode 100644 index 0000000..d4e5c7b --- /dev/null +++ b/shim-bsc1182776-fix-crash-at-exit.patch @@ -0,0 +1,181 @@ +From 74d26654d55a4f32e58b76757efca50ceedefef4 Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Fri, 5 Mar 2021 15:00:29 +0800 +Subject: [PATCH] Restore loaded image of shim at Exit() + +When grub2 invoked Exit() in AArch64 AAVMF, the VM crashed with the +following messsages: + +Unloading driver at 0x000B7D7B000 + +Synchronous Exception at 0x00000000BF5D5E68 +AllocatePool: failed to allocate 800 bytes + +Synchronous Exception at 0x00000000BF5D5E68 + +The similar error also showed when I modified MokManager to call +gBS->Exit() at the end of efi_main(). However, if MokManager just +returned, the error never showed. One significant difference is +whether the loaded image was restored or not, and the firmware seems +to need the original ImageBase pointer to do clean-up. + +To avoid the potential crash, this commit adds restore_loaded_image() so +that we can restore the loaded image both in start_image() and +do_exit(). + +Signed-off-by: Gary Lin +--- + replacements.c | 2 ++ + shim.c | 41 ++++++++++++++++++++++++----------------- + shim.h | 1 + + 3 files changed, 27 insertions(+), 17 deletions(-) + +Index: shim-15+git47/replacements.c +=================================================================== +--- shim-15+git47.orig/replacements.c ++++ shim-15+git47/replacements.c +@@ -159,6 +159,8 @@ do_exit(EFI_HANDLE ImageHandle, EFI_STAT + + shim_fini(); + ++ restore_loaded_image(); ++ + efi_status = gBS->Exit(ImageHandle, ExitStatus, + ExitDataSize, ExitData); + if (EFI_ERROR(efi_status)) { +Index: shim-15+git47/shim.c +=================================================================== +--- shim-15+git47.orig/shim.c ++++ shim-15+git47/shim.c +@@ -58,6 +58,8 @@ + + static EFI_SYSTEM_TABLE *systab; + static EFI_HANDLE global_image_handle; ++static EFI_LOADED_IMAGE *shim_li; ++static EFI_LOADED_IMAGE shim_li_bak; + + static CHAR16 *second_stage; + static void *load_options; +@@ -1861,13 +1863,24 @@ static EFI_STATUS shim_read_header(void + return efi_status; + } + ++VOID ++restore_loaded_image(VOID) ++{ ++ if (shim_li->FilePath) ++ FreePool(shim_li->FilePath); ++ ++ /* ++ * Restore our original loaded image values ++ */ ++ CopyMem(shim_li, &shim_li_bak, sizeof(shim_li_bak)); ++} ++ + /* + * Load and run an EFI executable + */ + EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) + { + EFI_STATUS efi_status; +- EFI_LOADED_IMAGE *li, li_bak; + EFI_IMAGE_ENTRY_POINT entry_point; + EFI_PHYSICAL_ADDRESS alloc_address; + UINTN alloc_pages; +@@ -1882,7 +1895,7 @@ EFI_STATUS start_image(EFI_HANDLE image_ + * binary in order to find our path + */ + efi_status = gBS->HandleProtocol(image_handle, &EFI_LOADED_IMAGE_GUID, +- (void **)&li); ++ (void **)&shim_li); + if (EFI_ERROR(efi_status)) { + perror(L"Unable to init protocol\n"); + return efi_status; +@@ -1891,14 +1904,14 @@ EFI_STATUS start_image(EFI_HANDLE image_ + /* + * Build a new path from the existing one plus the executable name + */ +- efi_status = generate_path_from_image_path(li, ImagePath, &PathName); ++ efi_status = generate_path_from_image_path(shim_li, ImagePath, &PathName); + if (EFI_ERROR(efi_status)) { + perror(L"Unable to generate path %s: %r\n", ImagePath, + efi_status); + goto done; + } + +- if (findNetboot(li->DeviceHandle)) { ++ if (findNetboot(shim_li->DeviceHandle)) { + efi_status = parseNetbootinfo(image_handle); + if (EFI_ERROR(efi_status)) { + perror(L"Netboot parsing failed: %r\n", efi_status); +@@ -1914,7 +1927,7 @@ EFI_STATUS start_image(EFI_HANDLE image_ + data = sourcebuffer; + datasize = sourcesize; + #if defined(ENABLE_HTTPBOOT) +- } else if (find_httpboot(li->DeviceHandle)) { ++ } else if (find_httpboot(shim_li->DeviceHandle)) { + efi_status = httpboot_fetch_buffer (image_handle, + &sourcebuffer, + &sourcesize); +@@ -1930,7 +1943,7 @@ EFI_STATUS start_image(EFI_HANDLE image_ + /* + * Read the new executable off disk + */ +- efi_status = load_image(li, &data, &datasize, PathName); ++ efi_status = load_image(shim_li, &data, &datasize, PathName); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to load image %s: %r\n", + PathName, efi_status); +@@ -1949,13 +1962,13 @@ EFI_STATUS start_image(EFI_HANDLE image_ + * We need to modify the loaded image protocol entry before running + * the new binary, so back it up + */ +- CopyMem(&li_bak, li, sizeof(li_bak)); ++ CopyMem(&shim_li_bak, shim_li, sizeof(shim_li_bak)); + + /* + * Update the loaded image with the second stage loader file path + */ +- li->FilePath = FileDevicePath(NULL, PathName); +- if (!li->FilePath) { ++ shim_li->FilePath = FileDevicePath(NULL, PathName); ++ if (!shim_li->FilePath) { + perror(L"Unable to update loaded image file path\n"); + efi_status = EFI_OUT_OF_RESOURCES; + goto restore; +@@ -1964,7 +1977,7 @@ EFI_STATUS start_image(EFI_HANDLE image_ + /* + * Verify and, if appropriate, relocate and execute the executable + */ +- efi_status = handle_image(data, datasize, li, &entry_point, ++ efi_status = handle_image(data, datasize, shim_li, &entry_point, + &alloc_address, &alloc_pages); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to load image: %r\n", efi_status); +@@ -1981,13 +1994,7 @@ EFI_STATUS start_image(EFI_HANDLE image_ + efi_status = entry_point(image_handle, systab); + + restore: +- if (li->FilePath) +- FreePool(li->FilePath); +- +- /* +- * Restore our original loaded image values +- */ +- CopyMem(li, &li_bak, sizeof(li_bak)); ++ restore_loaded_image(); + done: + if (PathName) + FreePool(PathName); +Index: shim-15+git47/shim.h +=================================================================== +--- shim-15+git47.orig/shim.h ++++ shim-15+git47/shim.h +@@ -163,6 +163,7 @@ extern EFI_STATUS LogError_(const char * + extern EFI_STATUS VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list args); + extern VOID PrintErrors(VOID); + extern VOID ClearErrors(VOID); ++extern VOID restore_loaded_image(VOID); + extern EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath); + extern EFI_STATUS import_mok_state(EFI_HANDLE image_handle); + diff --git a/shim.changes b/shim.changes index 3ca48eb..c38904f 100644 --- a/shim.changes +++ b/shim.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Mon Mar 8 03:13:13 UTC 2021 - Gary Ching-Pang Lin + +- Add shim-bsc1182776-fix-crash-at-exit.patch to fix the potential + crash at Exit() (bsc#1182776) + ------------------------------------------------------------------- Fri Jan 22 03:29:56 UTC 2021 - Gary Ching-Pang Lin diff --git a/shim.spec b/shim.spec index fa59131..480441a 100644 --- a/shim.spec +++ b/shim.spec @@ -100,6 +100,8 @@ Patch15: shim-bsc1177315-verify-eku-codesign.patch Patch16: shim-bsc1177789-fix-null-pointer-deref-AuthenticodeVerify.patch # PATCH-FIX-SUSE shim-bsc1177315-fix-buffer-use-after-free.patch bsc#1177315 glin@suse.com -- Fix buffer use-after-free at the end of the EKU verification Patch17: shim-bsc1177315-fix-buffer-use-after-free.patch +# PATCH-FIX-UPSTREAM shim-bsc1182776-fix-crash-at-exit.patch bsc#1182776 glin@suse.com -- Fix the potential crash at Exit() +Patch18: shim-bsc1182776-fix-crash-at-exit.patch # PATCH-FIX-OPENSUSE shim-opensuse-cert-prompt.patch glin@suse.com -- Show the prompt to ask whether the user trusts openSUSE certificate or not Patch100: shim-opensuse-cert-prompt.patch BuildRequires: gnu-efi >= 3.0.3 @@ -163,6 +165,7 @@ The source code of UEFI shim loader %patch15 -p1 %patch16 -p1 %patch17 -p1 +%patch18 -p1 %endif %if 0%{?is_opensuse} == 1 %patch100 -p1