Synopsis: IP options denial of service NetBSD versions: NetBSD 1.4.1 and before Thanks to: Jason Thorpe, Bill Sommerfeld Reported in NetBSD Security Advisory: SA2000-002 *** sys/netinet/ip.h.orig 1998/02/10 01:26:44 1.18 --- sys/netinet/ip.h 2000/05/05 03:06:42 1.18.8.1 *************** *** 68,74 **** u_int8_t ip_p; /* protocol */ u_int16_t ip_sum; /* checksum */ struct in_addr ip_src, ip_dst; /* source and dest address */ ! }; #define IP_MAXPACKET 65535 /* maximum packet size */ --- 68,74 ---- u_int8_t ip_p; /* protocol */ u_int16_t ip_sum; /* checksum */ struct in_addr ip_src, ip_dst; /* source and dest address */ ! } __attribute__((__packed__)); #define IP_MAXPACKET 65535 /* maximum packet size */ *************** *** 142,149 **** struct ipt_ta { struct in_addr ipt_addr; n_time ipt_time; ! } ipt_ta[1]; ! } ipt_timestamp; }; /* flag bits for ipt_flg */ --- 142,149 ---- struct ipt_ta { struct in_addr ipt_addr; n_time ipt_time; ! } ipt_ta[1] __attribute__((__packed__)); ! } ipt_timestamp __attribute__((__packed__)); }; /* flag bits for ipt_flg */ *** sys/netinet/ip_input.c.orig 2000/02/12 18:10:24 1.82.2.4 --- sys/netinet/ip_input.c 2000/05/06 16:43:25 1.82.2.6 *************** *** 856,866 **** struct mbuf *m; { register struct ip *ip = mtod(m, struct ip *); ! register u_char *cp; register struct ip_timestamp *ipt; register struct in_ifaddr *ia; int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; ! struct in_addr *sin, dst; n_time ntime; dst = ip->ip_dst; --- 856,866 ---- struct mbuf *m; { register struct ip *ip = mtod(m, struct ip *); ! register u_char *cp, *cp0; register struct ip_timestamp *ipt; register struct in_ifaddr *ia; int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; ! struct in_addr dst; n_time ntime; dst = ip->ip_dst; *************** *** 919,925 **** break; } off--; /* 0 origin */ ! if (off > optlen - sizeof(struct in_addr)) { /* * End of source route. Should be for us. */ --- 919,925 ---- break; } off--; /* 0 origin */ ! if ((off + sizeof(struct in_addr)) > optlen) { /* * End of source route. Should be for us. */ *************** *** 961,967 **** * If no space remains, ignore. */ off--; /* 0 origin */ ! if (off > optlen - sizeof(struct in_addr)) break; bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr, sizeof(ipaddr.sin_addr)); --- 961,967 ---- * If no space remains, ignore. */ off--; /* 0 origin */ ! if ((off + sizeof(struct in_addr)) > optlen) break; bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr, sizeof(ipaddr.sin_addr)); *************** *** 990,996 **** goto bad; break; } ! sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); switch (ipt->ipt_flg) { case IPOPT_TS_TSONLY: --- 990,996 ---- goto bad; break; } ! cp0 = (cp + ipt->ipt_ptr - 1); switch (ipt->ipt_flg) { case IPOPT_TS_TSONLY: *************** *** 1005,1012 **** m->m_pkthdr.rcvif); if (ia == 0) continue; ! bcopy((caddr_t)&ia->ia_addr.sin_addr, ! (caddr_t)sin, sizeof(struct in_addr)); ipt->ipt_ptr += sizeof(struct in_addr); break; --- 1005,1012 ---- m->m_pkthdr.rcvif); if (ia == 0) continue; ! bcopy(&ia->ia_addr.sin_addr, ! cp0, sizeof(struct in_addr)); ipt->ipt_ptr += sizeof(struct in_addr); break; *************** *** 1014,1020 **** if (ipt->ipt_ptr - 1 + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) goto bad; ! bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr, sizeof(struct in_addr)); if (ifa_ifwithaddr((SA)&ipaddr) == 0) continue; --- 1014,1020 ---- if (ipt->ipt_ptr - 1 + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) goto bad; ! bcopy(cp0, &ipaddr.sin_addr, sizeof(struct in_addr)); if (ifa_ifwithaddr((SA)&ipaddr) == 0) continue; *************** *** 1025,1031 **** goto bad; } ntime = iptime(); ! bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1, sizeof(n_time)); ipt->ipt_ptr += sizeof(n_time); } --- 1025,1032 ---- goto bad; } ntime = iptime(); ! cp0 = (u_char *) &ntime; /* XXX GCC BUG */ ! bcopy(cp0, (caddr_t)cp + ipt->ipt_ptr - 1, sizeof(n_time)); ipt->ipt_ptr += sizeof(n_time); }