# DF-3797 — VERDICT

## Status: REPRODUCED (protocol-replica on the audit guest; no ENA hardware present)

**Reproduced:** 1 — mechanism, sink and full command path proven with the
driver's own code; fatal-panic variant captured; fix validated baseline vs
patched on the same guest.

## Root cause (audited tree, line-accurate)
1. `sys/dev/virtual/amazon/ena/ena-com/ena_com.c:1156-1159` — after the
   CREATE_SQ admin command completes, `io_sq->idx` and
   `io_sq->db_addr = (u32 *)((uintptr_t)ena_dev->reg_bar +
   (uintptr_t)cmd_completion.sq_doorbell_offset)` are stored with **no
   validation** of the device-supplied `sq_doorbell_offset` (u32).
2. `sys/dev/virtual/amazon/ena/ena-com/ena_com.c:1333-1346` — same for the
   CREATE_CQ reply: `unmask_reg`, `cq_head_db_reg`, `numa_node_cfg_reg`
   from `cq_interrupt_unmask_register_offset`,
   `cq_head_db_register_offset`, `numa_node_register_offset` — no
   validation.
3. `sys/dev/virtual/amazon/ena/ena.c:3671-3675` — the DragonFly port never
   assigns `ena_dev->reg_bar` (FreeBSD's attach has the extra line
   `ena_dev->reg_bar = ((struct ena_bus*)(ena_dev->bus))->reg_bar_h;`,
   dropped here). `reg_bar` therefore stays NULL, so the pointers built in
   (1)/(2) are the **raw device offsets**.
4. `sys/dev/virtual/amazon/ena/ena-com/ena_plat.h:325-329` —
   `ENA_REG_WRITE32(bus, v, reg)` is `bus_space_write_4(reg_bar_t,
   reg_bar_h, (bus_size_t)reg, v)`, and DragonFly's x86_64
   `bus_space_write_4` (sys/cpu/x86_64/include/bus_dma.h:404-410) is
   `*(volatile u_int32_t *)(bsh + offset) = value` — a plain CPU store at
   BAR-KVA + offset.
5. Live sinks reachable from ena.c: `ena_com_write_sq_doorbell` at
   ena.c:1049 (RX refill), 2967/2978 (ena_start_xmit doorbells, value =
   `io_sq->tail`); `ena_com_unmask_intr` at ena.c:1813 (every IO MSI-X),
   2168 (ena_unmask_all_io_irqs).

Net effect: a malicious peer controls a u32 **write offset** into
[BAR KVA, +4G) of kernel virtual space and semi-controls the value (fixed
`intr_control` bits for the unmask sink; the groomable `tail` counter for
the doorbell sink). The store is executed by the guest CPU, so IOMMU
device-isolation is irrelevant — this is the classic escape for a
compartmentalized smart-NIC threat model, and a memory-corruption
primitive under the hypervisor-trust model this file is audited under.

## Evidence (this pack)
- `run.log` — decisive dmesg lines:
  - inline replica mode 1: BAR=0xfffff80118830000, device offset 0x1008 →
    real `ena_com_unmask_intr()` overwrote a sentinel in an *adjacent,
    unrelated* kernel mapping (0xfffff80118831008): `a1b2c3d4 → 40190014`.
  - mode 2: real `ena_com_write_sq_doorbell()` wrote `0x1337` (tail
    counter) at a device-chosen offset.
  - full-path baseline: REAL `ena_com_create_io_cq()` returned 0 with
    `unmask_reg=0x86fc0008` from an emulated hostile completion;
    `VICTIM OVERWRITTEN via device-chosen register offset — primitive
    confirmed`.
- `panic.txt` — mode 3: `Fatal trap 12: page fault while in kernel mode`,
  `fault virtual address = 0xfffff80196b9eff8` (= BAR + 0x7ffffff8),
  `fault code = supervisor write data, page not present`, DDB stopped at
  `enarep_run+0x3b9: movl $0x40190014,0x7ffffff8(%rax)` — the literal
  store instruction.
- `fix_run.log` — patched build (fix.diff applied to the shipped ena-com
  copy, `reg_bar_len = PAGE_SIZE`): same hostile completion →
  `ena_com_create_io_cq() = 22`, `unmask_reg=0`,
  `NO WRITE PERFORMED (fix active)`, `GUEST_STILL_UP`.
- `build.log` / `fix_build.log` — untrimmed builds (baseline and
  `-DENAFULL_FIXED`).
- `enarep.c` — inline replica (real driver static inlines + hostile reply
  values; the only simulated bytes are the device-reply fields).
- `enafull.c` — full-path replica: compiles the **unmodified** audited
  `ena-com/ena_com.c` + `ena_eth_com.c` into the module, builds a real
  admin queue (real `ena_com_init_comp_ctxt`, real submit → doorbell →
  polling completion path), lays a hostile CREATE_CQ completion into the
  admin CQ (the exact memory a malicious device DMA-writes), then calls
  the real `ena_com_create_io_cq()` and the real `ena_com_unmask_intr()`.
- `fix.diff` — `git apply --check` clean against sys/.
- `env.txt` — guest uname, cc 8.3, if_ena.ko present (not loaded, no ENA
  PCI device: expected on KVM).

## Why not runtime-driven from a real device
The audit guest is QEMU/KVM with virtio only; no Amazon ENA function
exists (pciconf in env.txt). The replica method (established for this
audit by DF-3779/DF-3715) runs the driver's real code against the hostile
peer bytes, which is the entire attack-relevant surface here.

## Exploitation ceiling (honest)
- Primitive: arbitrary-offset u32 write in [BAR, BAR+4G), value either
  fixed (`0x40190014` family) or a groomable u16-derived counter
  (`io_sq->tail`), repeatable (every interrupt unmask, every doorbell).
- Target selection depends on guest KVA layout: the BAR is mapped in the
  kernel map; the +4G window covers subsequent kernel-map allocations
  (other device mappings on this guest; heap depending on layout — in the
  observed runs kmalloc pages sat *below* the BAR, out of unsigned reach,
  while adjacent pmap_mapdev mappings were reachable).
- No uid=0 chain assembled: driving `tail`/traffic grooming requires a
  live malicious peer. Demonstrated impact is kernel-memory corruption of
  a chosen KVA (sentinel) and a deterministic guest panic.

## Fix validation
- baseline: overwrite via real path — reproduced (run.log).
- patched: `fix.diff` applied → EINVAL from create, no write, guest up
  (fix_run.log). fix_status = fixed.

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