]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Copy out the inet6 address from some unaligned strucutures before using
authorRoy Marples <roy@marples.name>
Tue, 14 Feb 2017 22:13:17 +0000 (22:13 +0000)
committerRoy Marples <roy@marples.name>
Tue, 14 Feb 2017 22:13:17 +0000 (22:13 +0000)
the data to avoid unaligned access.

dhcp6.c
ipv6nd.c

diff --git a/dhcp6.c b/dhcp6.c
index 7f5bae2d9f18a242a007e8fa9492ebf56d2dff09..602d3c7b49e40d983bea77b9bd55aae0a2aee4a9 100644 (file)
--- 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));
index 06f797440d90d2448d9a617e3ea99ff69af0f473..f3426330ce92dd46e0f38775a4c95b7d838cd5c1 100644 (file)
--- 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) {