diff options
author | kp <kp@FreeBSD.org> | 2017-04-20 09:05:53 +0000 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2017-04-20 09:30:28 -0300 |
commit | 539d8571ccbd8999cc55736a3adb1c412cd21a5b (patch) | |
tree | 68a2bb297283e04b22eca9fb15403dc97bf61b12 | |
parent | 26e03fe8d578308454f0b67ed90452003ceb1e31 (diff) | |
download | FreeBSD-src-539d8571ccbd8999cc55736a3adb1c412cd21a5b.zip FreeBSD-src-539d8571ccbd8999cc55736a3adb1c412cd21a5b.tar.gz |
pf: Fix possible incorrect IPv6 fragmentationRELENG_2_3_3
When forwarding pf tracks the size of the largest fragment in a fragmented
packet, and refragments based on this size.
It failed to ensure that this size was a multiple of 8 (as is required for all
but the last fragment), so it could end up generating incorrect fragments.
For example, if we received an 8 byte and 12 byte fragment pf would emit a first
fragment with 12 bytes of payload and the final fragment would claim to be at
offset 8 (not 12).
We now assert that the fragment size is a multiple of 8 in ip6_fragment(), so
other users won't make the same mistake.
Reported by: Antonios Atlasis <aatlasis at secfu net>
MFC after: 3 days
(cherry picked from commit 4f3397263b95a45dd58e2be3a566029f8841cace)
-rw-r--r-- | sys/netinet6/ip6_output.c | 2 | ||||
-rw-r--r-- | sys/netpfil/pf/pf_norm.c | 4 |
2 files changed, 6 insertions, 0 deletions
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index 09eab20..7af04b0 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -219,6 +219,8 @@ ip6_fragment(struct ifnet *ifp, struct mbuf *m0, int hlen, u_char nextproto, int error; int tlen = m0->m_pkthdr.len; + KASSERT(( mtu % 8 == 0), ("Fragment length must be a multiple of 8")); + m = m0; ip6 = mtod(m, struct ip6_hdr *); mnext = &m->m_nextpkt; diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c index 3559909..ead119f 100644 --- a/sys/netpfil/pf/pf_norm.c +++ b/sys/netpfil/pf/pf_norm.c @@ -1128,6 +1128,10 @@ pf_refragment6(struct ifnet *ifp, struct mbuf **m0, struct m_tag *mtag) hdr->ip6_nxt = IPPROTO_FRAGMENT; } + /* The MTU must be a multiple of 8 bytes, or we risk doing the + * fragmentation wrong. */ + maxlen = maxlen & ~7; + /* * Maxlen may be less than 8 if there was only a single * fragment. As it was fragmented before, add a fragment |