DragonFlyBSD Kernel Audit
DF-0542 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netgraph7/bluetooth/hci/ng_hci_evnt.c b/sys/netgraph7/bluetooth/hci/ng_hci_evnt.c
--- a/sys/netgraph7/bluetooth/hci/ng_hci_evnt.c
+++ b/sys/netgraph7/bluetooth/hci/ng_hci_evnt.c
@@ -384,7 +384,19 @@
 	ep = mtod(event, ng_hci_inquiry_result_ep *);
 	m_adj(event, sizeof(*ep));
 
-	for (; ep->num_responses > 0; ep->num_responses --) {
+	/*
+	 * Each response consumes sizeof(bdaddr) + 1 + 1 + 1 + NG_HCI_CLASS_SIZE
+	 * + sizeof(clock_offset) bytes from the mbuf.  The remote controller-
+	 * supplied num_responses is not trusted; stop as soon as the remaining
+	 * mbuf cannot hold a full response, otherwise m_copydata()/mtod() will
+	 * read past the exhausted chain (KASSERT/NULL-deref panic, and stale
+	 * *mtod reads leak residue into the neighbor cache).
+	 */
+#define NG_HCI_INQUIRY_RESULT_SIZE	\
+	(sizeof(bdaddr_t) + 3 + NG_HCI_CLASS_SIZE + sizeof(u_int16_t))
+	for (; ep->num_responses > 0 &&
+		   event->m_pkthdr.len >= NG_HCI_INQUIRY_RESULT_SIZE;
+	     ep->num_responses --) {
 		/* Get remote unit address */
 		m_copydata(event, 0, sizeof(bdaddr), &bdaddr);
 		m_adj(event, sizeof(bdaddr));