summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkp <kp@FreeBSD.org>2017-04-20 09:05:53 +0000
committerRenato Botelho <renato@netgate.com>2017-04-20 09:30:10 -0300
commit1d2c919ef6b6d7b9e78890cea95a129a17d61930 (patch)
tree5525dce39d921bf29c659b614d08f6d8e4a62e34
parent8ad574a269c9a3d960c70c5b765f9f6dc85eaab7 (diff)
downloadFreeBSD-src-1d2c919ef6b6d7b9e78890cea95a129a17d61930.zip
FreeBSD-src-1d2c919ef6b6d7b9e78890cea95a129a17d61930.tar.gz
pf: Fix possible incorrect IPv6 fragmentation
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.c2
-rw-r--r--sys/netpfil/pf/pf_norm.c4
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
OpenPOWER on IntegriCloud