DragonFlyBSD Kernel Audit
DF-0497 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netgraph7/bluetooth/socket/ng_btsocket_l2cap_raw.c b/sys/netgraph7/bluetooth/socket/ng_btsocket_l2cap_raw.c
--- a/sys/netgraph7/bluetooth/socket/ng_btsocket_l2cap_raw.c
+++ b/sys/netgraph7/bluetooth/socket/ng_btsocket_l2cap_raw.c
@@ -700,9 +700,13 @@
 				break;
 		}
 
-		lockmgr(&ng_btsocket_l2cap_raw_rt_lock, LK_RELEASE);
-
+		/*
+		 * Keep rt_lock held across pcb->rt = rt.  ng_btsocket_l2cap_rtentry
+		 * has no refcount, so releasing rt_lock before storing the pointer
+		 * lets ng_btsocket_l2cap_raw_rtclean() free the entry (use-after-free).
+		 */
 		if (rt == NULL) {
+			lockmgr(&ng_btsocket_l2cap_raw_rt_lock, LK_RELEASE);
 			error = ENETDOWN;
 			goto out;
 		}
@@ -714,6 +718,9 @@
 	pcb->rt = rt;
 	lockmgr(&pcb->pcb_lock, LK_RELEASE);
 
+	if (rt != NULL)
+		lockmgr(&ng_btsocket_l2cap_raw_rt_lock, LK_RELEASE);
+
 out:
 	lwkt_replymsg(&msg->bind.base.lmsg, error);
 } /* ng_btsocket_l2cap_raw_bind */