hci_route_lookup walks hci_unit_list and unit->hci_links with no synchronization against attach/detach (crit_enter-only) and privileged hci_disable teardown β UAF reads and 6-byte freed-heap disclosure via getsockname
Summary
The route lookup TAILQ-walks the global unit list and each unit's links with no lock while attach/detach mutate under crit_enter only (current-CPU interrupt masking, not cross-CPU exclusion) and privileged hci_disable frees all links: a detach/disable racing an unprivileged connect reads freed memory; bdaddr_copy copies 6 bytes of freed heap into the socket address readable via getsockname (limited leak) and a stale link deref panics. Privileged mutator precondition - Low. unit-list lock fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5781 Β· 2 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | file | 1.5 KB | β raw | |
| verdict.json | file | 1.6 KB | view raw |
DF-5781 β hci_route_lookup walks hci_unit_list / hci_links with no synchronization vs attach/detach/disable
Analysis-only pack (Low severity -> PoC skipped per audit contract).
hci_route_lookup() (sys/netbt/hci_misc.c:65-100) TAILQ-walks the global
hci_unit_list and each unit's hci_links with no lock, while:
hci_attach/hci_detachmutatehci_unit_listundercrit_enter()only (sys/netbt/hci_unit.c:113-115, 123-127) β crit_enter blocks interrupts on the current CPU only and does not stop a cross-CPU syscall-context walker;hci_disable(privileged SIOCSBTFLAGS, hci_ioctl.c:223-231; device detach) tears down all links (hci_unit.c:238-245) and frees all memos (:247-248) while user threads may be mid-walk.
A detach/disable racing an unprivileged connect() yields UAF reads of
struct hci_unit/struct hci_link; bdaddr_copy(src, &unit->hci_bdaddr)
(hci_misc.c:105) copies 6 bytes of freed kernel heap into the socket's local
address, readable back via getsockname(2) (limited info leak); a stale link
deref panics.
Rated Low: one side of the race requires root (SIOCSBTFLAGS/DOWN is caps_priv_check_self-gated) or physical device removal; no unprivileged-only trigger identified. Not PoC-verified (Low). The memo-list half of this family is DF-5780 (reproduced, High). Suggested fix: a global netbt unit-list lock (or per-unit refcount + RCU-style removal) plus holding it across hci_route_lookup's walks; see DF-5780's fix.diff for the memo-half.
Fix verification
not_testableConfirmed kernel references
Detail
Evidence (decisive lines)
source citations in README.md (this directory)
PoC changes
n/a (not built)
Verified recommended fix
global netbt unit-list lock (or per-unit refcount) held across hci_route_lookup walks and hci_attach/hci_detach/hci_disable
Verdict
Analysis-only (Low severity; PoC skipped per contract). hci_route_lookup walks hci_unit_list and unit->hci_links unlocked (hci_misc.c:65-100) against hci_attach/hci_detach's crit_enter-only list mutations (hci_unit.c:113-127) and hci_disable's teardown (hci_unit.c:238-248, privileged SIOCSBTFLAGS hci_ioctl.c:223-231). Detach/disable racing an unprivileged connect gives UAF reads and a 6-byte freed-heap read into the socket laddr (hci_misc.c:105, getsockname-readable). Root/physical precondition on one side -> Low, unverified on the guest (its memo-list sibling DF-5780 was reproduced).
No comments yet.