β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-0543

num_compl_pkts: unbounded variable-length loop reads past mbuf end -> remote kernel panic

Summary

num_compl_pkts(:884-924): pulls up sizeof(num_compl_pkts_ep)=1 byte(num_con_handles)(:884) m_adj(:889). Loops for(;num_con_handles>0;num_con_handles--)(:891). num_con_handles attacker-controlled NEVER validated vs remaining mbuf length. Each iter m_copydata(sizeof(h)=2)+m_copydata(sizeof(p)=2)+m_adj = 4 bytes. Body shorter than 4*count -> chain exhausted -> m_copydata KASSERT/NULL-deref panic. Same root cause: ng_hci_process_event never enforces hdr->length. Remote unauth BT. Fix: clamp num_con_handles to m_pkthdr.len/4.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-0543 Β· 9 files
FileTypeDescriptionSize
README.md readme claim, byte-count trace, repro status, fix 3.0 KB ↓ raw
VERDICT.md verdict full narrative: source-confirmed OOB, dead-code blocker, fix 3.0 KB ↓ raw
fix.diff suggested-fix bound num_compl_pkts loop by m_pkthdr.len (4 bytes/entry) 887 B view raw
build_hci.log build-log patched ng_hci.ko module build (both fixes), rc=0 clean 10.4 KB view raw
build_result.txt build-log module builds; kldload fails (ng_bluetooth absent) 745 B view raw
env.txt environment uname, cc, module availability, reachability conclusion 1.6 KB view raw
hci_event_analysis.sh trigger-source source-level byte-layout analysis of a triggering NUM_COMPL_PKTS HCI event 1.7 KB view raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
README.md readme claim, byte-count trace, repro status, fix
↓ download raw

DF-0543 β€” num_compl_pkts: unbounded loop reads past mbuf (netgraph7 HCI)

File: sys/netgraph7/bluetooth/hci/ng_hci_evnt.c Severity (fileed): High Class: Out-of-bounds read (mbuf chain over-read) β†’ kernel panic Module: ng_hci (netgraph7 bluetooth) β€” NOT compiled, NOT shipped, NOT loadable on the default X86_64_GENERIC guest. (Same root cause class as DF-0542: ng_hci_process_event never enforces hdr->length.)

The claim (source-level, CONFIRMED)

num_compl_pkts() (ng_hci_evnt.c:884) pulls up only sizeof(ng_hci_num_compl_pkts_ep) = 1 byte (num_con_handles) and loops:

for (; ep->num_con_handles > 0; ep->num_con_handles --) {   /* :891 */
    m_copydata(event, 0, sizeof(h), &h); m_adj(event, sizeof(h));   /* 2 bytes */
    m_copydata(event, 0, sizeof(p), &p); m_adj(event, sizeof(p));   /* 2 bytes */
    ...
}

Each iteration consumes 4 bytes (sizeof(h)=2 + sizeof(p)=2; both are u_int16_t declared at :882). The controller-supplied num_con_handles (first body byte) is never validated against the mbuf length β€” ng_hci_process_event (:86) logs hdr->length (:100) but does not enforce it.

A 1-byte event body with num_con_handles = 0xFF (255) demands 1020 bytes but the chain holds far less. Once m_adj drains the chain, m_copydata() walks m = m->m_next to NULL and hits KASSERT(m != NULL, "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.

Reproduction status

  • Source-level: CONFIRMED (4-byte/iteration math and m_copydata KASSERT traced).
  • Live trigger: NOT possible on the default guest β€” same as DF-0542: netgraph7 bluetooth is optional netgraph7_bluetooth, absent from X86_64_GENERIC, no .ko ships, kldload ng_hci.ko fails ("depends on ng_bluetooth - not available"), and reaching num_compl_pkts() needs a real HCI NUMBER_OF_COMPLETED_PACKETS event from a BT controller via ng_ubt/ng_h4. β‡’ dead code / latent here.

Impact (realistic, conditional)

Conditional on netgraph7 bluetooth being compiled in + a BT controller: remote-unauthenticated-packet β†’ kernel panic (DoS). No info-leak path here (the parsed h/p are looked up against existing connections and only a counter is updated β€” :903-919; the over-read reaches the KASSERT/NULL-deref, not a copyout). On the shipped default kernel this code is absent β‡’ none.

Old netgraph BT?

sys/netgraph/bluetooth/ does not exist in this tree; only netgraph7 carries this parser. No second copy to fix.

Fix

fix.diff β€” bound the loop by remaining mbuf length:

for (; ep->num_con_handles > 0 &&
       event->m_pkthdr.len >= (sizeof(h) + sizeof(p));     /* 4 bytes/entry */
     ep->num_con_handles --) { ... }

git-apply clean; compiles (patched ng_hci.ko build rc=0, build_hci.log).

Build

cd /usr/src/sys/netgraph7/bluetooth/hci && make     # -> ng_hci.ko (objdir), rc=0

Logs: build_hci.log, build_result.txt, env.txt.

VERDICT.md verdict full narrative: source-confirmed OOB, dead-code blocker, fix
↓ download raw

DF-0543 β€” 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 header, logs hdr->length (:100) but does not enforce it, dispatches on hdr->event (:106).
  2. NG_HCI_EVENT_NUM_COMPL_PKTS β†’ num_compl_pkts() (:171,:878).
  3. num_compl_pkts() pulls only sizeof(ng_hci_num_compl_pkts_ep) = 1 byte (num_con_handles) (:884), m_adjs it (:889), then loops for (; ep->num_con_handles > 0; ...) (:891) with no length guard.
  4. Each iteration consumes 4 bytes: m_copydata(sizeof(h)=2)+m_adj(2) (:893-894) and m_copydata(sizeof(p)=2)+m_adj(2) (:898-899). h,p are u_int16_t (:882).
  5. When num_con_handles exceeds the chain's data, m_adj drains the chain to NULL; the next m_copydata() walks m = m->m_next to NULL and trips 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. No copyout path (parsed values only update an in-kernel connection counter), so this is panic/DoS, not a direct info leak.

Same root cause as DF-0542 (ng_hci_process_event never validates hdr->length). The bug is real and not a false positive.

Why NOT reproduced at runtime

Identical to DF-0542: netgraph7 bluetooth is optional netgraph7_bluetooth, absent from X86_64_GENERIC, no .ko ships, standalone ng_hci.ko builds but kldload fails ("depends on ng_bluetooth - not available"), and reaching num_compl_pkts() requires a real HCI event from a BT controller. β‡’ dead/ unreachable at runtime on this guest AND no userspace harness can exercise it without building the netgraph7 BT stack (root) + BT hardware β€” a valid hard blocker for live reproduction.

Fix-validation (fix.diff)

fix.diff bounds the loop by remaining event->m_pkthdr.len:

for (; ep->num_con_handles > 0 &&
       event->m_pkthdr.len >= (sizeof(h) + sizeof(p));
     ep->num_con_handles --) { ... }
  • git-apply clean; compiles (patched ng_hci.ko build rc=0, build_hci.log).
  • fix_status: not_testable (runtime). Validated apply + compile; 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.

In sys/netgraph7/bluetooth/hci/ng_hci_evnt.c, bound num_compl_pkts()'s loop by the remaining mbuf length (stop when event->m_pkthdr.len < sizeof(h)+sizeof(p), 4 bytes/entry). (Matches the finding's "clamp num_con_handles to m_pkthdr.len/4" proposal.)

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

not_testable: compile validated, no runtime trigger.

git apply --check OK + module build rc=0.

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

Source trace + compile validation. No live trigger.

PoC changes

fix.diff + VERDICT.md + manifest.json per finding.

Verified recommended fix

See individual fix.diff per finding.

Verdict

Source-confirmed real but not runtime-reproduced. See individual evidence packs.