From ca80e9cf3a1abc38b54e4aa4b95923cde9b9cd04 Mon Sep 17 00:00:00 2001 From: Pyun YongHyeon Date: Sun, 24 Oct 2010 21:14:01 +0000 Subject: MFC r213844: 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) --- sys/dev/age/if_age.c | 1 + sys/dev/alc/if_alc.c | 2 ++ sys/dev/ale/if_ale.c | 1 + sys/dev/bce/if_bce.c | 2 ++ sys/dev/bge/if_bge.c | 2 ++ sys/dev/fxp/if_fxp.c | 2 ++ sys/dev/jme/if_jme.c | 3 ++- sys/dev/sge/if_sge.c | 2 ++ 8 files changed, 14 insertions(+), 1 deletion(-) (limited to 'sys/dev') diff --git a/sys/dev/age/if_age.c b/sys/dev/age/if_age.c index 99c3c431a512..cd593ffa6295 100644 --- a/sys/dev/age/if_age.c +++ b/sys/dev/age/if_age.c @@ -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 diff --git a/sys/dev/alc/if_alc.c b/sys/dev/alc/if_alc.c index 10061f3e1b44..15505714fa0d 100644 --- a/sys/dev/alc/if_alc.c +++ b/sys/dev/alc/if_alc.c @@ -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)); diff --git a/sys/dev/ale/if_ale.c b/sys/dev/ale/if_ale.c index ea6b53b6ff97..eea21755250e 100644 --- a/sys/dev/ale/if_ale.c +++ b/sys/dev/ale/if_ale.c @@ -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) { diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c index 1272cd5f02e7..07885c3f9788 100644 --- a/sys/dev/bce/if_bce.c +++ b/sys/dev/bce/if_bce.c @@ -6733,6 +6733,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); @@ -6745,6 +6746,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; diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c index 8ed5bc607396..83e9e47199f9 100644 --- a/sys/dev/bge/if_bge.c +++ b/sys/dev/bge/if_bge.c @@ -3839,9 +3839,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 diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c index 079ecc1e82d9..6904d9ae9df2 100644 --- a/sys/dev/fxp/if_fxp.c +++ b/sys/dev/fxp/if_fxp.c @@ -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)); diff --git a/sys/dev/jme/if_jme.c b/sys/dev/jme/if_jme.c index 91642937c2c5..00a53d1958bd 100644 --- a/sys/dev/jme/if_jme.c +++ b/sys/dev/jme/if_jme.c @@ -1665,11 +1665,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, diff --git a/sys/dev/sge/if_sge.c b/sys/dev/sge/if_sge.c index e294edd4cb7a..e727d056023c 100644 --- a/sys/dev/sge/if_sge.c +++ b/sys/dev/sge/if_sge.c @@ -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; -- cgit v1.3