From adbc1e472823ca8bdc1d8c5e724ce4d51f733c97 Mon Sep 17 00:00:00 2001 From: tholo Date: Sun, 26 Jan 1997 01:23:42 +0000 Subject: [PATCH] Make ip_len and ip_off unsigned values; don't transmit or accept packets larger than the maximum IP packet size. From NetBSD. --- sys/netinet/ip.h | 8 ++------ sys/netinet/ip_input.c | 10 ++++++++-- sys/netinet/ip_var.h | 13 +++++++------ sys/netinet/raw_ip.c | 10 +++++++++- sys/netinet/udp.h | 2 +- sys/netinet/udp_usrreq.c | 11 ++++++++++- 6 files changed, 37 insertions(+), 17 deletions(-) diff --git a/sys/netinet/ip.h b/sys/netinet/ip.h index 3214fb3f920..fb866314786 100644 --- a/sys/netinet/ip.h +++ b/sys/netinet/ip.h @@ -43,10 +43,6 @@ /* * Structure of an internet header, naked of options. - * - * We declare ip_len and ip_off to be short, rather than u_short - * pragmatically since otherwise unsigned comparisons can result - * against negative integers quite easily, and fail in subtle ways. */ struct ip { #if BYTE_ORDER == LITTLE_ENDIAN @@ -58,9 +54,9 @@ struct ip { ip_hl:4; /* header length */ #endif u_int8_t ip_tos; /* type of service */ - int16_t ip_len; /* total length */ + u_int16_t ip_len; /* total length */ u_int16_t ip_id; /* identification */ - int16_t ip_off; /* fragment offset field */ + u_int16_t ip_off; /* fragment offset field */ #define IP_RF 0x8000 /* reserved fragment flag */ #define IP_DF 0x4000 /* dont fragment flag */ #define IP_MF 0x2000 /* more fragments flag */ diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 89b2beb91be..2d8ab0bedb9 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.19 1996/10/27 00:47:33 deraadt Exp $ */ +/* $OpenBSD: ip_input.c,v 1.20 1997/01/26 01:23:43 tholo Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -569,10 +569,16 @@ insert: return (0); /* - * Reassembly is complete; concatenate fragments. + * Reassembly is complete. Check for a bogus message size and + * concatenate fragments. */ q = fp->ipq_fragq.lh_first; ip = q->ipqe_ip; + if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) { + ipstat.ips_toolong++; + ip_freef(fp); + return (0); + } m = dtom(q->ipqe_ip); t = m->m_next; m->m_next = 0; diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 7caed51f3e9..c79623bd0a8 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_var.h,v 1.3 1996/03/03 22:30:42 niklas Exp $ */ +/* $OpenBSD: ip_var.h,v 1.4 1997/01/26 01:23:44 tholo Exp $ */ /* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ /* @@ -42,11 +42,11 @@ * Overlay for ip header used by other protocols (tcp, udp). */ struct ipovly { - u_int8_t ih_x1[9]; /* (unused) */ - u_int8_t ih_pr; /* protocol */ - int16_t ih_len; /* protocol length */ - struct in_addr ih_src; /* source internet address */ - struct in_addr ih_dst; /* destination internet address */ + u_int8_t ih_x1[9]; /* (unused) */ + u_int8_t ih_pr; /* protocol */ + u_int16_t ih_len; /* protocol length */ + struct in_addr ih_src; /* source internet address */ + struct in_addr ih_dst; /* destination internet address */ }; /* @@ -144,6 +144,7 @@ struct ipstat { u_long ips_rawout; /* total raw ip packets generated */ u_long ips_badfrags; /* malformed fragments (bad length) */ u_long ips_rcvmemdrop; /* frags dropped for lack of memory */ + u_long ips_toolong; /* ip length > max ip packet size */ }; #ifdef _KERNEL diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index aaedb610567..97d641fddb4 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_ip.c,v 1.7 1996/08/14 20:19:20 deraadt Exp $ */ +/* $OpenBSD: raw_ip.c,v 1.8 1997/01/26 01:23:44 tholo Exp $ */ /* $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $ */ /* @@ -171,6 +171,10 @@ rip_output(m, va_alist) * Otherwise, allocate an mbuf for a header and fill it in. */ if ((inp->inp_flags & INP_HDRINCL) == 0) { + if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) { + m_freem(m); + return (EMSGSIZE); + } M_PREPEND(m, sizeof(struct ip), M_WAIT); ip = mtod(m, struct ip *); ip->ip_tos = 0; @@ -181,6 +185,10 @@ rip_output(m, va_alist) ip->ip_dst.s_addr = dst; ip->ip_ttl = MAXTTL; } else { + if (m->m_pkthdr.len > IP_MAXPACKET) { + m_freem(m); + return (EMSGSIZE); + } ip = mtod(m, struct ip *); /* * don't allow both user specified and setsockopt options, diff --git a/sys/netinet/udp.h b/sys/netinet/udp.h index c7964dfd30f..95bc044f7d9 100644 --- a/sys/netinet/udp.h +++ b/sys/netinet/udp.h @@ -42,6 +42,6 @@ struct udphdr { u_int16_t uh_sport; /* source port */ u_int16_t uh_dport; /* destination port */ - int16_t uh_ulen; /* udp length */ + u_int16_t uh_ulen; /* udp length */ u_int16_t uh_sum; /* udp checksum */ }; diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index f78e4be2d7f..31bdf858ac9 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.7 1996/07/05 20:42:18 deraadt Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.8 1997/01/26 01:23:46 tholo Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -460,6 +460,15 @@ udp_output(m, va_alist) goto bail; } + /* + * Compute the packet length of the IP header, and + * punt if the length looks bogus. + */ + if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) { + error = EMSGSIZE; + goto release; + } + /* * Fill in mbuf with extended UDP header * and addresses and length put into network format. -- 2.20.1