summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Boccassi <bluca@debian.org>2023-04-22 19:53:28 +0100
committerPeter Jones <pjones@redhat.com>2023-05-02 13:53:08 -0400
commit1f38cb30a5e1dcea97b8d48915515b866ec13c32 (patch)
tree05bacde73a56c6fc18cfee8cf521e79d3c308b8a
parentf23883ccf78f1f605a272f9e5700f47e5494a71d (diff)
downloadefi-boot-shim-1f38cb30a5e1dcea97b8d48915515b866ec13c32.tar.gz
efi-boot-shim-1f38cb30a5e1dcea97b8d48915515b866ec13c32.zip
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: https://github.com/systemd/systemd/pull/27358 Signed-off-by: Luca Boccassi <bluca@debian.org>
-rw-r--r--MokVars.txt5
-rw-r--r--replacements.c21
-rw-r--r--shim.c6
-rw-r--r--shim.h2
4 files changed, 33 insertions, 1 deletions
diff --git a/MokVars.txt b/MokVars.txt
index cdfec2c8..baf8db9a 100644
--- a/MokVars.txt
+++ b/MokVars.txt
@@ -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
diff --git a/replacements.c b/replacements.c
index bf781a8b..6066f9d6 100644
--- a/replacements.c
+++ b/replacements.c
@@ -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)) {
diff --git a/shim.c b/shim.c
index 27a8c112..e54f6345 100644
--- a/shim.c
+++ b/shim.c
@@ -1791,6 +1791,12 @@ die:
#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;
diff --git a/shim.h b/shim.h
index 14824c67..3e221b50 100644
--- a/shim.h
+++ b/shim.h
@@ -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_ */