⬢ DragonFlyBSD Kernel Audit
DF-5753 / fix.diff
← back to finding ↓ download raw
--- a/sys/netbt/hci_unit.c	2026-10-11 08:02:59.057438200 +0000
+++ b/sys/netbt/hci_unit.c	2026-10-11 08:36:08.935790902 +0000
@@ -392,12 +392,19 @@
 		DPRINTFN(11, "(%s) complete SCO\n",
 		    device_get_nameunit(unit->hci_dev));
 
+		/*
+		 * Dispatch under hci_devlock: cannot race a syscall-context
+		 * teardown (sco_disconnect: hl_sco = NULL; hci_link_free)
+		 * on the same link list.
+		 */
+		lockmgr(&unit->hci_devlock, LK_EXCLUSIVE);
 		TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
 			if (link == M_GETCTX(m, struct hci_link *)) {
 				hci_sco_complete(link, 1);
 				break;
 			}
 		}
+		lockmgr(&unit->hci_devlock, LK_RELEASE);
 
 		unit->hci_num_sco_pkts++;
 		m_freem(m);
--- a/sys/netbt/sco_upper.c	2026-10-11 08:02:59.061438148 +0000
+++ b/sys/netbt/sco_upper.c	2026-10-11 08:36:08.919791108 +0000
@@ -212,9 +212,20 @@
 
 	err = hci_send_cmd(sco->hl_unit, HCI_CMD_DISCONNECT, &cp, sizeof(cp));
 	if (err || linger == 0) {
+		struct hci_unit *unit = sco->hl_unit;
+
+		/*
+		 * Tear the pcb out of the link and free the link under
+		 * hci_devlock: the netisr scodone dispatch in hci_intr()
+		 * walks hci_links and calls hci_sco_complete() under the
+		 * same lock, so hl_sco can no longer be observed NULL
+		 * (or the link freed) mid-dispatch from this path.
+		 */
+		lockmgr(&unit->hci_devlock, LK_EXCLUSIVE);
 		sco->hl_sco = NULL;
 		pcb->sp_link = NULL;
 		hci_link_free(sco, err);
+		lockmgr(&unit->hci_devlock, LK_RELEASE);
 	}
 
 	return err;