DF-5617 / verdict.json
{ "finding_id": "DF-5617", "status": "reproduced", "reproduced": true, "impact": "panic", "confidence": "certain", "verdict": "ig4_acpi.cs attach-error unwinder re-enters the serializer leaked by ig4_iic.cs bus_setup_intr error path: ig4_acpi.c:127 sets pci_attached=1 before ig4iic_attach (ig4_acpi.c:132); when ig4iic_attach fails at bus_setup_intr it returns with sc->slz held (ig4_iic.c:648-655, no lwkt_serialize_exit on the error branch), and ig4_acpi.c:134 -> ig4_acpi.c:146-147 calls ig4iic_detach whose first lwkt_serialize_enter (ig4_iic.c:678) re-enters the self-held non-recursive serializer -> KKASSERT panic (INVARIANTS) / hard deadlock otherwise. Verified live: the real ig4_acpi.c path (probe/HID INT33C2 match, _CRS translation, MMIO alloc into a planted SSDT-backed register file, ig4iic_attach running to bus_setup_intr) was driven end-to-end with a planted ACPI device; the one non-natural input (bus_setup_intr failure - on real hardware any rman_activate/register_int failure, nexus.c:519-532) was injected with the proven DF-5601 pseudo-bus pattern, after which the production ig4iic_attach/ig4iic_detach panicked the guest exactly as the source predicts: panic: assertion !IS_SERIALIZED failed in lwkt_serialize_enter with backtrace ig4iic_detach <- attach unwinder. fix.diff (one-line lwkt_serialize_exit on ig4_iic.c:651-655 error path, same root fix as DF-5601) A/B validated: patched ig4.ko runs the identical scenario cleanly, guest stays up.", "exploit_chain": "", "evidence": "run.log/panic.txt: DF5617: serializer is HELD ... IS_SERIALIZED: 1 then panic: assertion \"!IS_SERIALIZED((s))\" failed in lwkt_serialize_enter at lwkt_serialize.c:107 with ig4iic_detach() at ig4iic_detach+0x1f backtrace; run-fixed.log: serializer is released ... IS_SERIALIZED: 0 + ig4iic_acpi_detach replay = 0 -- returned cleanly, NO PANIC (fix effective) with guest up; real-path proof: dance logs + run.log ig4iic0 attach lines (probe match, iomem 0xbffe1cdc irq N on acpi0, comp_version 3131352a, [attached!])", "kernel_refs": [ "sys/bus/smbus/ichiic/ig4_acpi.c:127", "sys/bus/smbus/ichiic/ig4_acpi.c:132", "sys/bus/smbus/ichiic/ig4_acpi.c:134", "sys/bus/smbus/ichiic/ig4_acpi.c:146", "sys/bus/smbus/ichiic/ig4_acpi.c:147", "sys/bus/smbus/ichiic/ig4_iic.c:648", "sys/bus/smbus/ichiic/ig4_iic.c:655", "sys/bus/smbus/ichiic/ig4_iic.c:678", "sys/kern/lwkt_serialize.c:107", "sys/sys/serialize.h:41", "sys/platform/pc64/x86_64/nexus.c:519" ], "poc_changes": "The seed sketch was rewritten: (1) planted-ACPI rig with the register file embedded in the SSDTs own AML pad (SMAP-RAM windows are rman-refused; the fw_cfg table area is not); window >= 0x810 because ig4_iic.c:504-508 reads GENERAL at +0x808 (a 0x200 window page-faults); (2) host-side ENABLE_STATUS latch dance (gpa2hva + /proc/qemu/mem, pre-resolved hva) because DWs 0x6C->0x9C latch cannot exist in RAM; (3) no reachable GSI deterministically fails bus_setup_intr on QEMU (acpi_resource.c:599 drops GSIs above the legacy map; IOAPIC auto-router picks handler-free slots), so the failure is injected via the proven DF-5601 pseudo-bus (df56.c) while ig4_acpi.cs prologue (ig4_acpi.c:104-127) and unwinder semantics (ig4_acpi.c:141-169) are replayed line-for-line around the REAL production ig4iic_attach()/ig4iic_detach().", "attempts": 9, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (X86_64_GENERIC, options INVARIANTS config:56)", "runtime_sec": 5400, "guest_dirty": 0, "build_cmd": "findings/poc/DF-5617/build_kld.sh (guest: make in /root/df5617work{,/f2}; fixed ig4.ko: cd /usr/src/sys/bus/smbus/ichiic && patch < fix.diff && SYSDIR=/usr/src/sys make KERNBUILDDIR=/usr/obj/usr/src/sys/X86_64_GENERIC)", "run_cmd": "vm.sh run_root kldload ig4 && kldload /root/df5617work/df56.ko && kldload /root/df5617work/f2/df5617.ko (see run.sh)", "code_hash": "fde6582d49e88a3d19f26b258adc34477c241c7ee12005a29c039b13942b1812", "notes": "ACPI sibling of DF-5601 (ig4_pci.c) sharing the DF-1049 root; file-specific defect is ig4_acpi.c:127/132-134s unwinder ordering. Real-hw trigger: any one-time IRQ-setup failure on an ACPI-enumerated ig4 (exclusive-owner GSI conflict etc.). Boot/kldload-time availability bug, not unprivileged-triggerable -> Low. Supplementary live observation in the pack: ig4_iic.c:504-508s unconditional GENERAL(0x808) read page-faults the kernel when the ACPI _CRS window is smaller than 0x80C (crafted-firmware DoS, generic _CRS-trust class, root cause in ig4_iic.c).", "recommended_fix": "Add lwkt_serialize_exit(&sc->slz) on ig4_iic.cs bus_setup_intr error path (ig4_iic.c:651-655) - one line, fixes both the PCI (DF-5601) and ACPI (DF-5617) unwinders at the root.", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "fixed", "fix_evidence": "Baseline (run.log/panic.txt): panic assertion !IS_SERIALIZED in lwkt_serialize_enter, backtrace ig4iic_detach <- df5617_attach <- device_doattach, guest down in DDB. Patched (run-fixed.log, same kernel config, fix.diff applied to /usr/src ig4_iic.c, ig4.ko rebuilt in guest - fix_build.log): DF5617: serializer is released ... IS_SERIALIZED: 0, ig4iic_acpi_detach replay = 0 -- returned cleanly, NO PANIC (fix effective), vm.sh status = up." } |