Skip to content

Commit

Permalink
Optionally allow to keep shim protocol installed
Browse files Browse the repository at this point in the history
If the ShimRetainProtocol variable is set, avoid uninstalling our
protocol.
For example, this allows sd-stub in a UKI to use the shim protocol to
validate PE binaries, even if it is executed by a second stage, before
the kernel is loaded.
Ensure that the variable is volatile and for BootServices access.
Also delete it on startup, so that we can be sure it was really set by
a second stage.

Example use case in sd-boot/sd-stub:

systemd/systemd#27358

Signed-off-by: Luca Boccassi <bluca@debian.org>
  • Loading branch information
bluca authored and vathpela committed May 2, 2023
1 parent f23883c commit 1f38cb3
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 1 deletion.
5 changes: 5 additions & 0 deletions MokVars.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ The hash will be regenerated by MokManager after the user is requested
to enter their password to confirm enrolment of the keys. If the hash
matches MokAuth, the user will be prompted to enrol the keys. BS,RT,NV

ShimRetainProtocol: UINT8, read by Shim before uninstalling protocol.
If set to non-zero, Shim will keep the protocol in place. It can be
used by second stages to ensure the protocol is still available for
later stages, and can thus be used to verify additional PE files. BS,RT.

State variables:

MokList: A list of authorized keys and hashes. An EFI_SIGNATURE_LIST
Expand Down
21 changes: 20 additions & 1 deletion replacements.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,27 @@ replacement_start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 *
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;
uninstall_shim_protocols();

/* 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)) {
Expand Down
6 changes: 6 additions & 0 deletions shim.c
Original file line number Diff line number Diff line change
Expand Up @@ -1791,6 +1791,12 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
#endif
}

/*
* This variable is supposed to be set by second stages, so ensure it is
* not set when we are starting up.
*/
(void) del_variable(SHIM_RETAIN_PROTOCOL_VAR_NAME, SHIM_LOCK_GUID);

efi_status = shim_init();
if (EFI_ERROR(efi_status)) {
msg = SHIM_INIT;
Expand Down
2 changes: 2 additions & 0 deletions shim.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ verify_buffer (char *data, int datasize,
#define DEBUG_VAR_NAME L"SHIM_DEBUG"
#endif

#define SHIM_RETAIN_PROTOCOL_VAR_NAME L"ShimRetainProtocol"

char *translate_slashes(char *out, const char *str);

#endif /* SHIM_H_ */

0 comments on commit 1f38cb3

Please sign in to comment.