Unsynchronized sc->inq/outq between hard ISR and netgraph forward: ifqueue corruption / UAF
Summary
bt3c_intr hard-ISR(:771) -> bt3c_receive IF_ENQUEUE(&sc->inq)(:939). bt3c_swi_intr(SWI_TTY:963) -> ng_send_fn -> bt3c_forward IF_DEQUEUE(&sc->inq)(:1017). IF_ENQUEUE/DEQUEUE macros(if_var.h:484-510) are LOCK-FREE linked list manipulation. attach(:609-675) inits NO ifqueue lock. Hard ISR explicitly outside netgraph node serialization. Hard IRQ preempts SWI -> ISR IF_ENQUEUE mid-IF_DEQUEUE -> list corruption, ifq_tail/ifq_head dangling at freed mbuf -> UAF. Same pattern outq(:566 vs :1060/:1081). Remote-ish BT RF trigger but gated on rare 3CRWB609 PCMCIA hardware. Fix: move IF_ENQUEUE to SWI or spinlock all queue ops.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-0533 Β· 9 files| File | Type | Description | Size | |
|---|---|---|---|---|
| build.sh | build-script | reports absence of ng_bt3c module/PCMCIA | 330 B | view raw |
| run.sh | run-script | probes driver/bus absence | 451 B | view raw |
| run.log | run-log | reachability probe: no module, no PCMCIA, no BT option | 662 B | view raw |
| env.txt | environment | uname, module/bus/option absence | 304 B | view raw |
| fix.diff | suggested-fix | add sc_lock spinlock; wrap all IF_*QUEUE sites (var.h + pccard.c); applies cleanly | 3.0 KB | view raw |
| VERDICT.md | verdict | full source trace + reachability + fix rationale | 3.3 KB | β raw |
| README.md | readme | evidence pack index | 1.5 KB | β 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-0533 β bt3c hard-ISR vs SWI unsynchronized inq/outq race (UAF)
Verdict: LATENT on this guest (source bug real; not runtime-exercisable).
Fix authored (fix.diff, applies cleanly; not_testable β no PCMCIA HW).
Bug
ng_bt3c_pccard.c registers a hard ISR (bt3c_intr β bt3c_receive) that does
IF_ENQUEUE(&sc->inq, β¦) (:939) and an SWI handler (bt3c_swi_intr β
bt3c_forward) that does IF_DEQUEUE(&sc->inq, β¦) (:1017). IF_*QUEUE macros
(net/if_var.h:484-510) are lock-free linked-list ops, and attach
initialises no lock for inq/outq. A hard IRQ landing mid-IF_DEQUEUE
corrupts the list β dangling ifq_head/ifq_tail β UAF. Same shape on outq
(:566 vs :1060/:1081).
Reachability
Latent on this guest. The driver is optional netgraph7_bluetooth_bt3c
(sys/conf/files:1669); there is no ng_bt3c.ko shipped, no bt3c symbols in
the running kernel, no PCMCIA/pccard bus in QEMU, and the 3Com 3CRWB6095
card it drives is absent. So the race is dead code here β a real defect that
would manifest on real hardware.
Fix
fix.diff adds a struct spinlock sc_lock to bt3c_softc
(ng_bt3c_var.h), spin_inits it in attach, and wraps every
IF_ENQUEUE/IF_DEQUEUE/IF_PREPEND site (inq + outq) with
spin_lock/spin_unlock, serialising the ISR producer against the SWI/netgraph
consumers. Applies cleanly; not build-validated (needs PCMCIA headers/HW).
See VERDICT.md for the full line-cited trace.
DF-0533 β bt3c hard-ISR vs SWI unsynchronized inq/outq race (UAF): LATENT
Verdict: NOT REPRODUCED on this guest (LATENT). Source bug REAL; fix authored, applies cleanly; not build/runtime-testable here (no PCMCIA hardware + module not shipped).
SOURCE TRACE (bug is real)
Driver: sys/netgraph7/bluetooth/drivers/bt3c/ng_bt3c_pccard.c (3Com 3CRWB6095 PCMCIA Bluetooth card)
-
bt3c_pccard_attach (:609-671):
- bus_setup_intr(dev, sc->irq, 0, bt3c_intr, sc, ...) [:635] -> hard ISR
- register_swi_mp(SWI_TTY, bt3c_swi_intr, ...) [:643] -> SWI handler
- sc->inq.ifq_maxlen = sc->outq.ifq_maxlen = ...; [:668] NO ifqueue lock / spinlock is initialised for inq or outq.
-
bt3c_intr (hard ISR, :749) -> bt3c_receive (:786) -> on a complete packet: IF_ENQUEUE(&sc->inq, sc->m); [:939] (also IF_QFULL/IF_DROP on inq at :930/:934.)
-
bt3c_swi_intr (:963) -> ng_send_fn(..., &bt3c_forward, ...) [:973] -> bt3c_forward (:1005) drains the queue from SWI/netgraph context: IF_DEQUEUE(&sc->inq, m); [:1017, :1027] bt3c_send (:1042) does IF_DEQUEUE/IF_PREPEND on outq [:1060, :1081]; bt3c_rcvdata (netgraph hook) does IF_ENQUEUE on outq [:566].
-
IF_ENQUEUE / IF_DEQUEUE / IF_PREPEND (net/if_var.h:484-510) are LOCK-FREE doubly-linked-list manipulations of ifq_head/ifq_tail. There is no serializer between the hard ISR (which preempts SWI) and the SWI dequeue. A hard IRQ landing mid-IF_DEQUEUE corrupts the list -> ifq_tail/ifq_head dangle at a freed mbuf -> use-after-free. (Same shape on outq between rcvdata and bt3c_send.)
REACHABILITY ON THIS GUEST (latent)
- ng_bt3c_pccard.c is
optional netgraph7_bluetooth_bt3c(sys/conf/files:1669) and is built as module ng_bt3c.ko via a PCMCIA (pccard) driver. There is NO ng_bt3c.ko in /boot/kernel on this guest, no bt3c symbols in the running kernel (nm count = 0). - The driver requires a 3Com 3CRWB6095 PCMCIA card. QEMU does not emulate PCMCIA/pccard; devinfo shows no pccard/cardbus/cbb bus. So the driver cannot attach and no bt3c interrupts can occur.
- => The race is DEAD CODE on this guest. It is a real latent defect that would manifest on real hardware (or a PCMCIA-emulating harness). This is a valid "genuinely not reachable on this kernel AND no harness can exercise it" case: the primitive is proven at the source level (lock-free IF_*QUEUE macros with a preempting producer), but no live trigger exists here.
FIX
fix.diff adds a struct spinlock sc_lock to bt3c_softc (ng_bt3c_var.h), inits
it in attach (spin_init), and wraps every IF_ENQUEUE/IF_DEQUEUE/IF_PREPEND site
(inq in bt3c_receive + bt3c_forward; outq in bt3c_rcvdata + bt3c_send) with
spin_lock/spin_unlock. The spinlock is acquireable from the hard ISR filter
context, serialising the producer (ISR) against the consumers (SWI/netgraph).
git-apply-able; applies cleanly. NOT build-validated on this guest (the module
requires pccard bus headers / hardware to build & exercise).
NOT TESTABLE
fix_status = not_testable: cannot build/exercise ng_bt3c on a guest without PCMCIA. The diff applies and the change is correct-by-inspection against the net/if_var.h IF_* macro definitions.
Fix verification
not_testablecompile validated
see evidence pack
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. bt3c ISR/SWI IF_ENQUEUE/IF_DEQUEUE lock-free race -> UAF. No PCMCIA HW, ng_bt3c not shipped.
No comments yet.