From: Gerd Hoffmann <[email protected]>
Copy data to stack-allocated struct before accessing it
to make sure it is properly aligned.
Fixes: CVE-2026-41440
Fixes: f1488fac0584 ("hw/uefi: add var-service-auth.c")
Reported-by: Katherine Leaver <[email protected]>
Signed-off-by: Gerd Hoffmann <[email protected]>
Message-ID: <[email protected]>
(cherry picked from commit b4680c02b8e838c75691656ee2c4450b454d1ca7)
Signed-off-by: Michael Tokarev <[email protected]>
diff --git a/hw/uefi/var-service-auth.c b/hw/uefi/var-service-auth.c
index fba5a0956a..795f2f54e4 100644
--- a/hw/uefi/var-service-auth.c
+++ b/hw/uefi/var-service-auth.c
@@ -180,9 +180,10 @@ static efi_status
uefi_vars_check_auth_2_sb(uefi_vars_state *uv,
void *data,
uint64_t data_offset)
{
- variable_auth_2 *auth = data;
+ variable_auth_2 auth;
uefi_variable *siglist;
+ memcpy(&auth, data, sizeof(auth));
if (custom_mode_is_active(uv)) {
/* no authentication in custom mode */
return EFI_SUCCESS;
@@ -193,7 +194,7 @@ static efi_status uefi_vars_check_auth_2_sb(uefi_vars_state
*uv,
return EFI_SUCCESS;
}
- if (auth->hdr_length == 24) {
+ if (auth.hdr_length == 24) {
/* no signature (auth->cert_data is empty) */
return EFI_SECURITY_VIOLATION;
}
@@ -218,23 +219,25 @@ static efi_status
uefi_vars_check_auth_2_sb(uefi_vars_state *uv,
efi_status uefi_vars_check_auth_2(uefi_vars_state *uv, uefi_variable *var,
mm_variable_access *va, void *data)
{
- variable_auth_2 *auth = data;
+ variable_auth_2 auth;
uint64_t data_offset;
efi_status status;
- if (va->data_size < sizeof(*auth)) {
+ if (va->data_size < sizeof(auth)) {
return EFI_SECURITY_VIOLATION;
}
- if (uadd64_overflow(sizeof(efi_time), auth->hdr_length, &data_offset)) {
+ memcpy(&auth, data, sizeof(auth));
+
+ if (uadd64_overflow(sizeof(efi_time), auth.hdr_length, &data_offset)) {
return EFI_SECURITY_VIOLATION;
}
if (va->data_size < data_offset) {
return EFI_SECURITY_VIOLATION;
}
- if (auth->hdr_revision != 0x0200 ||
- auth->hdr_cert_type != WIN_CERT_TYPE_EFI_GUID ||
- !qemu_uuid_is_equal(&auth->guid_cert_type, &EfiCertTypePkcs7Guid)) {
+ if (auth.hdr_revision != 0x0200 ||
+ auth.hdr_cert_type != WIN_CERT_TYPE_EFI_GUID ||
+ !qemu_uuid_is_equal(&auth.guid_cert_type, &EfiCertTypePkcs7Guid)) {
return EFI_UNSUPPORTED;
}
@@ -255,7 +258,7 @@ efi_status uefi_vars_check_auth_2(uefi_vars_state *uv,
uefi_variable *var,
}
/* checks passed, set variable data */
- var->time = auth->timestamp;
+ var->time = auth.timestamp;
if (va->data_size - data_offset > 0) {
var->data = g_malloc(va->data_size - data_offset);
memcpy(var->data, data + data_offset, va->data_size - data_offset);
diff --git a/hw/uefi/var-service-pkcs7.c b/hw/uefi/var-service-pkcs7.c
index f17ad6872f..c859743e86 100644
--- a/hw/uefi/var-service-pkcs7.c
+++ b/hw/uefi/var-service-pkcs7.c
@@ -21,17 +21,20 @@
*/
static gnutls_datum_t *build_signed_data(mm_variable_access *va, void *data)
{
- variable_auth_2 *auth = data;
- uint64_t data_offset = sizeof(efi_time) + auth->hdr_length;
+ variable_auth_2 auth;
+ uint64_t data_offset;
uint16_t *name = (void *)va + sizeof(mm_variable_access);
gnutls_datum_t *sdata;
uint64_t pos = 0;
+ memcpy(&auth, data, sizeof(auth));
+ data_offset = sizeof(efi_time) + auth.hdr_length;
+
sdata = g_new(gnutls_datum_t, 1);
sdata->size = (va->name_size - 2
+ sizeof(QemuUUID)
+ sizeof(va->attributes)
- + sizeof(auth->timestamp)
+ + sizeof(auth.timestamp)
+ va->data_size - data_offset);
sdata->data = g_malloc(sdata->size);
@@ -48,8 +51,8 @@ static gnutls_datum_t *build_signed_data(mm_variable_access
*va, void *data)
pos += sizeof(va->attributes);
/* TimeStamp */
- memcpy(sdata->data + pos, &auth->timestamp, sizeof(auth->timestamp));
- pos += sizeof(auth->timestamp);
+ memcpy(sdata->data + pos, &auth.timestamp, sizeof(auth.timestamp));
+ pos += sizeof(auth.timestamp);
/* Variable Content */
memcpy(sdata->data + pos, data + data_offset, va->data_size - data_offset);
@@ -105,11 +108,12 @@ static void wrap_pkcs7(gnutls_datum_t *pkcs7)
static gnutls_datum_t *build_pkcs7(void *data)
{
- variable_auth_2 *auth = data;
+ variable_auth_2 auth;
gnutls_datum_t *pkcs7;
+ memcpy(&auth, data, sizeof(auth));
pkcs7 = g_new(gnutls_datum_t, 1);
- pkcs7->size = auth->hdr_length - 24;
+ pkcs7->size = auth.hdr_length - 24;
pkcs7->data = g_malloc(pkcs7->size);
memcpy(pkcs7->data, data + 16 + 24, pkcs7->size);
--
2.47.3