Add padding between odhcp6c_entry structures to ensure 32-bit alignment
authorBen Hutchings <ben@decadent.org.uk>
Thu, 28 Jan 2016 04:33:48 +0000 (04:33 +0000)
committerBen Hutchings <ben@decadent.org.uk>
Thu, 28 Jan 2016 15:46:56 +0000 (15:46 +0000)
struct odhcp6c_entry is not declared as __packed, so the compiler may
assume it is naturally aligned.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
src/odhcp6c.c
src/odhcp6c.h
src/ra.c
src/script.c

index 59f6390..ba568bd 100644 (file)
@@ -570,8 +570,9 @@ static struct odhcp6c_entry* odhcp6c_find_entry(enum odhcp6c_state state, const
        uint8_t *start = odhcp6c_get_state(state, &len);
 
        for (struct odhcp6c_entry *c = (struct odhcp6c_entry*)start;
-                       (uint8_t*)c < &start[len] && &c->auxtarget[c->auxlen] <= &start[len];
-                       c = (struct odhcp6c_entry*)(&c->auxtarget[c->auxlen]))
+                       (uint8_t*)c < &start[len] &&
+                       (uint8_t*)odhcp6c_next_entry(c) <= &start[len];
+                       c = odhcp6c_next_entry(c))
                if (!memcmp(c, new, cmplen) && !memcmp(c->auxtarget, new->auxtarget, new->auxlen))
                        return c;
 
@@ -604,10 +605,10 @@ bool odhcp6c_update_entry(enum odhcp6c_state state, struct odhcp6c_entry *new,
                        x->t2 = new->t2;
                        x->iaid = new->iaid;
                } else {
-                       odhcp6c_add_state(state, new, sizeof(*new) + new->auxlen);
+                       odhcp6c_add_state(state, new, odhcp6c_entry_size(new));
                }
        } else if (x) {
-               odhcp6c_remove_state(state, ((uint8_t*)x) - start, sizeof(*x) + x->auxlen);
+               odhcp6c_remove_state(state, ((uint8_t*)x) - start, odhcp6c_entry_size(x));
        }
        return true;
 }
@@ -618,7 +619,8 @@ static void odhcp6c_expire_list(enum odhcp6c_state state, uint32_t elapsed)
        size_t len;
        uint8_t *start = odhcp6c_get_state(state, &len);
        for (struct odhcp6c_entry *c = (struct odhcp6c_entry*)start;
-                       (uint8_t*)c < &start[len] && &c->auxtarget[c->auxlen] <= &start[len];
+                       (uint8_t*)c < &start[len] &&
+                       (uint8_t*)odhcp6c_next_entry(c) <= &start[len];
                        ) {
                if (c->t1 < elapsed)
                        c->t1 = 0;
@@ -641,10 +643,10 @@ static void odhcp6c_expire_list(enum odhcp6c_state state, uint32_t elapsed)
                        c->valid -= elapsed;
 
                if (!c->valid) {
-                       odhcp6c_remove_state(state, ((uint8_t*)c) - start, sizeof(*c) + c->auxlen);
+                       odhcp6c_remove_state(state, ((uint8_t*)c) - start, odhcp6c_entry_size(c));
                        start = odhcp6c_get_state(state, &len);
                } else {
-                       c = (struct odhcp6c_entry*)(&c->auxtarget[c->auxlen]);
+                       c = odhcp6c_next_entry(c);
                }
        }
 }
index 928f82f..98d91dd 100644 (file)
@@ -302,6 +302,14 @@ struct odhcp6c_entry {
        uint8_t auxtarget[];
 };
 
+// Include padding after auxtarget to align the next entry
+#define odhcp6c_entry_size(entry) \
+       (sizeof(struct odhcp6c_entry) + (((entry)->auxlen + 3) & ~3))
+
+#define odhcp6c_next_entry(entry) \
+       ((struct odhcp6c_entry *)((uint8_t *)(entry) + odhcp6c_entry_size(entry)))
+
+
 struct odhcp6c_request_prefix {
        uint32_t iaid;
        uint16_t length;
index 1c121e6..2d442f6 100644 (file)
--- a/src/ra.c
+++ b/src/ra.c
@@ -444,8 +444,9 @@ bool ra_process(void)
                        size_t ra_dns_len;
                        uint8_t *start = odhcp6c_get_state(states[i], &ra_dns_len);
                        for (struct odhcp6c_entry *c = (struct odhcp6c_entry*)start;
-                                               (uint8_t*)c < &start[ra_dns_len] && &c->auxtarget[c->auxlen] <= &start[ra_dns_len];
-                                               c = (struct odhcp6c_entry*)(&c->auxtarget[c->auxlen]))
+                                               (uint8_t*)c < &start[ra_dns_len] &&
+                                               (uint8_t*)odhcp6c_next_entry(c) <= &start[ra_dns_len];
+                                               c = odhcp6c_next_entry(c))
                                if (IN6_ARE_ADDR_EQUAL(&c->router, &from.sin6_addr) &&
                                                c->valid > router_valid)
                                        c->valid = router_valid;
index 1533510..72add21 100644 (file)
@@ -220,8 +220,9 @@ static void search_to_env(const char *name, const uint8_t *start, size_t len)
        *c++ = '=';
 
        for (struct odhcp6c_entry *e = (struct odhcp6c_entry*)start;
-                               (uint8_t*)e < &start[len] && &e->auxtarget[e->auxlen] <= &start[len];
-                               e = (struct odhcp6c_entry*)(&e->auxtarget[e->auxlen])) {
+                               (uint8_t*)e < &start[len] &&
+                               (uint8_t*)odhcp6c_next_entry(e) <= &start[len];
+                               e = odhcp6c_next_entry(e)) {
                c = mempcpy(c, e->auxtarget, e->auxlen);
                *c++ = ' ';
        }