mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-10-01 01:35:54 -04:00
111 lines
4.0 KiB
Diff
111 lines
4.0 KiB
Diff
|
From e7fdc1ca00f1e589df8542af7e7acaaa87370625 Mon Sep 17 00:00:00 2001
|
||
|
From: Insun Song <insun.song@broadcom.com>
|
||
|
Date: Fri, 7 Apr 2017 16:27:49 -0700
|
||
|
Subject: [PATCH] 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: Insun Song <insun.song@broadcom.com>
|
||
|
---
|
||
|
drivers/net/wireless/bcmdhd/bcmevent.c | 27 ++++++++++++++--------
|
||
|
drivers/net/wireless/bcmdhd/include/proto/bcmeth.h | 1 +
|
||
|
2 files changed, 18 insertions(+), 10 deletions(-)
|
||
|
mode change 100755 => 100644 drivers/net/wireless/bcmdhd/include/proto/bcmeth.h
|
||
|
|
||
|
diff --git a/drivers/net/wireless/bcmdhd/bcmevent.c b/drivers/net/wireless/bcmdhd/bcmevent.c
|
||
|
index b85f111bce180..7ed9739c0eddf 100644
|
||
|
--- a/drivers/net/wireless/bcmdhd/bcmevent.c
|
||
|
+++ b/drivers/net/wireless/bcmdhd/bcmevent.c
|
||
|
@@ -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;
|
||
|
}
|
||
|
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h b/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h
|
||
|
old mode 100755
|
||
|
new mode 100644
|
||
|
index 41c1b57443c77..756f594bc61db
|
||
|
--- a/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h
|
||
|
+++ b/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h
|
||
|
@@ -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
|