net: wireless: bcmdhd: Fix Android Bug 25306181
Michael Hsu [Sat, 9 Jan 2016 00:16:08 +0000 (16:16 -0800)]
Original patch source: https://android.googlesource.com/kernel/msm

Original patch commit message:
> commit 3fffc78f70dc101add8b82af878d53457713d005
> Author: Patrick Tjin <pattjin@google.com>
> Date:   Wed Dec 9 15:24:05 2015 -0800
>
>     net: wireless: bcmdhd: check packet length for event messages
>
>     Check the datalen field is less than the size of
>     packet received from the network.
>
>     Bug: 25306181
>
>     Signed-off-by: Patrick Tjin <pattjin@google.com>
>     Change-Id: I3b021d88a95bd7d4e6e0d745d2527d73487bcadc
>     (cherry picked from commit 10b850b7e82873a14068d24dac4fc2080d46ff76)

Bug 1716690

Change-Id: Ic83eb29fe95ad0c1b50bdd8bcc39982575671e2d
Signed-off-by: Michael Hsu <mhsu@nvidia.com>
Reviewed-on: http://git-master/r/999648
GVS: Gerrit_Virtual_Submit
Reviewed-by: Manish Tuteja <mtuteja@nvidia.com>
Tested-by: Manish Tuteja <mtuteja@nvidia.com>

drivers/net/wireless/bcmdhd/dhd.h
drivers/net/wireless/bcmdhd/dhd_common.c
drivers/net/wireless/bcmdhd/dhd_linux.c

index ef64b4f..196ed1f 100644 (file)
@@ -726,7 +726,7 @@ extern int dhd_ifidx2hostidx(struct dhd_info *dhd, int ifidx);
 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);
 
index 1c08cae..c9c99c4 100644 (file)
@@ -1734,7 +1734,7 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data,
 #endif /* SHOW_EVENTS */
 
 int
-wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata,
+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 */
@@ -1756,6 +1756,9 @@ wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata,
                return (BCME_ERROR);
        }
 
+       if (pktlen < sizeof(bcm_event_t))
+               return (BCME_ERROR);
+
        *data_ptr = &pvt_data[1];
        event_data = *data_ptr;
 
@@ -1766,8 +1769,14 @@ wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata,
        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);
index 8f92720..1684b03 100644 (file)
@@ -765,7 +765,7 @@ static int dhd_toe_get(dhd_info_t *dhd, int idx, uint32 *toe_ol);
 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};
@@ -3178,6 +3178,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
 #else
                        skb->mac.raw,
 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) */
+                       len - 2,
                        &event,
                        &data);
 
@@ -8004,7 +8005,7 @@ dhd_wlanaudio_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
 }
 #endif /* CUSTOMER_HW20 && WLANAUDIO */
 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;
@@ -8019,9 +8020,11 @@ dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
 #endif /* CUSTOMER_HW20 && WLANAUDIO */
 
 #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)