β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-5618

ig4 ACPI glue hardcodes sc->version = IG4_ATOM for every matched HID under the false comment 'All the HIDs matched are Atom SOCs' β€” Haswell-LP (INT33C2/33C3), Broadwell (INT3432/33) and Apollo Lake (808622C1) silicon is mis-programmed: HSW-only SWMODE/LTR init and the SKL+-class LTR path in ig4_iic.c are skipped

Summary

The glue stores a constant instead of deriving the version from the matched HID (ig4_pci.c's own table classifies the same silicon differently): HSW-only SWMODE write skipped on ACPI-enumerated Haswell, SW/AUTO LTR handling skipped, and Apollo Lake lands outside the >=SKYLAKE branch skipping ACTIVE/IDLE LTR. All ATOM-path accesses remain valid on the mislabeled silicon - functional mis-programming, no memory safety. Reproduced live on the planted-ACPI rig: _HID INT33C2 device prints 'version 1' (ATOM) where ig4_pci says HASWELL. Map-HID-to-version fix proposed (unvalidated, Info).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-5618 Β· 4 files
FileTypeDescriptionSize
README.md file 485 B ↓ raw
VERDICT.md file 3.6 KB ↓ raw
febf_version_print.log file 13.3 KB view raw
verdict.json file 3.5 KB view raw
README.md file
↓ download raw

DF-5618 β€” hardcoded IG4_ATOM for non-Atom HIDs

See VERDICT.md. Evidence: febf_version_print.log (real boot, planted INT33C2 device: "ig4iic0: version 1" = IG4_ATOM). Reproduce with the DF-5617 planted-ACPI rig (../DF-5617/) using a device whose _CRS window is any allocatable MMIO (e.g. 0xFEBF0000+0x200): the attach prints stop at the compat gate ("Compat version too low") after the "version 1" line β€” the mis-programming is visible on the console without any harness code.

VERDICT.md file
↓ download raw

DF-5618 β€” ig4 ACPI glue hardcodes IG4_ATOM for Haswell/Broadwell/Apollo Lake HIDs

What

ig4iic_acpi_attach():

107:    /* All the HIDs matched are Atom SOCs. */
108:    sc->version = IG4_ATOM;

sets the controller version to IG4_ATOM (1) for every HID in ig4iic_ids[] (ig4_acpi.c:70-81). The comment is false for half the list, and ig4_pci.c's own device table (ig4_pci.c:103-138) classifies the same silicon differently:

HID Silicon ig4_pci.c classification
INT33C2/C3 Haswell-LP LPSS I2C (9c61/9c62) IG4_HASWELL
INT3432/33 Broadwell/Wildcat Point-LP IG4_HASWELL class
80860F41 Braswell IG4_ATOM (correct)
808622C1 Apollo Lake (5aac..5aba) IG4_APL
AMDI0010/50 AMD DesignWare n/a (closest ATOM)
APMC0D0F Ampere n/a (closest ATOM)

Consequences of the wrong value (all version-gated code in ig4_iic.c):

  • ig4_iic.c:513-519 β€” the HSW-only IG4_GENERAL_SWMODE write is skipped on ACPI-enumerated Haswell LPSS (the write that ig4_pci.c performs for the same silicon when PCI-enumerated β€” see DF-5600's inverse direction).
  • ig4_iic.c:522-526 β€” Haswell SW_LTR/AUTO_LTR handling skipped (log-only).
  • ig4_iic.c:527-532 β€” Apollo Lake falls out of the >= IG4_SKYLAKE branch: ACTIVE_LTR/IDLE_LTR handling skipped.
  • ig4_iic.c:620-626 (#if 0) and the debug dump (:1033-1051) mislabel.

No memory-safety impact: every version-gated access in the ATOM path is also valid on the mislabeled silicon (the ATOM path reads only registers that exist on Haswell-class LPSS). This is the pass-2 checklist (a) twin-check answer: the ACPI glue has no bzero bug (the sc->version store at ig4_acpi.c:108 happens after softc allocation, which newbus zeroes β€” subr_bus.c:1953-1954 kmalloc(..., M_INTWAIT | M_ZERO)), but the value itself is wrong for Haswell/Broadwell/Apollo Lake.

Live manifestation

febf_version_print.log β€” planted ig4 ACPI device (HID INT33C2, Haswell-LP silicon per ig4_pci.c:104) via the DF-5617 planted-ACPI rig:

ig4iic0: <Designware I2C Controller> iomem 0xfebf0000-0xfebf01ff irq 0 on acpi0
ig4iic0: version 1 type 00000000 params 00000000 general 00000000 comp_version 00000000

version 1 = IG4_ATOM for Haswell-HID hardware, exactly as the source predicts.

Suggested fix (unvalidated β€” Info-severity hardening)

Map the HID to the version like ig4_pci.c does, e.g.:

static const struct { const char *hid; enum ig4_vers ver; } ig4iic_acpi_vers[] = {
    { "INT33C2", IG4_HASWELL }, { "INT33C3", IG4_HASWELL },
    { "INT3432", IG4_HASWELL }, { "INT3433", IG4_HASWELL },
    { "80860F41", IG4_ATOM },   { "808622C1", IG4_APL },
    { "AMDI0510", IG4_ATOM },   { "AMDI0010", IG4_ATOM },
    { "APMC0D0F", IG4_ATOM },
};

and select in ig4iic_acpi_probe() (storing into the softc, which the ACPI glue β€” unlike ig4_pci.c β€” does not bzero afterwards), or read the DW COMP_TYPE/COMP_PARAM1 IP identity as Linux's designware driver does.

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

(No fix.diff for this item: documented recommendation only - see Fix above.)

Fix verification

not_testable
baseline reproduced→ patch + rebuild →patched clean

not_testable

Info-severity functional finding; no kernel build performed for the suggested HID->version mapping (no behavioral failure to A/B - the mis-programming is cosmetic at runtime on QEMU, where no real Haswell/APL silicon exists).
per-fix-DF-5618

Confirmed kernel references

Detail

Evidence (decisive lines)

febf_version_print.log lines: 'ig4iic0: <Designware I2C Controller> iomem 0xfebf0000-0xfebf01ff irq 0 on acpi0' followed by 'ig4iic0: version 1 type 00000000 params 00000000 general 00000000 comp_version 00000000' - INT33C2 (Haswell per ig4_pci.c:104) programmed as version 1 (IG4_ATOM, ig4_var.h:51).

PoC changes

Evidence captured with the DF-5617 planted-ACPI rig (QEMU -acpitable SSDT declaring a Device with _HID INT33C2 and _CRS Memory32Fixed 0xFEBF0000+0x200/IRQ0, kldload ig4); the version print is production ig4_iic.c:499 output.

Verified recommended fix

Select sc->version per matched HID (INT33C2/C3/INT3432/33 -> IG4_HASWELL, 808622C1 -> IG4_APL, 80860F41/AMDI*/APMC0D0F -> IG4_ATOM), mirroring ig4_pci.c:103-138; store it in ig4iic_acpi_probe() like ig4_pci.c does.

Verdict

ig4_acpi.c:107-108 hardcodes sc->version = IG4_ATOM for every HID in ig4iic_ids[] under the false comment 'All the HIDs matched are Atom SOCs'. INT33C2/INT33C3 are Haswell-LP LPSS and INT3432/3433 Broadwell (IG4_HASWELL per ig4_pci.c's own table for the same silicon), and 808622C1 is Apollo Lake (IG4_APL per ig4_pci.c:120-127). The mis-version skips version-gated handling in ig4_iic.c: the HSW-only IG4_GENERAL_SWMODE write (:513-519) on ACPI Haswell, HSW LTR (:522-526), and puts Apollo Lake outside the >=IG4_SKYLAKE branch (:527-532). Pass-2 checklist (a) twin-check: the ACPI glue has NO bzero-wipes-version bug (no bzero in this file; newbus allocates the softc zeroed, subr_bus.c:1953-1954) - the stored value is simply wrong for half the HIDs. Reproduced live: the DF-5617 planted-ACPI rig presented an INT33C2 (Haswell-HID) device and the guest kernel printed 'ig4iic0: version 1' (=IG4_ATOM) for it (febf_version_print.log), exactly as the source predicts. Functional mis-programming only - every ATOM-path register access is also valid on the mislabeled silicon - so Info severity.