efi-api: fix unaligned access in efi_guid_to_id128()

EFI_GUID requires 4-byte alignment due to its uint32_t Data1 field, but
callers may pass pointers at arbitrary offsets into serialized EFI
variable buffers (e.g. bootctl walking BootXXXX entries). UBSan flagged
the misaligned member access; the old comment claiming the struct was
packed was wrong. Copy the bytes into an aligned local first.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Daan De Meyer
2026-05-22 10:25:50 +02:00
committed by Lennart Poettering
parent b45a897edc
commit 24319a9c2c
+14 -10
View File
@@ -645,21 +645,25 @@ bool efi_has_tpm2(void) {
}
sd_id128_t efi_guid_to_id128(const void *guid) {
const EFI_GUID *uuid = ASSERT_PTR(guid); /* cast is safe, because struct efi_guid is packed */
EFI_GUID uuid;
sd_id128_t id128;
id128.bytes[0] = (uuid->Data1 >> 24) & 0xff;
id128.bytes[1] = (uuid->Data1 >> 16) & 0xff;
id128.bytes[2] = (uuid->Data1 >> 8) & 0xff;
id128.bytes[3] = uuid->Data1 & 0xff;
/* The input pointer is not guaranteed to be aligned (e.g. when pointing into a serialized EFI
* variable buffer), so copy into a properly aligned local first. */
memcpy(&uuid, ASSERT_PTR(guid), sizeof(uuid));
id128.bytes[4] = (uuid->Data2 >> 8) & 0xff;
id128.bytes[5] = uuid->Data2 & 0xff;
id128.bytes[0] = (uuid.Data1 >> 24) & 0xff;
id128.bytes[1] = (uuid.Data1 >> 16) & 0xff;
id128.bytes[2] = (uuid.Data1 >> 8) & 0xff;
id128.bytes[3] = uuid.Data1 & 0xff;
id128.bytes[6] = (uuid->Data3 >> 8) & 0xff;
id128.bytes[7] = uuid->Data3 & 0xff;
id128.bytes[4] = (uuid.Data2 >> 8) & 0xff;
id128.bytes[5] = uuid.Data2 & 0xff;
memcpy(&id128.bytes[8], uuid->Data4, sizeof(uuid->Data4));
id128.bytes[6] = (uuid.Data3 >> 8) & 0xff;
id128.bytes[7] = uuid.Data3 & 0xff;
memcpy(&id128.bytes[8], uuid.Data4, sizeof(uuid.Data4));
return id128;
}