Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optionally allow to keep shim protocol installed #565

Merged
merged 1 commit into from
May 2, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Optionally allow to keep shim protocol installed
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>
bluca committed Apr 26, 2023
commit 3ba0034d9ddf72bcc969d6b4a0e3ea3271339875
5 changes: 5 additions & 0 deletions MokVars.txt
Original file line number Diff line number Diff line change
@@ -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
21 changes: 20 additions & 1 deletion replacements.c
Original file line number Diff line number Diff line change
@@ -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)) {
6 changes: 6 additions & 0 deletions shim.c
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 2 additions & 0 deletions shim.h
Original file line number Diff line number Diff line change
@@ -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_ */