|
|
2aacef |
From 8d0b70887a09b9d4a8b669620579d3b6780f0755 Mon Sep 17 00:00:00 2001
|
|
|
2aacef |
From: Jan Janssen <medhefgo@web.de>
|
|
|
2aacef |
Date: Tue, 15 Nov 2022 18:53:02 +0100
|
|
|
2aacef |
Subject: [PATCH] boot: Replace firmware security hooks directly
|
|
|
2aacef |
|
|
|
2aacef |
For some firmware, replacing their own security arch instance with our
|
|
|
2aacef |
override using ReinstallProtocolInterface() is not enough as they will
|
|
|
2aacef |
not use it. This commit goes back to how this was done before by
|
|
|
2aacef |
directly modifying the security protocols.
|
|
|
2aacef |
|
|
|
2aacef |
Fixes: #25336
|
|
|
2aacef |
(cherry picked from commit 967a868563996e928f1fade5bcafc82a7219742b)
|
|
|
2aacef |
|
|
|
2aacef |
Related: #2138081
|
|
|
2aacef |
---
|
|
|
2aacef |
src/boot/efi/secure-boot.c | 119 +++++++++++++------------------------
|
|
|
2aacef |
1 file changed, 40 insertions(+), 79 deletions(-)
|
|
|
2aacef |
|
|
|
2aacef |
diff --git a/src/boot/efi/secure-boot.c b/src/boot/efi/secure-boot.c
|
|
|
2aacef |
index 0e615c55e0..65457bf423 100644
|
|
|
2aacef |
--- a/src/boot/efi/secure-boot.c
|
|
|
2aacef |
+++ b/src/boot/efi/secure-boot.c
|
|
|
2aacef |
@@ -128,15 +128,10 @@ out_deallocate:
|
|
|
2aacef |
}
|
|
|
2aacef |
|
|
|
2aacef |
static struct SecurityOverride {
|
|
|
2aacef |
- /* Our own security arch instances that we register onto original_handle, thereby replacing the
|
|
|
2aacef |
- * firmware provided instances. */
|
|
|
2aacef |
- EFI_SECURITY_ARCH_PROTOCOL override;
|
|
|
2aacef |
- EFI_SECURITY2_ARCH_PROTOCOL override2;
|
|
|
2aacef |
-
|
|
|
2aacef |
- /* These are saved so we can uninstall our own instance later. */
|
|
|
2aacef |
- EFI_HANDLE original_handle, original_handle2;
|
|
|
2aacef |
- EFI_SECURITY_ARCH_PROTOCOL *original_security;
|
|
|
2aacef |
- EFI_SECURITY2_ARCH_PROTOCOL *original_security2;
|
|
|
2aacef |
+ EFI_SECURITY_ARCH_PROTOCOL *security;
|
|
|
2aacef |
+ EFI_SECURITY2_ARCH_PROTOCOL *security2;
|
|
|
2aacef |
+ EFI_SECURITY_FILE_AUTHENTICATION_STATE original_hook;
|
|
|
2aacef |
+ EFI_SECURITY2_FILE_AUTHENTICATION original_hook2;
|
|
|
2aacef |
|
|
|
2aacef |
security_validator_t validator;
|
|
|
2aacef |
const void *validator_ctx;
|
|
|
2aacef |
@@ -148,13 +143,13 @@ static EFIAPI EFI_STATUS security_hook(
|
|
|
2aacef |
const EFI_DEVICE_PATH *file) {
|
|
|
2aacef |
|
|
|
2aacef |
assert(security_override.validator);
|
|
|
2aacef |
- assert(security_override.original_security);
|
|
|
2aacef |
+ assert(security_override.security);
|
|
|
2aacef |
+ assert(security_override.original_hook);
|
|
|
2aacef |
|
|
|
2aacef |
if (security_override.validator(security_override.validator_ctx, file, NULL, 0))
|
|
|
2aacef |
return EFI_SUCCESS;
|
|
|
2aacef |
|
|
|
2aacef |
- return security_override.original_security->FileAuthenticationState(
|
|
|
2aacef |
- security_override.original_security, authentication_status, file);
|
|
|
2aacef |
+ return security_override.original_hook(security_override.security, authentication_status, file);
|
|
|
2aacef |
}
|
|
|
2aacef |
|
|
|
2aacef |
static EFIAPI EFI_STATUS security2_hook(
|
|
|
2aacef |
@@ -165,92 +160,58 @@ static EFIAPI EFI_STATUS security2_hook(
|
|
|
2aacef |
BOOLEAN boot_policy) {
|
|
|
2aacef |
|
|
|
2aacef |
assert(security_override.validator);
|
|
|
2aacef |
- assert(security_override.original_security2);
|
|
|
2aacef |
+ assert(security_override.security2);
|
|
|
2aacef |
+ assert(security_override.original_hook2);
|
|
|
2aacef |
|
|
|
2aacef |
if (security_override.validator(security_override.validator_ctx, device_path, file_buffer, file_size))
|
|
|
2aacef |
return EFI_SUCCESS;
|
|
|
2aacef |
|
|
|
2aacef |
- return security_override.original_security2->FileAuthentication(
|
|
|
2aacef |
- security_override.original_security2, device_path, file_buffer, file_size, boot_policy);
|
|
|
2aacef |
+ return security_override.original_hook2(
|
|
|
2aacef |
+ security_override.security2, device_path, file_buffer, file_size, boot_policy);
|
|
|
2aacef |
}
|
|
|
2aacef |
|
|
|
2aacef |
-static EFI_STATUS install_security_override_one(
|
|
|
2aacef |
- EFI_GUID guid, void *override, EFI_HANDLE *ret_original_handle, void **ret_original_security) {
|
|
|
2aacef |
+/* This replaces the platform provided security arch protocols hooks (defined in the UEFI Platform
|
|
|
2aacef |
+ * Initialization Specification) with our own that uses the given validator to decide if a image is to be
|
|
|
2aacef |
+ * trusted. If not running in secure boot or the protocols are not available nothing happens. The override
|
|
|
2aacef |
+ * must be removed with uninstall_security_override() after LoadImage() has been called.
|
|
|
2aacef |
+ *
|
|
|
2aacef |
+ * This is a hack as we do not own the security protocol instances and modifying them is not an official part
|
|
|
2aacef |
+ * of their spec. But there is little else we can do to circumvent secure boot short of implementing our own
|
|
|
2aacef |
+ * PE loader. We could replace the firmware instances with our own instance using
|
|
|
2aacef |
+ * ReinstallProtocolInterface(), but some firmware will still use the old ones. */
|
|
|
2aacef |
+void install_security_override(security_validator_t validator, const void *validator_ctx) {
|
|
|
2aacef |
EFI_STATUS err;
|
|
|
2aacef |
|
|
|
2aacef |
- assert(override);
|
|
|
2aacef |
- assert(ret_original_handle);
|
|
|
2aacef |
- assert(ret_original_security);
|
|
|
2aacef |
-
|
|
|
2aacef |
- _cleanup_free_ EFI_HANDLE *handles = NULL;
|
|
|
2aacef |
- size_t n_handles = 0;
|
|
|
2aacef |
-
|
|
|
2aacef |
- err = BS->LocateHandleBuffer(ByProtocol, &guid, NULL, &n_handles, &handles);
|
|
|
2aacef |
- if (err != EFI_SUCCESS)
|
|
|
2aacef |
- /* No security arch protocol around? */
|
|
|
2aacef |
- return err;
|
|
|
2aacef |
-
|
|
|
2aacef |
- /* There should only ever be one security arch protocol instance, but let's be paranoid here. */
|
|
|
2aacef |
- assert(n_handles == 1);
|
|
|
2aacef |
-
|
|
|
2aacef |
- void *security = NULL;
|
|
|
2aacef |
- err = BS->LocateProtocol(&guid, NULL, &security);
|
|
|
2aacef |
- if (err != EFI_SUCCESS)
|
|
|
2aacef |
- return log_error_status_stall(err, u"Error getting security arch protocol: %r", err);
|
|
|
2aacef |
-
|
|
|
2aacef |
- err = BS->ReinstallProtocolInterface(handles[0], &guid, security, override);
|
|
|
2aacef |
- if (err != EFI_SUCCESS)
|
|
|
2aacef |
- return log_error_status_stall(err, u"Error overriding security arch protocol: %r", err);
|
|
|
2aacef |
-
|
|
|
2aacef |
- *ret_original_security = security;
|
|
|
2aacef |
- *ret_original_handle = handles[0];
|
|
|
2aacef |
- return EFI_SUCCESS;
|
|
|
2aacef |
-}
|
|
|
2aacef |
-
|
|
|
2aacef |
-/* This replaces the platform provided security arch protocols (defined in the UEFI Platform Initialization
|
|
|
2aacef |
- * Specification) with the provided override instances. If not running in secure boot or the protocols are
|
|
|
2aacef |
- * not available nothing happens. The override instances are provided with the necessary info to undo this
|
|
|
2aacef |
- * in uninstall_security_override(). */
|
|
|
2aacef |
-void install_security_override(security_validator_t validator, const void *validator_ctx) {
|
|
|
2aacef |
assert(validator);
|
|
|
2aacef |
|
|
|
2aacef |
if (!secure_boot_enabled())
|
|
|
2aacef |
return;
|
|
|
2aacef |
|
|
|
2aacef |
security_override = (struct SecurityOverride) {
|
|
|
2aacef |
- { .FileAuthenticationState = security_hook, },
|
|
|
2aacef |
- { .FileAuthentication = security2_hook, },
|
|
|
2aacef |
.validator = validator,
|
|
|
2aacef |
.validator_ctx = validator_ctx,
|
|
|
2aacef |
};
|
|
|
2aacef |
|
|
|
2aacef |
- (void) install_security_override_one(
|
|
|
2aacef |
- (EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID,
|
|
|
2aacef |
- &security_override.override,
|
|
|
2aacef |
- &security_override.original_handle,
|
|
|
2aacef |
- (void **) &security_override.original_security);
|
|
|
2aacef |
- (void) install_security_override_one(
|
|
|
2aacef |
- (EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID,
|
|
|
2aacef |
- &security_override.override2,
|
|
|
2aacef |
- &security_override.original_handle2,
|
|
|
2aacef |
- (void **) &security_override.original_security2);
|
|
|
2aacef |
+ EFI_SECURITY_ARCH_PROTOCOL *security = NULL;
|
|
|
2aacef |
+ err = BS->LocateProtocol(&(EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID, NULL, (void **) &security);
|
|
|
2aacef |
+ if (err == EFI_SUCCESS) {
|
|
|
2aacef |
+ security_override.security = security;
|
|
|
2aacef |
+ security_override.original_hook = security->FileAuthenticationState;
|
|
|
2aacef |
+ security->FileAuthenticationState = security_hook;
|
|
|
2aacef |
+ }
|
|
|
2aacef |
+
|
|
|
2aacef |
+ EFI_SECURITY2_ARCH_PROTOCOL *security2 = NULL;
|
|
|
2aacef |
+ err = BS->LocateProtocol(&(EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID, NULL, (void **) &security2);
|
|
|
2aacef |
+ if (err == EFI_SUCCESS) {
|
|
|
2aacef |
+ security_override.security2 = security2;
|
|
|
2aacef |
+ security_override.original_hook2 = security2->FileAuthentication;
|
|
|
2aacef |
+ security2->FileAuthentication = security2_hook;
|
|
|
2aacef |
+ }
|
|
|
2aacef |
}
|
|
|
2aacef |
|
|
|
2aacef |
void uninstall_security_override(void) {
|
|
|
2aacef |
- /* We use assert_se here to guarantee the system is not in a weird state in the unlikely case of an
|
|
|
2aacef |
- * error restoring the original protocols. */
|
|
|
2aacef |
-
|
|
|
2aacef |
- if (security_override.original_handle)
|
|
|
2aacef |
- assert_se(BS->ReinstallProtocolInterface(
|
|
|
2aacef |
- security_override.original_handle,
|
|
|
2aacef |
- &(EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID,
|
|
|
2aacef |
- &security_override.override,
|
|
|
2aacef |
- security_override.original_security) == EFI_SUCCESS);
|
|
|
2aacef |
-
|
|
|
2aacef |
- if (security_override.original_handle2)
|
|
|
2aacef |
- assert_se(BS->ReinstallProtocolInterface(
|
|
|
2aacef |
- security_override.original_handle2,
|
|
|
2aacef |
- &(EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID,
|
|
|
2aacef |
- &security_override.override2,
|
|
|
2aacef |
- security_override.original_security2) == EFI_SUCCESS);
|
|
|
2aacef |
+ if (security_override.original_hook)
|
|
|
2aacef |
+ security_override.security->FileAuthenticationState = security_override.original_hook;
|
|
|
2aacef |
+ if (security_override.original_hook2)
|
|
|
2aacef |
+ security_override.security2->FileAuthentication = security_override.original_hook2;
|
|
|
2aacef |
}
|