hw/uefi: avoid possibly unaligned variable_auth_2 struct field access
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 <katherine.j.leaver@gmail.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Message-ID: <20260422092910.444997-7-kraxel@redhat.com>
Gerd Hoffmann committed
Apr 22, 2026 at 11:29 UTC
b4680c02b8e838c75691656ee2c4450b454d1ca7
2 files changed
+23
-16
hw/uefi/var-service-auth.c
+12
-9
@@ -180,9 +180,10 @@ static efi_status uefi_vars_check_auth_2_sb(uefi_vars_state *uv,
180
void *data,
181
uint64_t data_offset)
182
{
183
- variable_auth_2 *auth = data;
183
+ variable_auth_2 auth;
184
uefi_variable *siglist;
185
186
+ memcpy(&auth, data, sizeof(auth));
187
if (custom_mode_is_active(uv)) {
188
/* no authentication in custom mode */
189
return EFI_SUCCESS;
@@ -193,7 +194,7 @@ static efi_status uefi_vars_check_auth_2_sb(uefi_vars_state *uv,
194
return EFI_SUCCESS;
195
}
196
196
- if (auth->hdr_length == 24) {
197
+ if (auth.hdr_length == 24) {
198
/* no signature (auth->cert_data is empty) */
199
return EFI_SECURITY_VIOLATION;
200
}
@@ -218,23 +219,25 @@ static efi_status uefi_vars_check_auth_2_sb(uefi_vars_state *uv,
219
efi_status uefi_vars_check_auth_2(uefi_vars_state *uv, uefi_variable *var,
220
mm_variable_access *va, void *data)
221
{
221
- variable_auth_2 *auth = data;
222
+ variable_auth_2 auth;
223
uint64_t data_offset;
224
efi_status status;
225
225
- if (va->data_size < sizeof(*auth)) {
226
+ if (va->data_size < sizeof(auth)) {
227
return EFI_SECURITY_VIOLATION;
228
}
228
- if (uadd64_overflow(sizeof(efi_time), auth->hdr_length, &data_offset)) {
229
+ memcpy(&auth, data, sizeof(auth));
230
+
231
+ if (uadd64_overflow(sizeof(efi_time), auth.hdr_length, &data_offset)) {
232
return EFI_SECURITY_VIOLATION;
233
}
234
if (va->data_size < data_offset) {
235
return EFI_SECURITY_VIOLATION;
236
}
237
235
- if (auth->hdr_revision != 0x0200 ||
236
- auth->hdr_cert_type != WIN_CERT_TYPE_EFI_GUID ||
237
- !qemu_uuid_is_equal(&auth->guid_cert_type, &EfiCertTypePkcs7Guid)) {
238
+ if (auth.hdr_revision != 0x0200 ||
239
+ auth.hdr_cert_type != WIN_CERT_TYPE_EFI_GUID ||
240
+ !qemu_uuid_is_equal(&auth.guid_cert_type, &EfiCertTypePkcs7Guid)) {
241
return EFI_UNSUPPORTED;
242
}
243
@@ -255,7 +258,7 @@ efi_status uefi_vars_check_auth_2(uefi_vars_state *uv, uefi_variable *var,
258
}
259
260
/* checks passed, set variable data */
258
- var->time = auth->timestamp;
261
+ var->time = auth.timestamp;
262
if (va->data_size - data_offset > 0) {
263
var->data = g_malloc(va->data_size - data_offset);
264
memcpy(var->data, data + data_offset, va->data_size - data_offset);
hw/uefi/var-service-pkcs7.c
+11
-7
@@ -21,17 +21,20 @@
21
*/
22
static gnutls_datum_t *build_signed_data(mm_variable_access *va, void *data)
23
{
24
- variable_auth_2 *auth = data;
25
- uint64_t data_offset = sizeof(efi_time) + auth->hdr_length;
24
+ variable_auth_2 auth;
25
+ uint64_t data_offset;
26
uint16_t *name = (void *)va + sizeof(mm_variable_access);
27
gnutls_datum_t *sdata;
28
uint64_t pos = 0;
29
30
+ memcpy(&auth, data, sizeof(auth));
31
+ data_offset = sizeof(efi_time) + auth.hdr_length;
32
+
33
sdata = g_new(gnutls_datum_t, 1);
34
sdata->size = (va->name_size - 2
35
+ sizeof(QemuUUID)
36
+ sizeof(va->attributes)
34
- + sizeof(auth->timestamp)
37
+ + sizeof(auth.timestamp)
38
+ va->data_size - data_offset);
39
sdata->data = g_malloc(sdata->size);
40
@@ -48,8 +51,8 @@ static gnutls_datum_t *build_signed_data(mm_variable_access *va, void *data)
51
pos += sizeof(va->attributes);
52
53
/* TimeStamp */
51
- memcpy(sdata->data + pos, &auth->timestamp, sizeof(auth->timestamp));
52
- pos += sizeof(auth->timestamp);
54
+ memcpy(sdata->data + pos, &auth.timestamp, sizeof(auth.timestamp));
55
+ pos += sizeof(auth.timestamp);
56
57
/* Variable Content */
58
memcpy(sdata->data + pos, data + data_offset, va->data_size - data_offset);
@@ -105,11 +108,12 @@ static void wrap_pkcs7(gnutls_datum_t *pkcs7)
108
109
static gnutls_datum_t *build_pkcs7(void *data)
110
{
108
- variable_auth_2 *auth = data;
111
+ variable_auth_2 auth;
112
gnutls_datum_t *pkcs7;
113
114
+ memcpy(&auth, data, sizeof(auth));
115
pkcs7 = g_new(gnutls_datum_t, 1);
112
- pkcs7->size = auth->hdr_length - 24;
116
+ pkcs7->size = auth.hdr_length - 24;
117
pkcs7->data = g_malloc(pkcs7->size);
118
memcpy(pkcs7->data, data + 16 + 24, pkcs7->size);
119