Copy the scan results into a new buffer to re-align the data so that we
authorpatrick <patrick@openbsd.org>
Sun, 11 Feb 2018 05:33:12 +0000 (05:33 +0000)
committerpatrick <patrick@openbsd.org>
Sun, 11 Feb 2018 05:33:12 +0000 (05:33 +0000)
don't fault on strict alignment architectures.

sys/dev/ic/bwfm.c

index 3937dc3..8a2f1be 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bwfm.c,v 1.40 2018/02/11 05:13:07 patrick Exp $ */
+/* $OpenBSD: bwfm.c,v 1.41 2018/02/11 05:33:12 patrick Exp $ */
 /*
  * Copyright (c) 2010-2016 Broadcom Corporation
  * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se>
@@ -1973,22 +1973,33 @@ bwfm_rx_event_cb(struct bwfm_softc *sc, void *arg)
 
        switch (ntohl(e->msg.event_type)) {
        case BWFM_E_ESCAN_RESULT: {
-               struct bwfm_escan_results *res = (void *)&e[1];
+               struct bwfm_escan_results *res;
                struct bwfm_bss_info *bss;
+               size_t reslen;
                int i;
                if (ntohl(e->msg.status) != BWFM_E_STATUS_PARTIAL) {
                        ieee80211_end_scan(ifp);
                        break;
                }
                len -= sizeof(*e);
-               if (len < sizeof(*res) || len < letoh32(res->buflen)) {
+               if (len < sizeof(*res)) {
                        printf("%s: results too small\n", DEVNAME(sc));
                        m_freem(m);
                        return;
                }
+               reslen = len;
+               res = malloc(len, M_TEMP, M_WAITOK);
+               memcpy(res, (void *)&e[1], len);
+               if (len < letoh32(res->buflen)) {
+                       printf("%s: results too small\n", DEVNAME(sc));
+                       free(res, M_TEMP, reslen);
+                       m_freem(m);
+                       return;
+               }
                len -= sizeof(*res);
                if (len < letoh16(res->bss_count) * sizeof(struct bwfm_bss_info)) {
                        printf("%s: results too small\n", DEVNAME(sc));
+                       free(res, M_TEMP, reslen);
                        m_freem(m);
                        return;
                }
@@ -2000,6 +2011,7 @@ bwfm_rx_event_cb(struct bwfm_softc *sc, void *arg)
                        if (len <= 0)
                                break;
                }
+               free(res, M_TEMP, reslen);
                break;
                }
        case BWFM_E_SET_SSID: