# DF-0542 — VERDICT

**Verdict:** NOT REPRODUCED at runtime (source-CONFIRMED real OOB-read; the
vulnerable code is dead/opt-in on the default guest).
**Impact:** none on a default install (latent; conditional on
`netgraph7_bluetooth` + BT hardware).
**Confidence:** likely (bug confirmed by source trace; not runtime-observed
because the module is not compiled/shipped/loadable on the default guest).

## Mechanism (source-confirmed)

1. `ng_hci_process_event()` (`ng_hci_evnt.c:86`) pulls the 3-byte HCI event
   header, logs `hdr->length` (`:100`) but does **not** validate it against
   the mbuf length, then dispatches on `hdr->event` (`:106`).
2. `NG_HCI_EVENT_INQUIRY_RESULT` → `inquiry_result()` (`:127`,`:370`).
3. `inquiry_result()` pulls only `sizeof(ng_hci_inquiry_result_ep)` = 1 byte
   (`num_responses`) (`:380`), `m_adj`s it (`:385`), then loops
   `for (; ep->num_responses > 0; ...)` (`:387`) with **no length guard**.
4. Each iteration consumes 14 bytes: `m_copydata(sizeof(bdaddr)=6)`+`m_adj(6)`
   (`:389-390`), `*mtod`+`m_adj(1)` (`:408-409`), `m_adj(1)` (`:412`),
   `*mtod`+`m_adj(1)` (`:414-415`), `m_adj(NG_HCI_CLASS_SIZE=3)` (`:418`),
   `m_copydata(sizeof(clock_offset)=2)` (`:421`). (NG_HCI_CLASS_SIZE=3 and
   bdaddr_t=6 confirmed in `ng_hci.h:78`,`:73`,`:375`.)
5. When `num_responses` exceeds the data in the chain, `m_adj` drains the chain
   to nothing; the next `m_copydata()` walks `m = m->m_next` to NULL and hits
   `KASSERT(m != NULL, "%s: length > size of mbuf chain")` at
   `sys/kern/uipc_mbuf.c:1687` → **panic (INVARIANTS/GENERIC)**; non-INVARIANTS
   ⇒ NULL `m->m_len` deref ⇒ page-fault panic. The `*mtod` reads (`:408`,`:414`)
   additionally read stale residue into the neighbor cache (limited leak).

The bug is real and not a false positive.

## Why NOT reproduced at runtime

netgraph7 bluetooth is opt-in and absent from the default system:
- `sys/conf/files` gates `ng_hci_evnt.c` on `optional netgraph7_bluetooth`;
  `X86_64_GENERIC` has **no** netgraph7 option ⇒ not in the kernel.
- No bluetooth/netgraph7 `.ko` ships in `/boot/kernel/`.
- Standalone `make` in `sys/netgraph7/bluetooth/hci` builds `ng_hci.ko`
  (rc=0), but `kldload` fails: *"depends on ng_bluetooth - not available"* —
  the whole netgraph7 BT framework is missing.
- Even fully loaded, the only way to reach `inquiry_result()` is a real HCI
  INQUIRY_RESULT event from a Bluetooth controller via `ng_ubt`/`ng_h4`; there
  is no userspace injection path on this guest.

⇒ The code path is **dead/unreachable at runtime on this guest AND no harness
can exercise it** without building the netgraph7 BT stack (root) and attaching
BT hardware — a valid hard blocker for live reproduction. (Validated the bug at
the source/object level and validated the fix compiles instead.)

## Fix-validation (fix.diff)

`fix.diff` adds a per-response size and bounds the loop by remaining
`event->m_pkthdr.len`:
```c
#define NG_HCI_INQUIRY_RESULT_SIZE \
    (sizeof(bdaddr_t) + 3 + NG_HCI_CLASS_SIZE + sizeof(u_int16_t))
for (; ep->num_responses > 0 &&
       event->m_pkthdr.len >= NG_HCI_INQUIRY_RESULT_SIZE;
     ep->num_responses --) { ... }
```
- git-apply clean; compiles (patched `ng_hci.ko` build rc=0, `build_hci.log`).
- `fix_status`: **not_testable** (runtime). The module is not loadable on the
  default guest and event injection requires BT hardware; the fix was validated
  to **apply + compile** and traced to close the over-read.

## PoC changes

Created the evidence pack from scratch (empty on handoff): `README.md`, this
`VERDICT.md`, `env.txt`, `build_result.txt`, `build_hci.log`, `fix.diff`,
`manifest.json`.

## Recommended fix (summary)

In `sys/netgraph7/bluetooth/hci/ng_hci_evnt.c`, bound `inquiry_result()`'s
loop by the remaining mbuf length (stop when `event->m_pkthdr.len <
NG_HCI_INQUIRY_RESULT_SIZE`, 14 bytes/response). (Matches the finding's
"clamp num_responses to m_pkthdr.len/14" proposal.)
