DragonFlyBSD Kernel Audit
DF-0282 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netgraph7/bluetooth/socket/ng_btsocket_rfcomm.c b/sys/netgraph7/bluetooth/socket/ng_btsocket_rfcomm.c
--- a/sys/netgraph7/bluetooth/socket/ng_btsocket_rfcomm.c
+++ b/sys/netgraph7/bluetooth/socket/ng_btsocket_rfcomm.c
@@ -2407,13 +2407,27 @@
 
 	/* Did we get any credits? */
 	if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) {
+		u_int8_t	credit;
+
+		/* The credit byte is the first byte of the UIH payload.  If the
+		 * frame has no payload, *mtod() reads a stale mbuf byte; require
+		 * at least one byte before consuming it. */
+		if (m0->m_pkthdr.len < 1)
+			goto drop1;
+
+		credit = *mtod(m0, u_int8_t *);
 		NG_BTSOCKET_RFCOMM_INFO(
 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
 "rx_cred=%d, tx_cred=%d\n",
-			__func__, *mtod(m0, u_int8_t *), dlci, pcb->state, 
+			__func__, credit, dlci, pcb->state, 
 			pcb->flags, pcb->rx_cred, pcb->tx_cred);
 
-		pcb->tx_cred += *mtod(m0, u_int8_t *);
+		/* tx_cred is int16_t; cap to RFCOMM_MAX_CREDITS to avoid signed
+		 * overflow from many credit-granting UIH frames (CWE-190). */
+		if (pcb->tx_cred + credit > RFCOMM_MAX_CREDITS)
+			pcb->tx_cred = RFCOMM_MAX_CREDITS;
+		else
+			pcb->tx_cred += credit;
 		m_adj(m0, 1);
 
 		/* Send more from the DLC. XXX check for errors? */