Index: sys/netinet6/frag6.c
===================================================================
--- sys/netinet6/frag6.c
+++ sys/netinet6/frag6.c
@@ -66,6 +66,11 @@
 #include <netinet/in_systm.h>	/* for ECN definitions */
 #include <netinet/ip.h>		/* for ECN definitions */
 
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/sctp.h>
+#include <netinet/udp.h>
+
 #include <security/mac/mac_framework.h>
 
 /*
@@ -83,6 +88,8 @@
 static void frag6_remque(struct ip6q *, uint32_t bucket);
 static void frag6_freef(struct ip6q *, uint32_t bucket);
 
+static int ip6_validhdrchain(uint8_t, uint16_t);
+
 struct ip6qbucket {
 	struct ip6q	ip6q;
 	struct mtx	lock;
@@ -328,6 +335,20 @@
 		    )
 			break;
 
+	/*
+	 * If first fragment (frag offset is 0) doesn't have carry an upper
+	 * layer header drop it per RFC7112
+	 */
+	fragoff = ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK);
+	if (fragoff == 0 &&
+		!ip6_validhdrchain(ip6f->ip6f_nxt, frgpartlen)) {
+
+		/* remove any fragments that have arrived in this chain */
+		if (q6 != head)
+			frag6_freef(q6, hash);
+		goto dropfrag;
+	}
+
 	if (q6 == head) {
 		/*
 		 * the first fragment to arrive, create a reassembly queue.
@@ -382,7 +403,6 @@
 	 * If it's the 1st fragment, record the length of the
 	 * unfragmentable part and the next header of the fragment header.
 	 */
-	fragoff = ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK);
 	if (fragoff == 0) {
 		q6->ip6q_unfrglen = offset - sizeof(struct ip6_hdr) -
 		    sizeof(struct ip6_frag);
@@ -959,3 +979,43 @@
 	m->m_flags |= M_FRAGMENTED;
 	return (0);
 }
+
+/*
+ * Ensure that proto is an upper layer header and there is enough space for the
+ * upper layer header.
+ */
+static int
+ip6_validhdrchain(uint8_t proto, uint16_t length)
+{
+	switch (proto) {
+	case IPPROTO_ICMPV6:
+		if (length < sizeof(struct icmp6_hdr))
+			return 0;
+		return 1;
+	case IPPROTO_IPV6:
+		if (length < sizeof(struct ip6_hdr))
+			return 0;
+		return 1;
+	case IPPROTO_ESP:
+		if (length < sizeof(uint32_t))
+			return 0;
+		return 1;
+	case IPPROTO_SCTP:
+		if (length < sizeof(struct sctphdr))
+			return 0;
+		return 1;
+	case IPPROTO_TCP:
+		if (length < TCP_MAXHLEN)
+			return 0;
+		return 1;
+	case IPPROTO_UDP:
+	case IPPROTO_UDPLITE:
+		if (length < sizeof(struct udphdr))
+			return 0;
+		return 1;
+	default:
+		/* not a known upper layer protocol */
+		return 0;
+	}
+	return 0;
+}