DragonFlyBSD Kernel Audit
DF-0281 / 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
@@ -3016,7 +3016,11 @@
 {
 	KKASSERT(lockowned(&pcb->pcb_lock) != 0);
 
-	pcb->mtu = le16toh(mtu);
+	/* DF-0281: the peer controls this value via a PN MCC frame; a zero
+	 * MTU later reaches an unguarded divisor in
+	 * ng_btsocket_rfcomm_send_credits() (line 3283). Reject/replace
+	 * an invalid (zero) MTU instead of trusting the peer. */
+	pcb->mtu = (le16toh(mtu) != 0) ? le16toh(mtu) : RFCOMM_DEFAULT_MTU;
 
 	if (cr) {
 		if (flow_control == 0xf0) {
@@ -3280,6 +3284,11 @@
 		__func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
 		ssb_space(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred);
 
+	/* DF-0281: never divide by pcb->mtu even if an earlier writer left
+	 * it zero; bail out instead of faulting (#DE -> kernel panic). */
+	if (pcb->mtu == 0)
+		return (EINVAL);
+
 	credits = ssb_space(&pcb->so->so_rcv) / pcb->mtu;
 	if (credits > 0) {
 		if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)