chid_match: match UEFI firmware hwids with the current smbios data by ani-sinha · Pull Request #42570 · systemd/systemd · GitHub
Skip to content

chid_match: match UEFI firmware hwids with the current smbios data#42570

Merged
poettering merged 1 commit into
systemd:mainfrom
ani-sinha:fix-efifw-chid-match
Jun 20, 2026
Merged

chid_match: match UEFI firmware hwids with the current smbios data#42570
poettering merged 1 commit into
systemd:mainfrom
ani-sinha:fix-efifw-chid-match

Conversation

@ani-sinha

Copy link
Copy Markdown
Contributor

UEFI firmware type hwids must be matched against the current hardware. Due to a gap, this was previously not being done.

@github-actions github-actions Bot added sd-boot/sd-stub/bootctl please-review PR is ready for (re-)review by a maintainer labels Jun 12, 2026
@ani-sinha ani-sinha marked this pull request as draft June 12, 2026 06:46
@ani-sinha

Copy link
Copy Markdown
Contributor Author

@ani-sinha ani-sinha marked this pull request as ready for review June 12, 2026 08:47
@ani-sinha ani-sinha force-pushed the fix-efifw-chid-match branch from 3e8f14c to 95a46af Compare June 12, 2026 09:32
@ani-sinha ani-sinha changed the title Match UEFI firmware hwids with the current smbios data chid_match: match UEFI firmware hwids with the current smbios data Jun 12, 2026
@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown

Claude review of PR #42570 (cbf8033)

Must fix

  • Sections no longer located when no CHID matchessrc/boot/pe.c:406-435 — when .hwids is present but neither chid_match succeeds, pe_locate_sections_internal() over the real section list is never called, so .linux/.initrd/.cmdline/etc. are never found and the UKI fails to boot (matches the TEST-70-TPM2 failures reported on the PR). Restore the unconditional final call.
  • OOB read in .hwids NUL-termination checksrc/boot/chid.c:146(size_t*) hwid_buffer + off advances the pointer by off * sizeof(size_t) bytes, not off bytes, so the memchr scans the wrong region (string termination is never actually bounded) and reads out of bounds for any non-zero offset. Use (const uint8_t *) hwid_buffer + off.

Suggestions

  • .efifw matching coupled to .dtbauto presencesrc/boot/pe.c:422 — UEFI-FW matching is only reachable because the whole block is gated by looking_for_dtbauto(); a caller requesting .efifw without .dtbauto would silently never match.
  • Unbounded attacker-controlled offset on UEFI-FW pathsrc/boot/pe.c:422device_get_fwid() dereferences an unvalidated uint32_t offset from the untrusted .hwids section; this pre-existing pattern is newly exercised by the UEFI_FW match. Consider bounds-checking offsets against hwid_length.
  • Offset validation doesn't bound string lengthsrc/boot/chid.c:131-145 — the new >= hwid_length checks bound only where each string starts, not its NUL-termination, so streq8() on fwid/name/compatible can still read past the section end.
  • Redundant/inconsistent section-location passessrc/boot/pe.c:413-429 — the final pass duplicates the inner success passes, and on DT-match + FW-no-match it runs with hwids==NULL but a stale non-NULL device; reset device with hwids and locate sections once. (device is now reset together with hwids; author considers the remaining restructuring resolved.)
  • Make CHID device-type dispatch exhaustivesrc/boot/chid.c:121 — declare the loop locals at narrowest scope and give the if/else if over device_type a terminal else assert_not_reached() so off/name_off definite-assignment doesn't rely implicitly on the IN_SET guard.
  • Validate untrusted descriptor size field (dismissed) — src/boot/chid.c:125 — the descriptor's size bits are read from the untrusted table but never checked against sizeof(Device); the loop hardcodes the stride.
  • Skip NUL-termination check for absent (offset 0) stringssrc/boot/chid.c:147 — offset 0 means "not present", but the unconditional memchr validates an unrelated region for absent fields, inconsistent with device_get_*().

Nits

  • Duplicate offset-validation blockssrc/boot/chid.c:131-145 — the DEVICETREE and UEFI_FW validation blocks are identical; compute the device type once and share the bounds check.
  • Stray indentationsrc/boot/pe.c:354return false; has a 9-column indent; fix to 8 while renaming the function.
  • Inconsistent argument indentationsrc/boot/pe.c:385 — the pe_locate_sections_internal() call indents its arguments to column 19, vs column 24 for the identical final call at line 430.
  • Stray double semicolonsrc/boot/chid.c:124&devices[n_devices];; has a trailing empty statement.
  • Over-long line in section-name predicatesrc/boot/pe.c:352 — the two pe_section_name_equal() checks exceed the ~109-column guideline.
  • Missing space in pointer castsrc/boot/chid.c:147(const uint8_t*) should be (const uint8_t *) per the project's pointer-spacing convention; applies to lines 147 and 149.
  • Collapse IN_SET onto one linesrc/boot/chid.c:130 — with device_type extracted into a local, the condition now fits on a single line.
  • Misleading "no UEFI FW" log for DT-only imagessrc/boot/pe.c:426 — fires on every boot of a devicetree-only image whose .hwids has no firmware entry, where no firmware was ever expected.

Workflow run

Comment thread src/boot/pe.c Outdated
Comment thread src/boot/pe.c Outdated
Comment thread src/boot/pe.c Outdated
@ani-sinha ani-sinha force-pushed the fix-efifw-chid-match branch from 95a46af to 583b869 Compare June 14, 2026 08:19
Comment thread src/boot/chid.c Outdated
Comment thread src/boot/pe.c
Comment thread src/boot/chid.c Outdated
Comment thread src/boot/pe.c Outdated
@ani-sinha ani-sinha force-pushed the fix-efifw-chid-match branch from 583b869 to 2113076 Compare June 14, 2026 13:05
Comment thread src/boot/chid.c Outdated
Comment thread src/boot/pe.c
@ani-sinha ani-sinha force-pushed the fix-efifw-chid-match branch from 2113076 to 7162d3f Compare June 14, 2026 15:18
Comment thread src/boot/chid.c Outdated
Comment thread src/boot/chid.c Outdated
Comment thread src/boot/pe.c Outdated
@ani-sinha ani-sinha force-pushed the fix-efifw-chid-match branch 2 times, most recently from b5630b7 to fd438eb Compare June 15, 2026 03:50
Comment thread src/boot/chid.c Outdated
@ani-sinha ani-sinha force-pushed the fix-efifw-chid-match branch from fd438eb to d04ddfa Compare June 15, 2026 05:49
Comment thread src/boot/chid.c Outdated
/* Count devices and check validity */
for (; (n_devices + 1) * sizeof(*devices) < hwid_length;) {
const Device *device = &devices[n_devices];
uint32_t device_type = DEVICE_TYPE_FROM_DESCRIPTOR(device->descriptor);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude: suggestion: Only the type nibble of the descriptor is validated (via DEVICE_TYPE_FROM_DESCRIPTOR); the size field encoded in the low 28 bits (DEVICE_SIZE_FROM_DESCRIPTOR(device->descriptor)) is read from the untrusted .hwids table but never checked against sizeof(Device). The counting loop instead advances by a fixed sizeof(*devices) stride and reads the union offsets at fixed positions 20/24, so a malformed descriptor declaring a different size is silently parsed as if it were 28 bytes. The format documents the descriptor as encoding the per-entry size (and assert_cc ties DEVICE_DESCRIPTOR_* to sizeof(Device)), so consider rejecting entries where DEVICE_SIZE_FROM_DESCRIPTOR(device->descriptor) != sizeof(Device) rather than ignoring the declared size.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not correct if different device types have different sizes.

Comment thread src/boot/chid.c Outdated
Comment thread src/boot/chid.c Outdated
Comment thread src/boot/pe.c Outdated
@ani-sinha ani-sinha force-pushed the fix-efifw-chid-match branch 3 times, most recently from c0c716a to a754a1f Compare June 16, 2026 08:04
Comment thread src/boot/chid.c Outdated
@poettering

Copy link
Copy Markdown
Member

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.
@ani-sinha ani-sinha force-pushed the fix-efifw-chid-match branch from a754a1f to cbf8033 Compare June 16, 2026 12:52
@poettering poettering merged commit 1f4f348 into systemd:main Jun 20, 2026
62 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants