diff options
Diffstat (limited to 'replacements.c')
| -rw-r--r-- | replacements.c | 222 |
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; -} |
