From bb6f532983a1c44bbc031d6010a1ca82bb18db8b Mon Sep 17 00:00:00 2001 From: chuck Date: Thu, 11 Jul 1996 00:17:11 +0000 Subject: fixes: - don't try and add a PDU trailer (or TBD for that matter) to an M_EXT mbuf. when M_EXT is set, the data area of the mbuf can be shared with other mbufs (see m_copym()), and writing to one M_EXT mbuf may invalidate another M_EXT mbuf (saw this with PDU trailers). - be sure to validate the length value from the PDU trailer so that it doesn't throw us out of sync with the chip (fixes yet another source of the dread "en_service: id mismatch" panic). - on recv, don't bother allocating an mbuf if mlen is zero since we are only going to toss the data anyway. --- sys/dev/ic/midway.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'sys/dev') diff --git a/sys/dev/ic/midway.c b/sys/dev/ic/midway.c index 95b052eb1f2..e50d73d48d1 100644 --- a/sys/dev/ic/midway.c +++ b/sys/dev/ic/midway.c @@ -1,5 +1,5 @@ -/* $OpenBSD: midway.c,v 1.8 1996/07/03 17:21:19 chuck Exp $ */ -/* (sync'd to midway.c 1.57) */ +/* $OpenBSD: midway.c,v 1.9 1996/07/11 00:17:10 chuck Exp $ */ +/* (sync'd to midway.c 1.58) */ /* * @@ -1360,7 +1360,15 @@ struct ifnet *ifp; #endif #ifdef EN_MBUF_OPT - if (M_LEADINGSPACE(m) >= MID_TBD_SIZE) { + + /* + * note: external storage (M_EXT) can be shared between mbufs + * to avoid copying (see m_copym()). this means that the same + * data buffer could be shared by several mbufs, and thus it isn't + * a good idea to try and write TBDs or PDUs to M_EXT data areas. + */ + + if (M_LEADINGSPACE(m) >= MID_TBD_SIZE && (m->m_flags & M_EXT) == 0) { m->m_data -= MID_TBD_SIZE; m->m_len += MID_TBD_SIZE; mlen += MID_TBD_SIZE; @@ -1374,7 +1382,8 @@ struct ifnet *ifp; atm_flags |= EN_OBHDR; } - if (toadd && M_TRAILINGSPACE(lastm) >= toadd) { + if (toadd && (lastm->m_flags & M_EXT) == 0 && + M_TRAILINGSPACE(lastm) >= toadd) { cp = mtod(lastm, u_int8_t *) + lastm->m_len; lastm->m_len += toadd; mlen += toadd; @@ -2280,6 +2289,14 @@ defer: /* defer processing */ pdu -= (EN_RXSZ*1024); pdu = EN_READ(sc, pdu); /* READ swaps to proper byte order */ fill = tlen - MID_RBD_SIZE - MID_PDU_LEN(pdu); + if (fill < 0) { + printf("%s: invalid AAL5 PDU length detected, dropping frame\n", + sc->sc_dev.dv_xname); + printf("%s: got %d cells (%d bytes), AAL5 len is %d bytes (pdu=0x%x)\n", + sc->sc_dev.dv_xname, MID_RBD_CNT(rbd), tlen - MID_RBD_SIZE, + MID_PDU_LEN(pdu), pdu); + fill = tlen; + } mlen = tlen - fill; } @@ -2299,6 +2316,7 @@ defer: /* defer processing */ */ m = sc->rxslot[slot].q.ifq_head; + drqneed = 1; if (m) { sav = mtod(m, u_int32_t *); if (sav[0] != cur) { @@ -2319,7 +2337,7 @@ defer: /* defer processing */ } } - if (m == NULL) { + if (mlen != 0 && m == NULL) { m = en_mget(sc, mlen, &drqneed); /* allocate! */ if (m == NULL) { fill += mlen; -- cgit v1.2.3