hci_event_inquiry_result/rssi_result: unbounded loops guarded only by KKASSERT -> remote kernel panic on short data
Summary
hci_event_inquiry_result(:447-469) + hci_event_rssi_result(:484-506): trust attacker ep.num_responses(uint8 0-255). Only check KKASSERT(pkthdr.len>=sizeof(ep)=1)(:447/:484). while(ep.num_responses--) loop per iter KKASSERT(pkthdr.len>=sizeof(ir)=15)(:455) / KKASSERT(pkthdr.len>=sizeof(rr)=14)(:492). Controller sends num_responses>N records -> KKASSERT fails -> panic INVARIANTS(default X86_64_GENERIC) / m_copydata NULL-deref non-INVARIANTS. hci_event_hdr_t.length NEVER consulted. Packed structs(hci.h:1862/2092) attacker computes exact short-data. Netbt twin of DF-0542(ng7). Remote unauth BT DoS. Fix: validate num_responses*sizeof(ir)<=remaining upfront, replace KKASSERT with real bounds check.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-0559 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | upfront num_responses*sizeof(ir/rr) bound + remove KKASSERT reliance | 1.2 KB | view raw |
| build.sh | build-script | build netbt.ko to validate the fix compiles | 439 B | view raw |
| run.sh | run-script | documents HW-gated trigger (no BT radio on guest) | 551 B | view raw |
| VERDICT.md | verdict | full source trace + why-not-reproducible + fix | 3.0 KB | β raw |
| env.txt | environment | uname, config, netbt module/HW reachability | 1.8 KB | view raw |
| fix_build.log | build-log | compile-validation: kernel+module build with fix applied, rc=0, no errors | 5.3 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 |
DF-0559 β hci_event_inquiry_result / rssi_result unbounded loops
Verdict
NOT TESTABLE at runtime (no Bluetooth hardware) β bug CONFIRMED at source
(certain). Fix authored in fix.diff; compiled cleanly as part of a combined
nativekernel build (netbt.ko) carrying all four verified findings' fixes.
Mechanism (source trace, every hop cited)
Two sibling handlers, both reached from hci_event() (sys/netbt/hci_event.c)
at :189-190 (HCI_EVENT_INQUIRY_RESULT) and :193-194
(HCI_EVENT_RSSI_RESULT).
hci_event_inquiry_result() (sys/netbt/hci_event.c:440-470):
- KKASSERT(m->m_pkthdr.len >= sizeof(ep)) (:447) β only the 1-byte
hci_inquiry_result_ep header. Reads ep.num_responses (uint8_t, 0-255,
attacker-controlled) (:448-449).
- while(ep.num_responses--) (:454) β per iteration the only guard is
KKASSERT(m->m_pkthdr.len >= sizeof(ir)) (:455) where sizeof(ir) = 15.
A KKASSERT is an INVARIANTS-only trap, NOT a runtime bounds check: it
panics instead of recovering. Each iteration consumes 15 bytes
(m_copydata+m_adj, :456-457).
hci_event_rssi_result() (sys/netbt/hci_event.c:477-507):
- Identical shape: KKASSERT(... sizeof(ep)) (:484), reads
ep.num_responses (:485), while(ep.num_responses--) (:491) with
KKASSERT(m->m_pkthdr.len >= sizeof(rr)) (:492) where sizeof(rr) = 14.
A controller (or injected HCI event) sending num_responses = N but fewer than
N*15 (resp. N*14) packed records makes the loop's KKASSERT trip on the
2nd+ iteration when the chain runs out β panic (INVARIANTS ON in
X86_64_GENERIC, the production default). On a non-INVARIANTS build,
m_copydata on an exhausted chain derefs NULL β panic. Either way it is a
remote unauthenticated Bluetooth DoS. hci_event_hdr_t.length (:168) is
never consulted.
INVARIANTS being ON means the per-iter KKASSERT is compiled in β the
reviewer's claim that this manifests as a panic on the default kernel is
correct (note: nm ... | grep KASSERT == 0 is a known false negative because
KKASSERT/KASSERT expand to inline panic(), not named symbols).
Why not reproduced live (the realistic constraint)
Same as DF-0558: the QEMU/KVM audit guest has no Bluetooth controller.
netbt is shipped only as netbt.ko (not in the kernel, not loaded) and no
struct hci_unit is ever created, so hci_event()/hci_input() are
unreachable. The bug is a genuine latent/net-radio path. The netbt-twin finding
DF-0542 (netgraph7 BT) is the same defect in the older stack.
Fix (fix.diff)
For each handler: replace the per-iteration INVARIANTS-only KKASSERT with an
explicit upfront bounds check β ep.num_responses * sizeof(ir/rr) against
the remaining m->m_pkthdr.len, log + return on a malformed event β and drop
the now-redundant per-iter KKASSERT. Minimal, targeted, recovers gracefully
instead of panicking.
PoC changes
findings/poc/DF-0559/ was empty on arrival. This runner authored fix.diff,
build.sh, run.sh, README.md, VERDICT.md, manifest.json, env.txt.
Fix verification
not_testablecompile validated rc=0
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed real, no BT HW. hci_event_inquiry_result/rssi_result unbounded loops.
No comments yet.