diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2011-10-21 15:45:56 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2011-10-21 15:45:56 +0000 |
commit | ab52f437470f82127e4526429af1c0289187b834 (patch) | |
tree | 8e17279ae32d6f5b3a452a19e6ebdddb69d1fd9e | |
parent | 41aaaeaecbb5e1b5703dd28e705b539385627016 (diff) |
strengthen some checks to prevent m_copy* routines from operating
on mbuf chains of insufficient length; prevents crashes seen by
dhill. also bring in some chunks omitted in the nat64 commit and
are essential for correct packet interpretation.
tested by dhill and me, ok henning
-rw-r--r-- | sys/net/if_pflog.c | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/sys/net/if_pflog.c b/sys/net/if_pflog.c index f8ae8be545d..3ea408aa6d4 100644 --- a/sys/net/if_pflog.c +++ b/sys/net/if_pflog.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pflog.c,v 1.44 2011/10/13 18:23:39 claudio Exp $ */ +/* $OpenBSD: if_pflog.c,v 1.45 2011/10/21 15:45:55 mikeb Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -296,6 +296,7 @@ pflog_bpfcopy(const void *src_arg, void *dst_arg, size_t len) struct pf_pdesc pd; struct pf_addr osaddr, odaddr; u_int16_t osport = 0, odport = 0; + u_int8_t proto = 0; m = (struct mbuf *)src_arg; dst = dst_arg; @@ -340,33 +341,46 @@ pflog_bpfcopy(const void *src_arg, void *dst_arg, size_t len) case AF_INET: { struct ip *h; + if (m->m_pkthdr.len < sizeof(*h)) + return; m_copydata(m, 0, sizeof(*h), mdst); h = (struct ip *)mdst; hlen = h->ip_hl << 2; - if (hlen > sizeof(*h)) + if (hlen > sizeof(*h) && (m->m_pkthdr.len >= hlen)) m_copydata(m, sizeof(*h), hlen - sizeof(*h), mdst + sizeof(*h)); break; } case AF_INET6: { + struct ip6_hdr *h; + + if (m->m_pkthdr.len < sizeof(*h)) + return; hlen = sizeof(struct ip6_hdr); m_copydata(m, 0, hlen, mdst); + h = (struct ip6_hdr *)mdst; + proto = h->ip6_nxt; break; } default: /* shouldn't happen ever :-) */ - m_copydata(m, 0, len, dst); + m_copydata(m, 0, min(len, m->m_pkthdr.len), dst); return; } - /* copy 8 bytes of the protocol header */ - m_copydata(m, hlen, 8, mdst + hlen); + if (m->m_pkthdr.len < hlen + 8 && proto != IPPROTO_NONE) + return; + else if (proto != IPPROTO_NONE) { + /* copy 8 bytes of the protocol header */ + m_copydata(m, hlen, 8, mdst + hlen); + hlen += 8; + } - mhdr->m_len += hlen + 8; + mhdr->m_len += hlen; mhdr->m_pkthdr.len = mhdr->m_len; - /* create a chain mhdr -> mptr, mptr->m_data = (m->m_data+hlen+8) */ - mp = m_getptr(m, hlen + 8, &off); + /* create a chain mhdr -> mptr, mptr->m_data = (m->m_data+hlen) */ + mp = m_getptr(m, hlen, &off); if (mp != NULL) { bcopy(mp, mptr, sizeof(*mptr)); cp = mtod(mp, char *); @@ -374,7 +388,7 @@ pflog_bpfcopy(const void *src_arg, void *dst_arg, size_t len) mptr->m_len -= off; mptr->m_flags &= ~M_PKTHDR; mhdr->m_next = mptr; - mhdr->m_pkthdr.len += m->m_pkthdr.len - (hlen + 8); + mhdr->m_pkthdr.len += m->m_pkthdr.len - hlen; } /* rewrite addresses if needed */ @@ -405,9 +419,15 @@ pflog_bpfcopy(const void *src_arg, void *dst_arg, size_t len) pfloghdr->dport = odport; } + pd.tot_len = min(pd.tot_len, len); + pd.tot_len -= pd.m->m_data - pd.m->m_pktdat; + if (afto) pf_translate_af(&pd); mlen = min(pd.m->m_pkthdr.len, len); m_copydata(pd.m, 0, mlen, dst); + len -= mlen; + if (len > 0) + bzero(dst + mlen, len); } |