# DF-5477 VERDICT — efi_get_table(): physical st_cfgtbl used as KVA + unbounded st_entries walk

**Status: reproduced (KLD-harness / verbatim-copy evidence class; see rig limit).**
**Impact: panic** (deterministic fatal kernel fault on the root-reachable
EFIIOC_GET_TABLE path of any conforming EFI boot) **+ unbounded OOB read walk**
(family: unvalidated firmware table, cf. DF-5430..5433 / DF-5365).

## Why the bug is real (source trace)

1. `sys/platform/pc64/x86_64/efirt.c:411-412` stores
   `efi_cfgtbl = (struct efi_cfgtbl *)efi_systbl->st_cfgtbl;` — raw, no
   `PHYS_TO_DMAP`, no validation. Per the EFI spec the system table's
   ConfigurationTable pointer is the **physical** address of the config
   table array as long as `SetVirtualAddressMap()` has not been called.
2. This kernel **never** calls SetVirtualAddressMap: `rt_setvirtual`
   (sys/efi.h:131-132) has zero call sites in the whole tree; the design
   comment at efirt.c:320-325 explicitly says the 1:1 mapping was chosen
   *instead of* the virtual map. The EFI loader
   (stand/boot/efi/loader/bootinfo.c:397) passes the firmware's systab
   pointer through metadata and rewrites none of its fields.
3. `efi_get_table()` (efirt.c:469-487) runs in **normal kernel context**
   (no `efi_enter()`, so the 1:1 efi pmap is NOT active), and dereferences
   that physical value as a kernel virtual pointer at efirt.c:480
   (`bcmp(&ct->ct_uuid, ...)`) and advances `ct++` (efirt.c:484) while
   `count = efi_systbl->st_entries` (efirt.c:477), a firmware-fed `u_long`
   with **no bound of any kind**.
4. On this platform the kernel direct map starts at 0xffffb80000000000
   (verified empirically on the guest build); low physical addresses —
   where firmware tables live (my Part B used 0x7FB1C000, a typical value)
   — are **unmapped in the kernel pmap**. The first `ct->ct_uuid` read
   therefore takes a kernel-mode page fault on a "user" address with
   `pcb_onfault == NULL` → `trap.c:917-926` "Fatal user address access from
   kernel mode" → panic. On any EFI-booted DragonFly machine, the first
   `EFIIOC_GET_TABLE` ioctl (root-only /dev/efi, efidev.c:77-84) after
   boot panics the kernel deterministically.
5. Independently of the fault: wherever the walk *can* proceed (crafted
   boot environment that maps low RAM, or a small st_entries lie on a
   system where the cfgtbl happens to be reachable), the unbounded count
   is an OOB read walk, and a "match" returns `PHYS_TO_DMAP(ct_data)` —
   a kernel virtual address — straight to the ioctl caller (also DF-5481).

## Rig limitation (honest)

The audit guest boots legacy BIOS: `efi_systbl_phys == 0`, `efi_init()`
returns ENXIO before assigning `efi_systbl`/`efi_cfgtbl`, so the in-situ
production function has no inputs on this rig. Note `efirt.ko` still loads
(MOD_LOAD error 6 is merely logged by `module_register_init`) and
`/dev/efi` still appears — the surface is present, the data is not.

Evidence class therefore = **KLD harness with a verbatim copy** of
efirt.c:469-487 (df5477_harness.c; only the two statics renamed; every
expression identical). The kernel-side constants (DMAP base, fault
classification, pcb_onfault semantics) are the real, running kernel's.

## What was run

* **Part A** — `sysctl debug.df5477=1`: table with 2 true entries,
  `st_entries = 200` (the lie a crafted systab feeds). Output:
  `DF-5477A: FOUND entry 199 past table end -> returned kernel DMAP
  pointer 0xffffc5eadbeef000` — the walk demonstrably consumed data 4776
  bytes past the table's true extent and handed a kernel DMAP VA to the
  caller. (run.log)
* **Part B** — `sysctl debug.df5477=2`: `st_cfgtbl = 0x7FB1C000`
  (physical), used raw exactly as efirt.c:411-412 stores it. Output
  (run.2.log / panic.txt): `Fatal user address access from kernel mode
  from sysctl`, `Fatal trap 12: page fault while in kernel mode`,
  `fault virtual address = 0x7fb1c000`, `supervisor read data, page not
  present`, `Stopped at bcmp+0x11: movq (%rdi),%r8` — the precise
  efirt.c:480 dereference, the precise trap.c:917-926 classification.
  Guest wedged in DDB; reset with `vm.sh reset` afterwards.

## Exploit-chain assessment

Firmware/loader-fed at boot, root-gated at runtime: no unprivileged-user
route. The primitive is an arbitrary-length kernel OOB *read* walk that
also discloses kernel DMAP VAs; worst realistic outcome on a crafted boot
chain is kernel-memory disclosure / boot-time fault — consistent with the
family's Medium rating (cf. DF-5365 lapic_map). No escalation chain is
claimed.

## Fix validation

`fix.diff` (cap `st_entries` at 256 → EOVERFLOW; `PHYS_TO_DMAP` the
physical table pointer before the walk; bounds-check `ct_data`).
Validated by `df5477_fixed.c` — the same harness carrying only the fix:
  * lie st_entries=512 → `error=84 (EOVERFLOW) ... FIX HOLDS (walk refused)`
  * physical 0x7FB1C000 → `DMAPs it to 0xffffb8007fb1c000 before deref`,
    `returned without fault`.
(fix_run.log). A full kernel-rebuild validation is not meaningful on this
BIOS rig: the patched in-situ function has no inputs here (baseline
itself is only reachable via the harness); the harness equivalence is the
strongest test this rig admits.

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