Commit cf90edff authored by Peter Jones's avatar Peter Jones

Allow fallback to use the system's LoadImage/StartImage .

Track use of the system's LoadImage(), and when the next StartImage()
call is for an image the system verified, allow that to count as
participating, since it has been verified by the system's db.
Signed-off-by: default avatarPeter Jones <pjones@redhat.com>
parent a5d135bd
......@@ -60,26 +60,82 @@
static EFI_SYSTEM_TABLE *systab;
static typeof(systab->BootServices->LoadImage) system_load_image;
static typeof(systab->BootServices->StartImage) system_start_image;
static typeof(systab->BootServices->Exit) system_exit;
static typeof(systab->BootServices->ExitBootServices) system_exit_boot_services;
static EFI_HANDLE last_loaded_image;
void
unhook_system_services(void)
{
systab->BootServices->Exit = system_exit;
systab->BootServices->LoadImage = system_load_image;
systab->BootServices->StartImage = system_start_image;
systab->BootServices->ExitBootServices = system_exit_boot_services;
}
static EFI_STATUS EFIAPI
load_image(BOOLEAN BootPolicy, EFI_HANDLE ParentImageHandle,
EFI_DEVICE_PATH *DevicePath, VOID *SourceBuffer,
UINTN SourceSize, EFI_HANDLE *ImageHandle)
{
EFI_STATUS status;
unhook_system_services();
status = systab->BootServices->LoadImage(BootPolicy,
ParentImageHandle, DevicePath,
SourceBuffer, SourceSize, ImageHandle);
hook_system_services(systab);
if (EFI_ERROR(status))
last_loaded_image = NULL;
else
last_loaded_image = *ImageHandle;
return status;
}
static EFI_STATUS EFIAPI
start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 **exit_data)
{
EFI_STATUS status;
unhook_system_services();
/* We have to uninstall shim's protocol here, because if we're
* On the fallback.efi path, then our call pathway is:
*
* shim->fallback->shim->grub
* ^ ^ ^
* | | \- gets protocol #0
* | \- installs its protocol (#1)
* \- installs its protocol (#0)
* and if we haven't removed this, then grub will get the *first*
* shim's protocol, but it'll get the second shim's systab
* replacements. So even though it will participate and verify
* the kernel, the systab never finds out.
*/
if (image_handle == last_loaded_image) {
loader_is_participating = 1;
uninstall_shim_protocols();
}
status = systab->BootServices->StartImage(image_handle, exit_data_size, exit_data);
if (EFI_ERROR(status))
if (EFI_ERROR(status)) {
if (image_handle == last_loaded_image) {
EFI_STATUS status2 = install_shim_protocols();
if (EFI_ERROR(status2)) {
Print(L"Something has gone seriously wrong: %d\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);
loader_is_participating = 0;
}
return status;
}
......@@ -123,6 +179,16 @@ hook_system_services(EFI_SYSTEM_TABLE *local_systab)
/* 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 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;
......
......@@ -41,4 +41,7 @@ extern int loader_is_participating;
extern void hook_system_services(EFI_SYSTEM_TABLE *local_systab);
extern void unhook_system_services(void);
extern EFI_STATUS install_shim_protocols(void);
extern void uninstall_shim_protocols(void);
#endif /* SHIM_REPLACEMENTS_H */
......@@ -1707,11 +1707,56 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle)
return EFI_SUCCESS;
}
EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
static SHIM_LOCK shim_lock_interface;
static EFI_HANDLE shim_lock_handle;
EFI_STATUS
install_shim_protocols(void)
{
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
EFI_STATUS efi_status;
/*
* Install the protocol
*/
efi_status = uefi_call_wrapper(BS->InstallProtocolInterface, 4,
&shim_lock_handle, &shim_lock_guid,
EFI_NATIVE_INTERFACE, &shim_lock_interface);
if (EFI_ERROR(efi_status)) {
console_error(L"Could not install security protocol",
efi_status);
return efi_status;
}
#if defined(OVERRIDE_SECURITY_POLICY)
/*
* Install the security protocol hook
*/
security_policy_install(shim_verify);
#endif
return EFI_SUCCESS;
}
void
uninstall_shim_protocols(void)
{
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
static SHIM_LOCK shim_lock_interface;
EFI_HANDLE handle = NULL;
#if defined(OVERRIDE_SECURITY_POLICY)
/*
* Clean up the security protocol hook
*/
security_policy_uninstall();
#endif
/*
* If we're back here then clean everything up before exiting
*/
uefi_call_wrapper(BS->UninstallProtocolInterface, 3, shim_lock_handle,
&shim_lock_guid, &shim_lock_interface);
}
EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
{
EFI_STATUS efi_status;
verification_method = VERIFIED_BY_NOTHING;
......@@ -1768,24 +1813,9 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
}
}
/*
* Install the protocol
*/
efi_status = uefi_call_wrapper(BS->InstallProtocolInterface, 4,
&handle, &shim_lock_guid, EFI_NATIVE_INTERFACE,
&shim_lock_interface);
if (EFI_ERROR(efi_status)) {
console_error(L"Could not install security protocol",
efi_status);
efi_status = install_shim_protocols();
if (EFI_ERROR(efi_status))
return efi_status;
}
#if defined(OVERRIDE_SECURITY_POLICY)
/*
* Install the security protocol hook
*/
security_policy_install(shim_verify);
#endif
/*
* Enter MokManager if necessary
......@@ -1810,20 +1840,7 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
efi_status = init_grub(image_handle);
#if defined(OVERRIDE_SECURITY_POLICY)
/*
* Clean up the security protocol hook
*/
security_policy_uninstall();
#endif
/*
* If we're back here then clean everything up before exiting
*/
uefi_call_wrapper(BS->UninstallProtocolInterface, 3, handle,
&shim_lock_guid, &shim_lock_interface);
uninstall_shim_protocols();
/*
* Remove our hooks from system services.
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment