⬢ DragonFlyBSD Kernel Audit
DF-4763 / fix.diff
← back to finding ↓ download raw
# DF-4763 fix — check M_PREPEND(M_NOWAIT) failure in fwe_as_output()

NOT applied to sys/ (read-only audit tree). Authored after
source-level verification; not runtime-validated (no FireWire hardware
on the audit guest) — see VERDICT.md.

On failure M_PREPEND has already freed the chain and set m = NULL
(sys/sys/mbuf.h:465-482): return the dequeued xfer to the free list,
count the error, and continue with the next packet instead of
dereferencing NULL at if_fwe.c:509.

--- a/sys/dev/netif/fwe/if_fwe.c
+++ b/sys/dev/netif/fwe/if_fwe.c
@@ -504,10 +504,17 @@ fwe_as_output(struct fwe_softc *fwe, struct ifnet *ifp)
 		STAILQ_REMOVE_HEAD(&fwe->xferlist, link);
 		BPF_MTAP(ifp, m);
 
 		/* keep ip packet alignment for alpha */
 		M_PREPEND(m, ETHER_ALIGN, M_NOWAIT);
+		if (m == NULL) {
+			/* M_PREPEND(M_NOWAIT) freed the chain and returned
+			 * NULL; dereferencing m below would panic. */
+			IFNET_STAT_INC(ifp, oerrors, 1);
+			STAILQ_INSERT_TAIL(&fwe->xferlist, xfer, link);
+			continue;
+		}
 		fp = &xfer->send.hdr;
 		*(u_int32_t *)&xfer->send.hdr = *(int32_t *)&fwe->pkt_hdr;
 		fp->mode.stream.len = m->m_pkthdr.len;
 		xfer->mbuf = m;
 		xfer->send.pay_len = m->m_pkthdr.len;