aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Tjin <pattjin@google.com>2015-12-09 21:17:56 -0800
committerWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2016-03-18 01:51:05 +0100
commit054977b84bd1b4aaa2251fdffc5d84bec51630ed (patch)
tree66812a6eaecd66982a84a0da5273483dc39c06e4
parentcbfc7fd3baa2b525bf0534f678a59c2e4c88c71c (diff)
downloadkernel_samsung_smdk4412-054977b84bd1b4aaa2251fdffc5d84bec51630ed.zip
kernel_samsung_smdk4412-054977b84bd1b4aaa2251fdffc5d84bec51630ed.tar.gz
kernel_samsung_smdk4412-054977b84bd1b4aaa2251fdffc5d84bec51630ed.tar.bz2
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 BUG=25668859 Signed-off-by: Patrick Tjin <pattjin@google.com> Change-Id: I3b021d88a95bd7d4e6e0d745d2527d73487bcadc
-rw-r--r--drivers/net/wireless/bcmdhd/dhd.h2
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_common.c11
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c7
3 files changed, 15 insertions, 5 deletions
diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h
index b0b2b29..c5074ab 100644
--- a/drivers/net/wireless/bcmdhd/dhd.h
+++ b/drivers/net/wireless/bcmdhd/dhd.h
@@ -651,7 +651,7 @@ extern int dhd_ifname2idx(struct dhd_info *dhd, char *name);
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);
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 ea3433e..dd6ace7 100644
--- a/drivers/net/wireless/bcmdhd/dhd_common.c
+++ b/drivers/net/wireless/bcmdhd/dhd_common.c
@@ -1190,7 +1190,7 @@ wl_show_host_event(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)
{
/* check whether packet is a BRCM event pkt */
@@ -1211,6 +1211,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;
@@ -1220,8 +1223,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);
switch (type) {
#ifdef PROP_TXSTATUS
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index da6b2a2..876ae18 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -679,7 +679,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);
#if defined(SUPPORT_P2P_GO_PS)
@@ -2213,6 +2213,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);
@@ -6154,13 +6155,13 @@ dhd_get_wireless_stats(struct net_device *dev)
#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);
- bcmerror = wl_host_event(&dhd->pub, ifidx, pktdata, event, data);
+ bcmerror = wl_host_event(&dhd->pub, ifidx, pktdata, pktlen, event, data);
if (bcmerror != BCME_OK)
return (bcmerror);