DragonFlyBSD Kernel Audit
DF-1795 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/netif/plip/if_plip.c b/sys/dev/netif/plip/if_plip.c
--- a/sys/dev/netif/plip/if_plip.c
+++ b/sys/dev/netif/plip/if_plip.c
@@ -346,11 +346,20 @@
 	break;
 
     case SIOCSIFMTU:
+    {
+	u_char *newbuf;
 	ptr = sc->sc_ifbuf;
-	sc->sc_ifbuf = kmalloc(ifr->ifr_mtu+MLPIPHDRLEN, M_DEVBUF, M_WAITOK);
+	newbuf = kmalloc(ifr->ifr_mtu+MLPIPHDRLEN, M_DEVBUF, M_WAITOK);
+	/* Publish the new buffer and the new mtu together; free the old
+	 * buffer last.  Previously the three steps (kmalloc new, kfree old,
+	 * set if_mtu) were unlocked and visible to lp_intr in intermediate
+	 * states, so the interrupt handler could sample the OLD mtu as a
+	 * length bound against the NEW (smaller) buffer and overflow it. */
+	sc->sc_ifbuf = newbuf;
+	sc->sc_if.if_mtu = ifr->ifr_mtu;
 	if (ptr)
 	    kfree(ptr,M_DEVBUF);
-	sc->sc_if.if_mtu = ifr->ifr_mtu;
+    }
 	break;
 
     case SIOCGIFMTU: