From: Roy Marples Date: Tue, 14 Feb 2017 22:13:17 +0000 (+0000) Subject: Copy out the inet6 address from some unaligned strucutures before using X-Git-Tag: v7.0.0-beta1~79 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7878d124cbda67f21cf684dbc674b37dc1fa55e4;p=thirdparty%2Fdhcpcd.git Copy out the inet6 address from some unaligned strucutures before using the data to avoid unaligned access. --- diff --git a/dhcp6.c b/dhcp6.c index 7f5bae2d..602d3c7b 100644 --- a/dhcp6.c +++ b/dhcp6.c @@ -1919,6 +1919,7 @@ dhcp6_findpd(struct interface *ifp, const uint8_t *iaid, uint8_t nb, *pw; uint16_t ol; struct dhcp6_pd_addr pdp; + struct in6_addr pdp_prefix; i = 0; state = D6_STATE(ifp); @@ -1949,8 +1950,10 @@ dhcp6_findpd(struct interface *ifp, const uint8_t *iaid, o += sizeof(pdp); ol = (uint16_t)(ol - sizeof(pdp)); + /* pdp.prefix is not aligned so copy it out. */ + memcpy(&pdp_prefix, &pdp.prefix, sizeof(pdp_prefix)); TAILQ_FOREACH(a, &state->addrs, next) { - if (IN6_ARE_ADDR_EQUAL(&a->prefix, &pdp.prefix)) + if (IN6_ARE_ADDR_EQUAL(&a->prefix, &pdp_prefix)) break; } @@ -1966,8 +1969,8 @@ dhcp6_findpd(struct interface *ifp, const uint8_t *iaid, a->dadcallback = dhcp6_dadcallback; a->ia_type = D6_OPTION_IA_PD; memcpy(a->iaid, iaid, sizeof(a->iaid)); - /* pdp.prefix is not aligned so copy it in. */ - memcpy(&a->prefix, &pdp.prefix, sizeof(a->prefix)); + /* pdp.prefix is not aligned so use copy. */ + a->prefix = pdp_prefix; a->prefix_len = pdp.prefix_len; ia = inet_ntop(AF_INET6, &a->prefix, iabuf, sizeof(iabuf)); diff --git a/ipv6nd.c b/ipv6nd.c index 06f79744..f3426330 100644 --- a/ipv6nd.c +++ b/ipv6nd.c @@ -741,6 +741,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, struct interface *ifp, char buf[INET6_ADDRSTRLEN]; const char *cbp; struct ra *rap; + struct in6_addr pi_prefix; struct ipv6_addr *ap; struct dhcp_opt *dho; uint8_t new_rap, new_data; @@ -935,8 +936,10 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, struct interface *ifp, ifp->name); continue; } - if (IN6_IS_ADDR_MULTICAST(&pi.nd_opt_pi_prefix) || - IN6_IS_ADDR_LINKLOCAL(&pi.nd_opt_pi_prefix)) + /* nd_opt_pi_prefix is not aligned. */ + memcpy(&pi_prefix, &pi.nd_opt_pi_prefix, sizeof(pi_prefix)); + if (IN6_IS_ADDR_MULTICAST(&pi_prefix) || + IN6_IS_ADDR_LINKLOCAL(&pi_prefix)) { logger(ifp->ctx, new_data ? LOG_ERR : LOG_DEBUG, "%s: invalid prefix in RA", ifp->name); @@ -951,8 +954,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, struct interface *ifp, } TAILQ_FOREACH(ap, &rap->addrs, next) if (ap->prefix_len ==pi.nd_opt_pi_prefix_len && - IN6_ARE_ADDR_EQUAL(&ap->prefix, - &pi.nd_opt_pi_prefix)) + IN6_ARE_ADDR_EQUAL(&ap->prefix, &pi_prefix)) break; if (ap == NULL) { if (!(pi.nd_opt_pi_flags_reserved & @@ -966,7 +968,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, struct interface *ifp, ap->iface = rap->iface; ap->flags = IPV6_AF_NEW; ap->prefix_len = pi.nd_opt_pi_prefix_len; - ap->prefix = pi.nd_opt_pi_prefix; + ap->prefix = pi_prefix; if (pi.nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO && ap->iface->options->options & @@ -1475,6 +1477,7 @@ ipv6nd_handlena(struct dhcpcd_ctx *ctx, struct interface *ifp, struct icmp6_hdr *icp, size_t len, int hoplimit) { struct nd_neighbor_advert *nd_na; + struct in6_addr nd_na_target; struct ra *rap; uint32_t is_router, is_solicited; char buf[INET6_ADDRSTRLEN]; @@ -1507,7 +1510,9 @@ ipv6nd_handlena(struct dhcpcd_ctx *ctx, struct interface *ifp, taddr = inet_ntop(AF_INET6, &nd_na->nd_na_target, buf, INET6_ADDRSTRLEN); - if (IN6_IS_ADDR_MULTICAST(&nd_na->nd_na_target)) { + /* nd_na->nd_na_target is not aligned. */ + memcpy(&nd_na_target, &nd_na->nd_na_target, sizeof(nd_na_target)); + if (IN6_IS_ADDR_MULTICAST(&nd_na_target)) { logger(ifp->ctx, LOG_ERR, "%s: NA multicast address %s (%s)", ifp->name, taddr, ctx->sfrom); return; @@ -1515,7 +1520,7 @@ ipv6nd_handlena(struct dhcpcd_ctx *ctx, struct interface *ifp, TAILQ_FOREACH(rap, ctx->ra_routers, next) { if (rap->iface == ifp && - IN6_ARE_ADDR_EQUAL(&rap->from, &nd_na->nd_na_target)) + IN6_ARE_ADDR_EQUAL(&rap->from, &nd_na_target)) break; } if (rap == NULL) {