Improve input validation for raw IPv4 socket using the IP_HDRINCL
option. This issue was found by running syzkaller on OpenBSD. Greg Steuck made me aware that the problem might also exist on FreeBSD. Reported by: Greg Steuck MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D18834
This commit is contained in:
parent
1e690381ab
commit
6903958c2a
@ -454,6 +454,8 @@ rip_output(struct mbuf *m, struct socket *so, ...)
|
||||
u_long dst;
|
||||
int flags = ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0) |
|
||||
IP_ALLOWBROADCAST;
|
||||
int cnt;
|
||||
u_char opttype, optlen, *cp;
|
||||
|
||||
va_start(ap, so);
|
||||
dst = va_arg(ap, u_long);
|
||||
@ -528,6 +530,34 @@ rip_output(struct mbuf *m, struct socket *so, ...)
|
||||
m_freem(m);
|
||||
return (EINVAL);
|
||||
}
|
||||
/*
|
||||
* Don't allow IP options which do not have the required
|
||||
* structure as specified in section 3.1 of RFC 791 on
|
||||
* pages 15-23.
|
||||
*/
|
||||
cp = (u_char *)(ip + 1);
|
||||
cnt = (ip->ip_hl << 2) - sizeof (struct ip);
|
||||
for (; cnt > 0; cnt -= optlen, cp += optlen) {
|
||||
opttype = cp[IPOPT_OPTVAL];
|
||||
if (opttype == IPOPT_EOL)
|
||||
break;
|
||||
if (opttype == IPOPT_NOP) {
|
||||
optlen = 1;
|
||||
continue;
|
||||
}
|
||||
if (cnt < IPOPT_OLEN + sizeof(u_char)) {
|
||||
INP_RUNLOCK(inp);
|
||||
m_freem(m);
|
||||
return (EINVAL);
|
||||
}
|
||||
optlen = cp[IPOPT_OLEN];
|
||||
if (optlen < IPOPT_OLEN + sizeof(u_char) ||
|
||||
optlen > cnt) {
|
||||
INP_RUNLOCK(inp);
|
||||
m_freem(m);
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This doesn't allow application to specify ID of zero,
|
||||
* but we got this limitation from the beginning of history.
|
||||
|
Loading…
Reference in New Issue
Block a user