Skip to content

Commit

Permalink
Ensure that apps launched by shim get correct BS->Exit() behavior
Browse files Browse the repository at this point in the history
Right now applications run by shim get our wrapper for Exit(), but it
doesn't do as much cleanup as it should - shim itself also exits, but
currently is not doing all the cleanup it should be doing.

This changes it so all of shim's cleanup is also performed.

Based on a patch and lots of review from Gary Lin.

Signed-off-by: Peter Jones <pjones@redhat.com>
  • Loading branch information
vathpela committed Jun 11, 2015
1 parent a0e8307 commit 7ad9495
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 50 deletions.
37 changes: 30 additions & 7 deletions replacements.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ unhook_system_services(void)
if (!systab)
return;

systab->BootServices->Exit = system_exit;
systab->BootServices->LoadImage = system_load_image;
systab->BootServices->StartImage = system_start_image;
systab->BootServices->ExitBootServices = system_exit_boot_services;
Expand Down Expand Up @@ -163,18 +162,30 @@ exit_boot_services(EFI_HANDLE image_key, UINTN map_key)

static EFI_STATUS EFIAPI
do_exit(EFI_HANDLE ImageHandle, EFI_STATUS ExitStatus,
UINTN ExitDataSize, CHAR16 *ExitData)
UINTN ExitDataSize, CHAR16 *ExitData)
{
EFI_STATUS status;
unhook_system_services();

status = systab->BootServices->Exit(ImageHandle, ExitStatus, ExitDataSize, ExitData);
if (EFI_ERROR(status))
hook_system_services(systab);
shim_fini();

status = systab->BootServices->Exit(ImageHandle, ExitStatus,
ExitDataSize, ExitData);
if (EFI_ERROR(status)) {
EFI_STATUS status2 = shim_init();

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);
}
}
return status;
}


void
hook_system_services(EFI_SYSTEM_TABLE *local_systab)
{
Expand All @@ -201,6 +212,18 @@ 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;
}

void
unhook_exit(void)
{
systab->BootServices->Exit = system_exit;
}

void
hook_exit(EFI_SYSTEM_TABLE *local_systab)
{
systab = local_systab;

/* 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
Expand Down
3 changes: 3 additions & 0 deletions replacements.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ extern int loader_is_participating;
extern void hook_system_services(EFI_SYSTEM_TABLE *local_systab);
extern void unhook_system_services(void);

extern void hook_exit(EFI_SYSTEM_TABLE *local_systab);
extern void unhook_exit(void);

extern EFI_STATUS install_shim_protocols(void);
extern void uninstall_shim_protocols(void);

Expand Down
116 changes: 73 additions & 43 deletions shim.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#define MOK_MANAGER L"\\MokManager.efi"

static EFI_SYSTEM_TABLE *systab;
static EFI_HANDLE image_handle;
static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table);

static CHAR16 *second_stage;
Expand Down Expand Up @@ -1809,7 +1810,6 @@ EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
/*
* Verify that MokSBState is valid, and if appropriate set insecure mode
*/

static EFI_STATUS check_mok_sb (void)
{
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
Expand Down Expand Up @@ -2042,7 +2042,62 @@ uninstall_shim_protocols(void)
&shim_lock_guid, &shim_lock_interface);
}

EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
EFI_STATUS
shim_init(void)
{
EFI_STATUS status = EFI_SUCCESS;
setup_console(1);
setup_verbosity();
dprinta(shim_version);

/* Set the second stage loader */
set_second_stage (image_handle);

if (secure_mode()) {
if (vendor_cert_size || vendor_dbx_size) {
/*
* If shim includes its own certificates then ensure
* that anything it boots has performed some
* validation of the next image.
*/
hook_system_services(systab);
loader_is_participating = 0;
}

hook_exit(systab);

status = install_shim_protocols();
}
return status;
}

void
shim_fini(void)
{
if (secure_mode()) {
/*
* Remove our protocols
*/
uninstall_shim_protocols();

/*
* Remove our hooks from system services.
*/
unhook_system_services();
unhook_exit();
}

/*
* Free the space allocated for the alternative 2nd stage loader
*/
if (load_options_size > 0 && second_stage)
FreePool(second_stage);

setup_console(0);
}

EFI_STATUS efi_main (EFI_HANDLE passed_image_handle,
EFI_SYSTEM_TABLE *passed_systab)
{
EFI_STATUS efi_status;

Expand All @@ -2062,84 +2117,59 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
shim_lock_interface.Context = shim_read_header;

systab = passed_systab;
image_handle = passed_image_handle;

/*
* Ensure that gnu-efi functions are available
*/
InitializeLib(image_handle, systab);

setup_console(1);
setup_verbosity();

dprinta(shim_version);

/* Set the second stage loader */
set_second_stage (image_handle);

/*
* Check whether the user has configured the system to run in
* insecure mode
*/
check_mok_sb();

efi_status = shim_init();
if (EFI_ERROR(efi_status)) {
Print(L"Something has gone seriously wrong: %r\n", efi_status);
Print(L"shim cannot continue, sorry.\n");
systab->BootServices->Stall(5000000);
systab->RuntimeServices->ResetSystem(EfiResetShutdown,
EFI_SECURITY_VIOLATION,
0, NULL);
}

/*
* Tell the user that we're in insecure mode if necessary
*/
if (user_insecure_mode) {
Print(L"Booting in insecure mode\n");
uefi_call_wrapper(BS->Stall, 1, 2000000);
} else if (secure_mode()) {
if (vendor_cert_size || vendor_dbx_size) {
/*
* If shim includes its own certificates then ensure
* that anything it boots has performed some
* validation of the next image.
*/
hook_system_services(systab);
loader_is_participating = 0;
}
}

efi_status = install_shim_protocols();
if (EFI_ERROR(efi_status))
return efi_status;

/*
* Enter MokManager if necessary
*/
efi_status = check_mok_request(image_handle);

/*
* Copy the MOK list to a runtime variable so the kernel can make
* use of it
* Copy the MOK list to a runtime variable so the kernel can
* make use of it
*/
efi_status = mirror_mok_list();

/*
* Create the runtime MokIgnoreDB variable so the kernel can make
* use of it
* Create the runtime MokIgnoreDB variable so the kernel can
* make use of it
*/
efi_status = mok_ignore_db();

/*
* Hand over control to the second stage bootloader
*/

efi_status = init_grub(image_handle);

uninstall_shim_protocols();
/*
* Remove our hooks from system services.
*/
unhook_system_services();

/*
* Free the space allocated for the alternative 2nd stage loader
*/
if (load_options_size > 0)
FreePool(second_stage);

setup_console(0);

shim_fini();
return efi_status;
}
3 changes: 3 additions & 0 deletions shim.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ typedef struct _SHIM_LOCK {
EFI_SHIM_LOCK_HASH Hash;
EFI_SHIM_LOCK_CONTEXT Context;
} SHIM_LOCK;

extern EFI_STATUS shim_init(void);
extern void shim_fini(void);

0 comments on commit 7ad9495

Please sign in to comment.