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);
}