summaryrefslogtreecommitdiff
path: root/replacements.c
diff options
context:
space:
mode:
Diffstat (limited to 'replacements.c')
-rw-r--r--replacements.c222
1 files changed, 0 insertions, 222 deletions
diff --git a/replacements.c b/replacements.c
deleted file mode 100644
index 469e73aa..00000000
--- a/replacements.c
+++ /dev/null
@@ -1,222 +0,0 @@
-// SPDX-License-Identifier: BSD-2-Clause-Patent
-/*
- * shim - trivial UEFI first-stage bootloader
- *
- * Copyright Red Hat, Inc
- */
-
-/* Chemical agents lend themselves to covert use in sabotage against
- * which it is exceedingly difficult to visualize any really effective
- * defense... I will not dwell upon this use of CBW because, as one
- * pursues the possibilities of such covert uses, one discovers that the
- * scenarios resemble that in which the components of a nuclear weapon
- * are smuggled into New York City and assembled in the basement of the
- * Empire State Building.
- * In other words, once the possibility is recognized to exist, about
- * all that one can do is worry about it.
- * -- Dr. Ivan L Bennett, Jr., testifying before the Subcommittee on
- * National Security Policy and Scientific Developments, November 20,
- * 1969.
- */
-#include "shim.h"
-
-static EFI_SYSTEM_TABLE *systab;
-
-EFI_SYSTEM_TABLE *
-get_active_systab(void)
-{
- if (systab)
- return systab;
- return ST;
-}
-
-static typeof(systab->BootServices->LoadImage) system_load_image;
-static typeof(systab->BootServices->StartImage) system_start_image;
-static typeof(systab->BootServices->Exit) system_exit;
-#if !defined(DISABLE_EBS_PROTECTION)
-static typeof(systab->BootServices->ExitBootServices) system_exit_boot_services;
-#endif /* !defined(DISABLE_EBS_PROTECTION) */
-
-static EFI_HANDLE last_loaded_image;
-
-void
-unhook_system_services(void)
-{
- if (!systab)
- return;
-
- systab->BootServices->LoadImage = system_load_image;
- systab->BootServices->StartImage = system_start_image;
-#if !defined(DISABLE_EBS_PROTECTION)
- systab->BootServices->ExitBootServices = system_exit_boot_services;
-#endif /* !defined(DISABLE_EBS_PROTECTION) */
- BS = systab->BootServices;
-}
-
-static EFI_STATUS EFIAPI
-load_image(BOOLEAN BootPolicy, EFI_HANDLE ParentImageHandle,
- EFI_DEVICE_PATH *DevicePath, VOID *SourceBuffer,
- UINTN SourceSize, EFI_HANDLE *ImageHandle)
-{
- EFI_STATUS efi_status;
-
- unhook_system_services();
- efi_status = BS->LoadImage(BootPolicy, ParentImageHandle, DevicePath,
- SourceBuffer, SourceSize, ImageHandle);
- hook_system_services(systab);
- if (EFI_ERROR(efi_status))
- last_loaded_image = NULL;
- else
- last_loaded_image = *ImageHandle;
- return efi_status;
-}
-
-static EFI_STATUS EFIAPI
-replacement_start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 **exit_data)
-{
- EFI_STATUS efi_status;
- unhook_system_services();
-
- if (image_handle == last_loaded_image) {
- UINT8 retain_protocol = 0;
- UINTN retain_protocol_size = sizeof(retain_protocol);
- UINT32 retain_protocol_attrs = 0;
-
- loader_is_participating = 1;
-
- /* If a boot component asks us, keep our protocol around - it will be used to
- * validate further PE payloads (e.g.: by the UKI stub, before the kernel is booted).
- * But also check that the variable was set by a boot component, to ensure that
- * nobody at runtime can attempt to change shim's behaviour. */
- efi_status = RT->GetVariable(SHIM_RETAIN_PROTOCOL_VAR_NAME,
- &SHIM_LOCK_GUID,
- &retain_protocol_attrs,
- &retain_protocol_size,
- &retain_protocol);
- if (EFI_ERROR(efi_status) ||
- (retain_protocol_attrs & EFI_VARIABLE_NON_VOLATILE) ||
- !(retain_protocol_attrs & EFI_VARIABLE_BOOTSERVICE_ACCESS) ||
- retain_protocol_size != sizeof(retain_protocol) ||
- retain_protocol == 0)
- uninstall_shim_protocols();
- }
- efi_status = BS->StartImage(image_handle, exit_data_size, exit_data);
- if (EFI_ERROR(efi_status)) {
- if (image_handle == last_loaded_image) {
- EFI_STATUS efi_status2 = install_shim_protocols();
-
- if (EFI_ERROR(efi_status2)) {
- console_print(L"Something has gone seriously wrong: %r\n",
- efi_status2);
- console_print(L"shim cannot continue, sorry.\n");
- usleep(5000000);
- RT->ResetSystem(EfiResetShutdown,
- EFI_SECURITY_VIOLATION,
- 0, NULL);
- }
- }
- hook_system_services(systab);
- loader_is_participating = 0;
- }
- return efi_status;
-}
-
-#if !defined(DISABLE_EBS_PROTECTION)
-static EFI_STATUS EFIAPI
-exit_boot_services(EFI_HANDLE image_key, UINTN map_key)
-{
- if (loader_is_participating ||
- verification_method == VERIFIED_BY_HASH) {
- unhook_system_services();
- EFI_STATUS efi_status;
- efi_status = BS->ExitBootServices(image_key, map_key);
- if (EFI_ERROR(efi_status))
- hook_system_services(systab);
- return efi_status;
- }
-
- console_print(L"Bootloader has not verified loaded image.\n");
- console_print(L"System is compromised. halting.\n");
- usleep(5000000);
- RT->ResetSystem(EfiResetShutdown, EFI_SECURITY_VIOLATION, 0, NULL);
- return EFI_SECURITY_VIOLATION;
-}
-#endif /* !defined(DISABLE_EBS_PROTECTION) */
-
-static EFI_STATUS EFIAPI
-do_exit(EFI_HANDLE ImageHandle, EFI_STATUS ExitStatus,
- UINTN ExitDataSize, CHAR16 *ExitData)
-{
- EFI_STATUS efi_status;
-
- shim_fini();
-
- restore_loaded_image();
-
- efi_status = BS->Exit(ImageHandle, ExitStatus,
- ExitDataSize, ExitData);
- if (EFI_ERROR(efi_status)) {
- EFI_STATUS efi_status2 = shim_init();
-
- if (EFI_ERROR(efi_status2)) {
- console_print(L"Something has gone seriously wrong: %r\n",
- efi_status2);
- console_print(L"shim cannot continue, sorry.\n");
- usleep(5000000);
- RT->ResetSystem(EfiResetShutdown,
- EFI_SECURITY_VIOLATION, 0, NULL);
- }
- }
- return efi_status;
-}
-
-void
-hook_system_services(EFI_SYSTEM_TABLE *local_systab)
-{
- systab = local_systab;
- BS = systab->BootServices;
-
- /* 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 replacement_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;
- systab->BootServices->StartImage = replacement_start_image;
-
-#if !defined(DISABLE_EBS_PROTECTION)
- /* we need to hook ExitBootServices() so a) we can enforce the policy
- * and b) we can unwrap when we're done. */
- system_exit_boot_services = systab->BootServices->ExitBootServices;
- systab->BootServices->ExitBootServices = exit_boot_services;
-#endif /* defined(DISABLE_EBS_PROTECTION) */
-}
-
-void
-unhook_exit(void)
-{
- systab->BootServices->Exit = system_exit;
- BS = systab->BootServices;
-}
-
-void
-hook_exit(EFI_SYSTEM_TABLE *local_systab)
-{
- systab = local_systab;
- BS = local_systab->BootServices;
-
- /* 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;
-}