@samitouri / QOSamiQemu / commits / b4680c02b8

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