Page MenuHomeFreeBSD

D16851.id48828.diff
No OneTemporary

D16851.id48828.diff

Index: sys/netinet/dccp.h
===================================================================
--- /dev/null
+++ sys/netinet/dccp.h
@@ -0,0 +1,50 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018 Tom Jones <thj@freebsd.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _NETINET_DCCP_H_
+#define _NETINET_DCCP_H_
+
+__FBSDID("$FreeBSD$");
+
+/* DCCP protocol header as per RFC4340 */
+struct dccphdr {
+ uint16_t d_sport;
+ uint16_t d_dport;
+ uint8_t d_doff;
+ uint8_t d_ccval;
+ uint16_t d_cksum;
+ uint8_t d_extseq;
+ uint8_t d_seq[6];
+};
+
+#define IPPROTO_DCCP 33
+#define DCCP_SHORTHDR 12
+#define DCCP_LONGHDR 16
+#define DCCP_EXTHDR 0x80
+
+#endif /* _NETINET_DCCP_H */
Index: sys/netinet6/frag6.c
===================================================================
--- sys/netinet6/frag6.c
+++ sys/netinet6/frag6.c
@@ -66,6 +66,13 @@
#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 <netinet/dccp.h>
+#include <net/if_gre.h>
+
#include <security/mac/mac_framework.h>
/*
@@ -328,6 +335,20 @@
)
break;
+ /*
+ * If first fragment (frag offset is 0) doesn't have contain an upper
+ * layer header drop it per RFC7112.
+ */
+ fragoff = ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK);
+ if (fragoff == 0 &&
+ !ip6_validhdrchain(m, offset, ip6f->ip6f_nxt, frgpartlen)) {
+
+ /* remove any fragments that have arrived */
+ 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,72 @@
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.
+ */
+int
+ip6_validhdrchain(struct mbuf *m, int offset, uint8_t proto, uint16_t length)
+{
+ uint16_t hdrlen = 0;
+ struct tcphdr *tp;
+ struct iphdr *ip;
+ struct dccphdr *dccp;
+
+ 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 < sizeof(struct tcphdr))
+ return 0;
+ tp = (struct tcphdr *)m;
+ hdrlen = tp->th_off << 2;
+ if (length < hdrlen)
+ return 0;
+ return 1;
+ case IPPROTO_UDP:
+ case IPPROTO_UDPLITE:
+ if (length < sizeof(struct udphdr))
+ return 0;
+ return 1;
+ case IPPROTO_DCCP:
+ if (length < DCCP_SHORTHDR)
+ return 0;
+ dccp = (struct dccphdr *)m;
+ hdrlen = dccp->d_extseq;
+ if (hdrlen & DCCP_EXTHDR && length < DCCP_LONGHDR)
+ return 0;
+ return 1;
+ case IPPROTO_IP:
+ if (length < sizeof(struct ip))
+ return 0;
+ ip = (struct iphdr *)m;
+ hdrlen = hdrlen << 2;
+ if (length < hdrlen)
+ return 0;
+ return 1;
+ case IPPROTO_GRE:
+ if (length < sizeof(struct grehdr))
+ return 0;
+ return 1;
+ default:
+ /* not a known upper layer protocol */
+ return 0;
+ }
+ return 0;
+}
Index: sys/netinet6/ip6_var.h
===================================================================
--- sys/netinet6/ip6_var.h
+++ sys/netinet6/ip6_var.h
@@ -402,6 +402,7 @@
struct ip6_pktopts *ip6_copypktopts(struct ip6_pktopts *, int);
int ip6_optlen(struct inpcb *);
int ip6_deletefraghdr(struct mbuf *, int, int);
+int ip6_validhdrchain(struct mbuf *, int, uint8_t, uint16_t);
int ip6_fragment(struct ifnet *, struct mbuf *, int, u_char, int,
uint32_t);

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 31, 12:51 AM (8 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16349644
Default Alt Text
D16851.id48828.diff (5 KB)

Event Timeline