Fix in6_pcbrtentry() for the case of IPv6-mapped IPv4 addresses:
don't assume that the cached route is a sockaddr_in6, and do the right comparisions so that no out-of-bounds memory is accessed. btw, the use of "#ifdef INET" throughout the source doesn't look clean to me: There are 2 cases -- whether AF_INET is usable by userland programs, and whether IPv4 is supported as on-wire protocol.
This commit is contained in:
parent
72ff826442
commit
e3e9b75351
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in6_pcb.c,v 1.89 2007/11/10 00:14:31 dyoung Exp $ */
|
||||
/* $NetBSD: in6_pcb.c,v 1.90 2007/11/21 21:18:25 drochner Exp $ */
|
||||
/* $KAME: in6_pcb.c,v 1.84 2001/02/08 18:02:08 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.89 2007/11/10 00:14:31 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.90 2007/11/21 21:18:25 drochner Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipsec.h"
|
||||
|
@ -903,20 +903,38 @@ struct rtentry *
|
|||
in6_pcbrtentry(struct in6pcb *in6p)
|
||||
{
|
||||
struct route *ro;
|
||||
const struct sockaddr_in6 *cdst;
|
||||
union {
|
||||
const struct sockaddr *sa;
|
||||
const struct sockaddr_in6 *sa6;
|
||||
#ifdef INET
|
||||
const struct sockaddr_in *sa4;
|
||||
#endif
|
||||
} cdst;
|
||||
|
||||
ro = &in6p->in6p_route;
|
||||
|
||||
if (in6p->in6p_af != AF_INET6)
|
||||
return (NULL);
|
||||
|
||||
cdst = (const struct sockaddr_in6 *)rtcache_getdst(ro);
|
||||
if (cdst == NULL)
|
||||
cdst.sa = rtcache_getdst(ro);
|
||||
if (cdst.sa == NULL)
|
||||
;
|
||||
else if (!IN6_ARE_ADDR_EQUAL(&cdst->sin6_addr, &in6p->in6p_faddr))
|
||||
rtcache_free(ro);
|
||||
else
|
||||
rtcache_check(ro);
|
||||
#ifdef INET
|
||||
else if (cdst.sa->sa_family == AF_INET) {
|
||||
KASSERT(IN6_IS_ADDR_V4MAPPED(&in6p->in6p_faddr));
|
||||
if (cdst.sa4->sin_addr.s_addr != in6p->in6p_faddr.s6_addr32[3])
|
||||
rtcache_free(ro);
|
||||
else
|
||||
rtcache_check(ro);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
if (!IN6_ARE_ADDR_EQUAL(&cdst.sa6->sin6_addr,
|
||||
&in6p->in6p_faddr))
|
||||
rtcache_free(ro);
|
||||
else
|
||||
rtcache_check(ro);
|
||||
}
|
||||
#ifdef INET
|
||||
if (ro->ro_rt == NULL && IN6_IS_ADDR_V4MAPPED(&in6p->in6p_faddr)) {
|
||||
union {
|
||||
|
|
Loading…
Reference in New Issue