⬢ DragonFlyBSD Kernel Audit
DF-5747 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5747",
  "status": "reproduced",
  "reproduced": true,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Reproduced on the QEMU guest with a KLD rig compiling sys/netbt/rfcomm_session.c, rfcomm_dlc.c, rfcomm_upper.c VERBATIM (md5-verified vs /usr/src/sys/netbt) against a stub L2CAP layer. Production rfcomm_bind() (rfcomm_upper.c:103-109) accepted a re-bind of a live LISTENing DLC: bind #2 in state 8 returned 0 and mutated the listeners advertised channel 3->5 and psm 0x0003->0x1001 in place. NetBSD upstream returns EINVAL for exactly this call (state check in rfcomm_bind_pcb(), still present in rfcomm_upper.c 1.24/2024); DragonFly never took the fix. Pure semantic/state-confusion bug confined to the callers own sockets (rfcomm_listens channel allocator and rfcomm_dlc_newconns best-match both consume rd_laddr.bt_channel); no memory unsafety, no cross-privilege effect - hence Info severity. One-line fix validated on the guest: patched build returns 22/EINVAL for the LISTEN-state bind while the CLOSED-state bind still succeeds and teardown stays clean.",
  "exploit_chain": "",
  "evidence": "run.log: [DF-5747] bind #2 (state LISTEN) -> 0 (BUG: live listener mutated; upstream returns EINVAL) and listener now advertises: channel=5 psm=0x1001 state=8; fix_run.log: bind #2 (state LISTEN) -> 22 (EINVAL - fixed) with channel=3 psm=0x0003 preserved; fix_build.log: objdump of patched rfcomm_bind showing cmpw rd_state/mov $0x16 (EINVAL); setup.log: verbatim-source md5s",
  "kernel_refs": [
    "sys/netbt/rfcomm_upper.c:103-109",
    "sys/netbt/rfcomm_upper.c:357-373",
    "sys/netbt/rfcomm_dlc.c:92-113"
  ],
  "poc_changes": "Harness written fresh on the DF-5733 rig pattern (verbatim netbt sources + l2cap_stub.c + FCS-valid frame injectors were not needed here - only production upper-API calls); stub gained harness_last_channel(); no production source modified for the baseline run.",
  "attempts": 2,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "runtime_sec": 8,
  "guest_dirty": 0,
  "build_cmd": "cd /root/rfup/DF-5747 && ./build.sh   (make -m /usr/src/share/mk SYSDIR=/usr/src/sys)",
  "run_cmd": "cd /root/rfup/DF-5747 && ./run.sh && dmesg | tail",
  "code_hash": "0ddb3bdabd9c9816c15f01ae9d4ad295ae9e4845437eab0a0732e7a43b993ef8",
  "notes": "Fix-validation note: the first patched rebuild without make clean/MAKEOBJDIRPREFIX relinked a stale rfcomm_upper.o from a second objdir and showed unchanged behavior; the clean rebuild (disassembly-verified) is the validated one. Guest left clean via vm.sh reset with-src. netbt is not in X86_64_GENERIC; rig compiles it into the module, which is why a socket-level PoC was not possible on this guest.",
  "recommended_fix": "Add the upstream NetBSD state check to rfcomm_bind(): reject with EINVAL unless dlc->rd_state == RFCOMM_DLC_CLOSED (see fix.diff).",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026 (same guest, rig-level rebuild of the verbatim sources)",
  "fix_verdict": "fix.diff applied to the verbatim rig copy with patch -p3, clean-rebuilt, reloaded, same trigger: bind #2 (state LISTEN) now returns 22/EINVAL and the listener keeps channel=3/psm=0x0003; bind #1 (CLOSED) still returns 0; detach/teardown clean. Bad behavior gone on patched build.",
  "fix_evidence": "fix_run.log ([DF-5747] bind #2 (state LISTEN) -> 22  (EINVAL - fixed)); fix_build.log (patch output + relink + rfcomm_bind disassembly with the EINVAL path)"
}