diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 8c3f0f6..5e33262 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -813,7 +813,7 @@ extern int dhd_net2idx(struct dhd_info *dhd, struct net_device *net); extern struct net_device * dhd_idx2net(void *pub, int ifidx); extern int net_os_send_hang_message(struct net_device *dev); -extern int wl_host_event(dhd_pub_t *dhd_pub, int *idx, void *pktdata, +extern int wl_host_event(dhd_pub_t *dhd_pub, int *idx, void *pktdata, size_t pktlen, wl_event_msg_t *, void **data_ptr, void *); extern void wl_event_to_host_order(wl_event_msg_t * evt); diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index 8a6882f..201a0ac 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -109,7 +109,7 @@ extern int dhd_socram_dump(struct dhd_bus *bus); #ifdef DNGL_EVENT_SUPPORT static void dngl_host_event_process(dhd_pub_t *dhdp, bcm_dngl_event_t *event); -static int dngl_host_event(dhd_pub_t *dhdp, void *pktdata); +static int dngl_host_event(dhd_pub_t *dhdp, void *pktdata, size_t pktlen); #endif /* DNGL_EVENT_SUPPORT */ bool ap_cfg_running = FALSE; bool ap_fw_loaded = FALSE; @@ -1380,7 +1380,7 @@ #ifdef DNGL_EVENT_SUPPORT /* Check whether packet is a BRCM dngl event pkt. If it is, process event data. */ int -dngl_host_event(dhd_pub_t *dhdp, void *pktdata) +dngl_host_event(dhd_pub_t *dhdp, void *pktdata, size_t pktlen) { bcm_dngl_event_t *pvt_data = (bcm_dngl_event_t *)pktdata; @@ -1391,14 +1391,14 @@ /* Check to see if this is a DNGL event */ if (ntoh16_ua((void *)&pvt_data->bcm_hdr.usr_subtype) == BCMILCP_BCM_SUBTYPE_DNGLEVENT) { - dngl_host_event_process(dhdp, pvt_data); + dngl_host_event_process(dhdp, pvt_data, pktlen); return BCME_OK; } return BCME_ERROR; } void -dngl_host_event_process(dhd_pub_t *dhdp, bcm_dngl_event_t *event) +dngl_host_event_process(dhd_pub_t *dhdp, bcm_dngl_event_t *event, size_t pktlen) { bcm_dngl_event_msg_t *dngl_event = &event->dngl_event; uint8 *p = (uint8 *)(event + 1); @@ -1407,6 +1407,9 @@ uint16 version = ntoh16_ua((void *)&dngl_event->version); DHD_EVENT(("VERSION:%d, EVENT TYPE:%d, DATALEN:%d\n", version, type, datalen)); + if (datalen > (pktlen - sizeof(bcm_event_t))) { + return; + } if (version != BCM_DNGL_EVENT_MSG_VERSION) { DHD_ERROR(("%s:version mismatch:%d:%d\n", __FUNCTION__, version, BCM_DNGL_EVENT_MSG_VERSION)); @@ -1499,7 +1502,7 @@ } #endif /* DNGL_EVENT_SUPPORT */ -int wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, +int wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, size_t pktlen, wl_event_msg_t *event, void **data_ptr, void *raw_event) { /* check whether packet is a BRCM event pkt */ @@ -1512,7 +1515,7 @@ #ifdef DNGL_EVENT_SUPPORT /* If it is a DNGL event process it first */ - if (dngl_host_event(dhd_pub, pktdata) == BCME_OK) { + if (dngl_host_event(dhd_pub, pktdata, pktlen) == BCME_OK) { /* Return error purposely to prevent DNGL event being processed as BRCM event */ return BCME_ERROR; } @@ -1529,18 +1532,27 @@ return (BCME_ERROR); } + if (pktlen < sizeof(bcm_event_t)) + return (BCME_ERROR); + *data_ptr = &pvt_data[1]; event_data = *data_ptr; - /* memcpy since BRCM event pkt may be unaligned. */ memcpy(event, &pvt_data->event, sizeof(wl_event_msg_t)); type = ntoh32_ua((void *)&event->event_type); flags = ntoh16_ua((void *)&event->flags); status = ntoh32_ua((void *)&event->status); + datalen = ntoh32_ua((void *)&event->datalen); + if (datalen > pktlen) + return (BCME_ERROR); + evlen = datalen + sizeof(bcm_event_t); + if (evlen > pktlen) { + return BCME_ERROR; + } /* find equivalent host index for event ifidx */ hostidx = dhd_ifidx2hostidx(dhd_pub->info, event->ifidx); diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 3998402..7c0563a 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -700,7 +700,7 @@ static int dhd_toe_set(dhd_info_t *dhd, int idx, uint32 toe_ol); #endif /* TOE */ -static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, +static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, size_t pktlen, wl_event_msg_t *event_ptr, void **data_ptr); #ifdef DHD_UNICAST_DHCP static const uint8 llc_snap_hdr[SNAP_HDR_LEN] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; @@ -3018,6 +3018,7 @@ #else skb->mac.raw, #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) */ + len - 2, &event, &data); @@ -7452,16 +7453,18 @@ #endif /* defined(WL_WIRELESS_EXT) */ static int -dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, +dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, size_t pktlen, wl_event_msg_t *event, void **data) { int bcmerror = 0; ASSERT(dhd != NULL); #ifdef SHOW_LOGTRACE - bcmerror = wl_host_event(&dhd->pub, ifidx, pktdata, event, data, &dhd->event_data); + bcmerror = wl_host_event(&dhd->pub, ifidx, pktdata, pktlen, + event, data, &dhd->event_data); #else - bcmerror = wl_host_event(&dhd->pub, ifidx, pktdata, event, data, NULL); + bcmerror = wl_host_event(&dhd->pub, ifidx, pktdata, pktlen, + event, data, NULL); #endif /* SHOW_LOGTRACE */ if (bcmerror != BCME_OK)