Make sure to not use stale ip/tcp header pointers. The ip/tcp

header parser uses m_pullup(9) to get access to mbuf chain.
m_pullup(9) can allocate new mbuf chain and free old one if the
space left in the mbuf chain is not enough to hold requested
contiguous bytes. Previously drivers can use stale ip/tcp header
pointer if m_pullup(9) returned new mbuf chain.

Reported by:	Andrew Boyer (aboyer <> averesystems dot com)
MFC after:	10 days
This commit is contained in:
Pyun YongHyeon 2010-10-14 18:31:40 +00:00
parent cb2f3e7f9b
commit 96486faa6e
8 changed files with 14 additions and 1 deletions

View File

@ -1565,6 +1565,7 @@ age_encap(struct age_softc *sc, struct mbuf **m_head)
*m_head = NULL;
return (ENOBUFS);
}
ip = (struct ip *)(mtod(m, char *) + ip_off);
tcp = (struct tcphdr *)(mtod(m, char *) + poff);
/*
* L1 requires IP/TCP header size and offset as

View File

@ -2104,6 +2104,8 @@ alc_encap(struct alc_softc *sc, struct mbuf **m_head)
* Reset IP checksum and recompute TCP pseudo
* checksum as NDIS specification said.
*/
ip = (struct ip *)(mtod(m, char *) + ip_off);
tcp = (struct tcphdr *)(mtod(m, char *) + poff);
ip->ip_sum = 0;
tcp->th_sum = in_pseudo(ip->ip_src.s_addr,
ip->ip_dst.s_addr, htons(IPPROTO_TCP));

View File

@ -1677,6 +1677,7 @@ ale_encap(struct ale_softc *sc, struct mbuf **m_head)
*m_head = NULL;
return (ENOBUFS);
}
ip = (struct ip *)(mtod(m, char *) + ip_off);
tcp = (struct tcphdr *)(mtod(m, char *) + poff);
m = m_pullup(m, poff + (tcp->th_off << 2));
if (m == NULL) {

View File

@ -6736,6 +6736,7 @@ bce_tso_setup(struct bce_softc *sc, struct mbuf **m_head, u16 *flags)
}
/* Get the TCP header length in bytes (min 20) */
ip = (struct ip *)(m->m_data + sizeof(struct ether_header));
th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
tcp_hlen = (th->th_off << 2);
@ -6748,6 +6749,7 @@ bce_tso_setup(struct bce_softc *sc, struct mbuf **m_head, u16 *flags)
}
/* IP header length and checksum will be calc'd by hardware */
ip = (struct ip *)(m->m_data + sizeof(struct ether_header));
ip_len = ip->ip_len;
ip->ip_len = 0;
ip->ip_sum = 0;

View File

@ -4097,9 +4097,11 @@ bge_setup_tso(struct bge_softc *sc, struct mbuf *m, uint16_t *mss)
* checksum. These checksum computed by upper stack should be 0.
*/
*mss = m->m_pkthdr.tso_segsz;
ip = (struct ip *)(mtod(m, char *) + sizeof(struct ether_header));
ip->ip_sum = 0;
ip->ip_len = htons(*mss + (ip->ip_hl << 2) + (tcp->th_off << 2));
/* Clear pseudo checksum computed by TCP stack. */
tcp = (struct tcphdr *)(mtod(m, char *) + poff);
tcp->th_sum = 0;
/*
* Broadcom controllers uses different descriptor format for

View File

@ -1454,6 +1454,8 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head)
* Since 82550/82551 doesn't modify IP length and pseudo
* checksum in the first frame driver should compute it.
*/
ip = (struct ip *)(mtod(m, char *) + ip_off);
tcp = (struct tcphdr *)(mtod(m, char *) + poff);
ip->ip_sum = 0;
ip->ip_len = htons(m->m_pkthdr.tso_segsz + (ip->ip_hl << 2) +
(tcp->th_off << 2));

View File

@ -1657,11 +1657,12 @@ jme_encap(struct jme_softc *sc, struct mbuf **m_head)
*m_head = NULL;
return (ENOBUFS);
}
tcp = (struct tcphdr *)(mtod(m, char *) + poff);
/*
* Reset IP checksum and recompute TCP pseudo
* checksum that NDIS specification requires.
*/
ip = (struct ip *)(mtod(m, char *) + ip_off);
tcp = (struct tcphdr *)(mtod(m, char *) + poff);
ip->ip_sum = 0;
if (poff + (tcp->th_off << 2) == m->m_pkthdr.len) {
tcp->th_sum = in_pseudo(ip->ip_src.s_addr,

View File

@ -1457,7 +1457,9 @@ sge_encap(struct sge_softc *sc, struct mbuf **m_head)
* Reset IP checksum and recompute TCP pseudo
* checksum that NDIS specification requires.
*/
ip = (struct ip *)(mtod(m, char *) + ip_off);
ip->ip_sum = 0;
tcp = (struct tcphdr *)(mtod(m, char *) + poff);
tcp->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
htons(IPPROTO_TCP));
*m_head = m;