]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
efi-api: fix unaligned access in efi_guid_to_id128()
authorDaan De Meyer <daan@amutable.com>
Thu, 21 May 2026 22:00:28 +0000 (22:00 +0000)
committerLennart Poettering <lennart@poettering.net>
Fri, 22 May 2026 08:25:50 +0000 (10:25 +0200)
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>
src/shared/efi-api.c

index c205ffb9002b9fe064ebb2bae2238108964c0b7a..56b055a0c8a94325cd6c5cc9c9cadfee6c7d1989 100644 (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;
 }