]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
chid_match: match UEFI firmware hwid entry with the current smbios data
authorAni Sinha <anisinha@redhat.com>
Fri, 12 Jun 2026 06:40:47 +0000 (12:10 +0530)
committerLennart Poettering <lennart@poettering.net>
Sat, 20 Jun 2026 13:14:40 +0000 (15:14 +0200)
UEFI firmware type hwids must be matched against the current hardware first.
This change implements that. Additionally, some extra validations on the hwids
entries have also been added.

src/boot/chid.c
src/boot/pe.c
src/boot/stub.c

index 6cb11e8b1c1b20c7506970711594e45b96d3fad6..23bd60537fa2d7299406f7f8c277398c7188672e 100644 (file)
@@ -121,12 +121,35 @@ EFI_STATUS chid_match(const void *hwid_buffer, size_t hwid_length, uint32_t matc
 
         /* Count devices and check validity */
         for (; (n_devices + 1) * sizeof(*devices) < hwid_length;) {
+                const Device *device = &devices[n_devices];
 
-                if (devices[n_devices].descriptor == DEVICE_DESCRIPTOR_EOL)
+                if (device->descriptor == DEVICE_DESCRIPTOR_EOL)
                         break;
-                if (!IN_SET(DEVICE_TYPE_FROM_DESCRIPTOR(devices[n_devices].descriptor),
-                            DEVICE_TYPE_UEFI_FW, DEVICE_TYPE_DEVICETREE))
+
+                uint32_t device_type = DEVICE_TYPE_FROM_DESCRIPTOR(device->descriptor);
+                size_t name_off, off;
+
+                if (!IN_SET(device_type, DEVICE_TYPE_UEFI_FW, DEVICE_TYPE_DEVICETREE))
                         return EFI_UNSUPPORTED;
+
+                if (device_type == DEVICE_TYPE_DEVICETREE) {
+                        off = device->devicetree.compatible_offset;
+                        name_off = device->devicetree.name_offset;
+                } else if (device_type == DEVICE_TYPE_UEFI_FW) {
+                        off = device->uefi_fw.fwid_offset;
+                        name_off = device->uefi_fw.name_offset;
+                } else
+                        assert_not_reached();
+
+                if (off >= hwid_length || name_off >= hwid_length)
+                        return EFI_INVALID_PARAMETER;
+
+                /* check for NULL termination */
+                if (off && !memchr((const uint8_t *) hwid_buffer + off, 0, hwid_length - off))
+                        return EFI_INVALID_PARAMETER;
+                if (name_off && !memchr((const uint8_t *) hwid_buffer + name_off, 0, hwid_length - name_off))
+                        return EFI_INVALID_PARAMETER;
+
                 n_devices++;
         }
 
index e96600ab05d55a05f6b55a79fb9e91979b1685bc..872cb9e6220e43bf25254b44fca6f3ddd157fa07 100644 (file)
@@ -345,13 +345,14 @@ static void pe_locate_sections_internal(
                 }
 }
 
-static bool looking_for_dtbauto(const char *const section_names[]) {
+static bool looking_for_dtbauto_or_efifw(const char *const section_names[]) {
         assert(section_names);
 
         for (size_t i = 0; section_names[i]; i++)
-                if (pe_section_name_equal(section_names[i], ".dtbauto"))
+                if (pe_section_name_equal(section_names[i], ".dtbauto") ||
+                    pe_section_name_equal(section_names[i], ".efifw"))
                         return true;
-         return false;
+        return false;
 }
 
 static void pe_locate_sections(
@@ -361,7 +362,7 @@ static void pe_locate_sections(
                 size_t validate_base,
                 PeSectionVector sections[]) {
 
-        if (!looking_for_dtbauto(section_names))
+        if (!looking_for_dtbauto_or_efifw(section_names))
                 return pe_locate_sections_internal(
                                   section_table,
                                   n_section_table,
@@ -377,40 +378,64 @@ static void pe_locate_sections(
         const void *hwids = NULL;
         const Device *device = NULL;
 
-        if (!firmware_devicetree_exists()) {
-                /* Find HWIDs table and search for the current device */
-                static const char *const hwid_section_names[] = { ".hwids", NULL };
-                PeSectionVector hwids_section[1] = {};
-
-                pe_locate_sections_internal(
-                                section_table,
-                                n_section_table,
-                                hwid_section_names,
-                                validate_base,
-                                /* device_table= */ NULL,
-                                /* device= */ NULL,
-                                hwids_section);
-
-                if (PE_SECTION_VECTOR_IS_SET(hwids_section)) {
-                        hwids = (const uint8_t *) SIZE_TO_PTR(validate_base) + hwids_section[0].memory_offset;
-
-                        EFI_STATUS err = chid_match(hwids, hwids_section[0].memory_size, DEVICE_TYPE_DEVICETREE, &device);
-                        if (err != EFI_SUCCESS) {
+        /* Find HWIDs table and search for the current device */
+        static const char *const hwid_section_names[] = { ".hwids", NULL };
+        PeSectionVector hwids_section[1] = {};
+
+        pe_locate_sections_internal(
+                   section_table,
+                   n_section_table,
+                   hwid_section_names,
+                   validate_base,
+                   /* device_table= */ NULL,
+                   /* device= */ NULL,
+                   hwids_section);
+
+        if (PE_SECTION_VECTOR_IS_SET(hwids_section)) {
+                hwids = (const uint8_t *) SIZE_TO_PTR(validate_base) + hwids_section[0].memory_offset;
+                EFI_STATUS err;
+
+                if (!firmware_devicetree_exists()) {
+                        err = chid_match(hwids, hwids_section[0].memory_size, DEVICE_TYPE_DEVICETREE, &device);
+                        if (err == EFI_SUCCESS)
+                                pe_locate_sections_internal(
+                                                section_table,
+                                                n_section_table,
+                                                section_names,
+                                                validate_base,
+                                                hwids,
+                                                device,
+                                                sections);
+                        else
                                 log_full(err, err == EFI_NOT_FOUND ? LOG_DEBUG : LOG_ERR,
                                          "HWID matching failed, no DT blob will be selected: %m");
-                                hwids = NULL;
-                        }
                 }
-        }
 
+                err = chid_match(hwids, hwids_section[0].memory_size, DEVICE_TYPE_UEFI_FW, &device);
+                if (err == EFI_SUCCESS)
+                        pe_locate_sections_internal(
+                                        section_table,
+                                        n_section_table,
+                                        section_names,
+                                        validate_base,
+                                        hwids,
+                                        device,
+                                        sections);
+                else {
+                        log_full(err, err == EFI_NOT_FOUND ? LOG_DEBUG : LOG_ERR,
+                                 "No UEFI FW will be selected: %m");
+                        hwids = NULL;
+                        device = NULL;
+                }
+        }
         return pe_locate_sections_internal(
-                            section_table,
-                            n_section_table,
-                            section_names,
-                            validate_base,
-                            hwids,
-                            device,
-                            sections);
+                   section_table,
+                   n_section_table,
+                   section_names,
+                   validate_base,
+                   hwids,
+                   device,
+                   sections);
 }
 
 static uint32_t get_compatibility_entry_address(const DosFileHeader *dos, const PeFileHeader *pe) {
index 712a82e739850242612c470d243217557e2e23e9..e69faca00b0bf95f39f8cf7d7ce056a6adcfed19 100644 (file)
@@ -599,7 +599,7 @@ static EFI_STATUS load_addons(
                 err = pe_memory_locate_sections(loaded_addon->ImageBase, unified_sections, sections);
                 if (err != EFI_SUCCESS) {
                         log_error_status(err,
-                                         "Unable to locate embedded .cmdline/.dtb/.dtbauto/.initrd/.ucode sections in %ls, ignoring: %m",
+                                         "Unable to locate embedded .cmdline/.dtb/.dtbauto/.efifw/.initrd/.ucode sections in %ls, ignoring: %m",
                                          items[i]);
                         continue;
                 }