# DF-5433 — VERDICT

## 1. Reproduced? YES — deterministic SMP boot wedge (DoS)

run.log (kernel v6.5.0.1712.g89e6a #1 Mon Jun 29 clean-install build):

```
madt_lapic_probe: lapic_count=3 x2apic_count=0     <- probe accepts dups
ACPI CPUS = 3                                       <- naps inflated to 2
Warning: No next valid APICID found. Returning -1   <- topology walk confused by dup id
SMI Frequency (worst case): 35714 Hz (28 us)
[nothing further — no "Initialize MI interrupts", no SMP CPU1 banner]
```

`vm.sh up` timed out (ssh never answered); the guest stayed powered-on but
dead inside `start_all_aps()` — a silent wedge, worse to diagnose than a
panic. Classification per contract table: timeout + wedged guest ⇒
reproduced / dos.

## 2. Why it is real (path:line)

* `madt_lapic_pass2_callback` (acpi_madt.c:290-315): for every entry with
  `ACPI_MADT_ENABLED` it hands out `cpu = arg->cpu++` and calls
  `lapic_set_cpuid(cpu, lapic_ent->Id)` — no check that `Id` was already
  given a slot, and no check that `Id` corresponds to a CPU the system can
  start. Same for x2APIC (:330-344).
* Probe counts the same way (:399-407, :412-420) — duplicates and phantoms
  both inflate `lapic_count`/`x2apic_count`, so the table is accepted.
* Consumer: `naps = arg.cpu - 1` (:376) → `start_all_aps`
  (mp_machdep.c:482): per slot x, `start_ap()` INIT/SIPIs
  `CPUID_TO_APICID(x)`. For the duplicate: slot2's INIT lands on the
  already-running AP that serves slot1, so a gd slot never comes up; for a
  nonexistent ID the SIPI goes nowhere. `start_ap` failure path
  (mp_machdep.c:529-541) is an interactive `panic y/n?` prompt — on a
  serial console with no input the boot simply wedges before that.

Distinct from DF-1064 (entry-count OOB writes: needs >255 entries) — this
manifests with 3 entries and no memory corruption. Distinct from DF-5366
(cpu_id_to_apic_id sentinel) — the failure is enumeration topology, not
map lookup.

## 3. Threat model

Firmware-fed table, same vector as DF-5430/5431/5432 (demonstrated via the
unvalidated `hint.acpi.0.rsdp` kenv + QEMU loader blob). No unprivileged
in-guest path. Boot-time DoS (wedge). Low severity, DF-5343 bar.

## 4. Exploit chain

None — no memory unsafety; in-bounds indices only.

## 5. Fix

`fix.diff` adds an APIC-ID seen-bitmap to the pass2 cbarg and skips
duplicate entries in both callbacks (`madt_lapic_id_seen`, prints and
ignores). `git apply --check` passes. Nonexistent-ID phantoms are inherent
to trusting firmware enumeration (they degrade to the existing `start_ap`
timeout/panic path, which at least prints) — the dedup removes the
duplicate-id class that wedges silently. Not kernel-build-validated this
run (mandatory build slot spent on DF-5432; Low DoS class, DF-5339/DF-5343
precedent).

## 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.
