Skip to content
Snippets Groups Projects
Commit 589e4738 authored by Insun Song's avatar Insun Song Committed by Stuart Scott
Browse files

net: wireless: bcmdhd: additional length check for BRCM EVENT frame.


This is just for exceptional case where user has updated kernel to the
latest, but still used non-patched firmware. The non-patched firmware
could deliver ETHER_TYPE_BRCM packet to host.

If attacker inject packet with its header length forged, it could bypass
current host driver's length check routine and cause memory corruption.

Proposed fix is enhancing length check to validate its header length.

Change-Id: I90fc5101bddfd1d427e0a52758ddf8bc16577555
Bug: 37168488
Signed-off-by: default avatarInsun Song <insun.song@broadcom.com>
parent dc9f6a22
No related branches found
No related tags found
No related merge requests found
......@@ -209,12 +209,14 @@ int
is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype,
bcm_event_msg_u_t *out_event)
{
uint16 len;
uint16 evlen;
uint16 subtype;
uint16 usr_subtype;
bcm_event_t *bcm_event;
uint8 *pktend;
uint8 *evend;
int err = BCME_OK;
uint32 data_len;
pktend = (uint8 *)pktdata + pktlen;
bcm_event = (bcm_event_t *)pktdata;
......@@ -235,8 +237,9 @@ is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype,
}
/* check length in bcmeth_hdr */
len = ntoh16_ua((void *)&bcm_event->bcm_hdr.length);
if (((uint8 *)&bcm_event->bcm_hdr.version + len) > pktend) {
evlen = ntoh16_ua((void *)&bcm_event->bcm_hdr.length);
evend = (uint8 *)&bcm_event->bcm_hdr.version + evlen;
if (evend != pktend) {
err = BCME_BADLEN;
goto done;
}
......@@ -257,13 +260,15 @@ is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype,
usr_subtype = ntoh16_ua((void *)&bcm_event->bcm_hdr.usr_subtype);
switch (usr_subtype) {
case BCMILCP_BCM_SUBTYPE_EVENT:
if (pktlen < sizeof(bcm_event_t)) {
if ((pktlen < sizeof(bcm_event_t)) ||
(evend < ((uint8 *)bcm_event + sizeof(bcm_event_t)))) {
err = BCME_BADLEN;
goto done;
}
len = sizeof(bcm_event_t) + ntoh32_ua((void *)&bcm_event->event.datalen);
if ((uint8 *)pktdata + len > pktend) {
data_len = ntoh32_ua((void *)&bcm_event->event.datalen);
if ((sizeof(bcm_event_t) + data_len +
BCMILCP_BCM_SUBTYPE_EVENT_DATA_PAD) != pktlen) {
err = BCME_BADLEN;
goto done;
}
......@@ -280,14 +285,16 @@ is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype,
break;
case BCMILCP_BCM_SUBTYPE_DNGLEVENT:
if (pktlen < sizeof(bcm_dngl_event_t)) {
if (pktlen < sizeof(bcm_dngl_event_t) ||
(evend < ((uint8 *)bcm_event + sizeof(bcm_dngl_event_t)))) {
err = BCME_BADLEN;
goto done;
}
len = sizeof(bcm_dngl_event_t) +
ntoh16_ua((void *)&((bcm_dngl_event_t *)pktdata)->dngl_event.datalen);
if ((uint8 *)pktdata + len > pktend) {
data_len = ntoh16_ua((void *)&((bcm_dngl_event_t *)pktdata)
->dngl_event.datalen);
if ((sizeof(bcm_dngl_event_t) + data_len +
BCMILCP_BCM_SUBTYPE_EVENT_DATA_PAD) != pktlen) {
err = BCME_BADLEN;
goto done;
}
......
......@@ -93,6 +93,7 @@
#define BCMILCP_BCM_SUBTYPE_DNGLEVENT 5
#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8
#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0
#define BCMILCP_BCM_SUBTYPE_EVENT_DATA_PAD 2
/* These fields are stored in network order */
typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment