diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2011-09-21 19:07:31 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2011-09-21 19:07:31 +0000 |
commit | 6287503c0728d297aa9bd6fc227c07f86d5879a6 (patch) | |
tree | 44bc312d330c5955aa44bfa5a6e3e53abe93b4a7 /sys | |
parent | e87b51bed54409a1df9b9b74398545e33404322c (diff) |
Check the protocol header length for tcp, udp, icmp, icmp6 in
pf_setup_pdesc(). It is better to check and bail out early than
to rely on pf_pull_hdr() later.
ok henning mpf
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/pf.c | 20 | ||||
-rw-r--r-- | sys/net/pf_norm.c | 6 | ||||
-rw-r--r-- | sys/net/pf_osfp.c | 4 |
3 files changed, 21 insertions, 9 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c index fab59f4a822..ea5895e8357 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.779 2011/09/20 15:17:26 bluhm Exp $ */ +/* $OpenBSD: pf.c,v 1.780 2011/09/21 19:07:30 bluhm Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -5718,6 +5718,12 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pfi_kif *kif, action, reason, pd->af)) return (-1); pd->hdrlen = sizeof(*th); + if (pd->off + (th->th_off << 2) > pd->tot_len || + (th->th_off << 2) < sizeof(struct tcphdr)) { + *action = PF_DROP; + REASON_SET(reason, PFRES_SHORT); + return (-1); + } pd->p_len = pd->tot_len - pd->off - (th->th_off << 2); pd->sport = &th->th_sport; pd->dport = &th->th_dport; @@ -5731,7 +5737,7 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pfi_kif *kif, return (-1); pd->hdrlen = sizeof(*uh); if (uh->uh_dport == 0 || - ntohs(uh->uh_ulen) > m->m_pkthdr.len - pd->off || + pd->off + ntohs(uh->uh_ulen) > pd->tot_len || ntohs(uh->uh_ulen) < sizeof(struct udphdr)) { *action = PF_DROP; REASON_SET(reason, PFRES_SHORT); @@ -5746,6 +5752,11 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pfi_kif *kif, action, reason, pd->af)) return (-1); pd->hdrlen = ICMP_MINLEN; + if (pd->off + pd->hdrlen > pd->tot_len) { + *action = PF_DROP; + REASON_SET(reason, PFRES_SHORT); + return (-1); + } break; } #ifdef INET6 @@ -5771,6 +5782,11 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pfi_kif *kif, action, reason, pd->af)) return (-1); pd->hdrlen = icmp_hlen; + if (pd->off + pd->hdrlen > pd->tot_len) { + *action = PF_DROP; + REASON_SET(reason, PFRES_SHORT); + return (-1); + } break; } #endif /* INET6 */ diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c index f0602fe581b..6134c88c81c 100644 --- a/sys/net/pf_norm.c +++ b/sys/net/pf_norm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_norm.c,v 1.143 2011/09/20 10:51:18 bluhm Exp $ */ +/* $OpenBSD: pf_norm.c,v 1.144 2011/09/21 19:07:30 bluhm Exp $ */ /* * Copyright 2001 Niels Provos <provos@citi.umich.edu> @@ -835,10 +835,6 @@ pf_normalize_tcp(struct mbuf *m, struct pf_pdesc *pd) goto tcp_drop; } - /* Check for illegal header length */ - if (th->th_off < (sizeof(struct tcphdr) >> 2)) - goto tcp_drop; - /* If flags changed, or reserved data set, then adjust */ if (flags != th->th_flags || th->th_x2 != 0) { u_int16_t ov, nv; diff --git a/sys/net/pf_osfp.c b/sys/net/pf_osfp.c index 21d49b523e9..514b6c2a1c3 100644 --- a/sys/net/pf_osfp.c +++ b/sys/net/pf_osfp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_osfp.c,v 1.23 2011/09/20 15:17:26 bluhm Exp $ */ +/* $OpenBSD: pf_osfp.c,v 1.24 2011/09/21 19:07:30 bluhm Exp $ */ /* * Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org> @@ -89,7 +89,7 @@ pf_osfp_fingerprint(struct pf_pdesc *pd, struct mbuf *m) struct ip6_hdr *ip6 = NULL; char hdr[60]; - if (pd->proto != IPPROTO_TCP || (th->th_off << 2) < sizeof(*th)) + if (pd->proto != IPPROTO_TCP) return (NULL); switch (pd->af) { |