mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-24 23:19:31 -05:00
156 lines
4.8 KiB
Diff
156 lines
4.8 KiB
Diff
|
From 8f1621cd0d0ca0bc494a926a1331f582b27b913e Mon Sep 17 00:00:00 2001
|
||
|
From: Insun Song <insun.song@broadcom.com>
|
||
|
Date: Thu, 3 Nov 2016 10:53:51 -0700
|
||
|
Subject: [PATCH] net: wireless: bcmdhd: fix buffer overrun in
|
||
|
wl_cfgvendor_hotlist_cfg
|
||
|
|
||
|
fix buffer overrun found where user manipulated input parameters
|
||
|
|
||
|
1. allocate local buffer with max length than input sized.
|
||
|
2. length check added in each tlv parsing and added error handling.
|
||
|
3. limit max hotlist count to PFN_SW_MAX_NUM_APS(16).
|
||
|
|
||
|
bug=32474971
|
||
|
|
||
|
Signed-off-by: Insun Song <insun.song@broadcom.com>
|
||
|
Change-Id: I60d513a30875f6a8ee8cfdc557bdec1436416fe7
|
||
|
---
|
||
|
drivers/net/wireless/bcmdhd/wl_cfgvendor.c | 107 +++++++++++++++++++++--------
|
||
|
1 file changed, 78 insertions(+), 29 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c
|
||
|
index eb83c8339e471..d578026885619 100644
|
||
|
--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c
|
||
|
+++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c
|
||
|
@@ -691,14 +691,22 @@ static int wl_cfgvendor_hotlist_cfg(struct wiphy *wiphy,
|
||
|
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
|
||
|
gscan_hotlist_scan_params_t *hotlist_params;
|
||
|
int tmp, tmp1, tmp2, type, j = 0, dummy;
|
||
|
- const struct nlattr *outer, *inner, *iter;
|
||
|
- bool flush = FALSE;
|
||
|
+ const struct nlattr *outer, *inner = NULL, *iter;
|
||
|
+ uint8 flush = 0;
|
||
|
struct bssid_t *pbssid;
|
||
|
|
||
|
- hotlist_params = (gscan_hotlist_scan_params_t *)kzalloc(len, GFP_KERNEL);
|
||
|
+ if (len < sizeof(*hotlist_params) || len >= WLC_IOCTL_MAXLEN) {
|
||
|
+ WL_ERR(("buffer length :%d wrong - bail out.\n", len));
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ hotlist_params = kzalloc(sizeof(*hotlist_params)
|
||
|
+ + (sizeof(struct bssid_t) * (PFN_SWC_MAX_NUM_APS - 1)),
|
||
|
+ GFP_KERNEL);
|
||
|
+
|
||
|
if (!hotlist_params) {
|
||
|
WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes \n", len));
|
||
|
- return -1;
|
||
|
+ return -ENOMEM;
|
||
|
}
|
||
|
|
||
|
hotlist_params->lost_ap_window = GSCAN_LOST_AP_WINDOW_DEFAULT;
|
||
|
@@ -706,37 +714,78 @@ static int wl_cfgvendor_hotlist_cfg(struct wiphy *wiphy,
|
||
|
nla_for_each_attr(iter, data, len, tmp2) {
|
||
|
type = nla_type(iter);
|
||
|
switch (type) {
|
||
|
- case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS:
|
||
|
- pbssid = hotlist_params->bssid;
|
||
|
- nla_for_each_nested(outer, iter, tmp) {
|
||
|
- nla_for_each_nested(inner, outer, tmp1) {
|
||
|
- type = nla_type(inner);
|
||
|
+ case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS:
|
||
|
+ pbssid = hotlist_params->bssid;
|
||
|
+ nla_for_each_nested(outer, iter, tmp) {
|
||
|
+ nla_for_each_nested(inner, outer, tmp1) {
|
||
|
+ type = nla_type(inner);
|
||
|
|
||
|
- switch (type) {
|
||
|
- case GSCAN_ATTRIBUTE_BSSID:
|
||
|
- memcpy(&(pbssid[j].macaddr),
|
||
|
- nla_data(inner), ETHER_ADDR_LEN);
|
||
|
- break;
|
||
|
- case GSCAN_ATTRIBUTE_RSSI_LOW:
|
||
|
- pbssid[j].rssi_reporting_threshold =
|
||
|
- (int8) nla_get_u8(inner);
|
||
|
- break;
|
||
|
- case GSCAN_ATTRIBUTE_RSSI_HIGH:
|
||
|
- dummy = (int8) nla_get_u8(inner);
|
||
|
- break;
|
||
|
+ switch (type) {
|
||
|
+ case GSCAN_ATTRIBUTE_BSSID:
|
||
|
+ if (nla_len(inner) != sizeof(pbssid[j].macaddr)) {
|
||
|
+ WL_DBG(("type:%d length:%d not matching.\n",
|
||
|
+ type, nla_len(inner)));
|
||
|
+ err = -EINVAL;
|
||
|
+ goto exit;
|
||
|
}
|
||
|
+ memcpy(
|
||
|
+ &pbssid[j].macaddr,
|
||
|
+ nla_data(inner),
|
||
|
+ sizeof(pbssid[j].macaddr));
|
||
|
+ break;
|
||
|
+ case GSCAN_ATTRIBUTE_RSSI_LOW:
|
||
|
+ if (nla_len(inner) != sizeof(uint8)) {
|
||
|
+ WL_DBG(("type:%d length:%d not matching.\n",
|
||
|
+ type, nla_len(inner)));
|
||
|
+ err = -EINVAL;
|
||
|
+ goto exit;
|
||
|
+ }
|
||
|
+ pbssid[j].rssi_reporting_threshold =
|
||
|
+ (int8)nla_get_u8(inner);
|
||
|
+ break;
|
||
|
+ case GSCAN_ATTRIBUTE_RSSI_HIGH:
|
||
|
+ if (nla_len(inner) != sizeof(uint8)) {
|
||
|
+ WL_DBG(("type:%d length:%d not matching.\n",
|
||
|
+ type, nla_len(inner)));
|
||
|
+ err = -EINVAL;
|
||
|
+ goto exit;
|
||
|
+ }
|
||
|
+ dummy = (int8)nla_get_u8(inner);
|
||
|
+ break;
|
||
|
}
|
||
|
- j++;
|
||
|
+ }
|
||
|
+ if (++j > PFN_SWC_MAX_NUM_APS) {
|
||
|
+ WL_DBG(("nbssid:%d exeed limit.\n",
|
||
|
+ hotlist_params->nbssid));
|
||
|
+ err = -EINVAL;
|
||
|
+ goto exit;
|
||
|
}
|
||
|
hotlist_params->nbssid = j;
|
||
|
- break;
|
||
|
- case GSCAN_ATTRIBUTE_HOTLIST_FLUSH:
|
||
|
- flush = (bool) nla_get_u8(iter);
|
||
|
- break;
|
||
|
- case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
|
||
|
- hotlist_params->lost_ap_window = nla_get_u32(iter);
|
||
|
- break;
|
||
|
}
|
||
|
+ break;
|
||
|
+ case GSCAN_ATTRIBUTE_HOTLIST_FLUSH:
|
||
|
+ if (nla_len(iter) != sizeof(uint8)) {
|
||
|
+ WL_DBG(("type:%d length:%d not matching.\n",
|
||
|
+ type, nla_len(inner)));
|
||
|
+ err = -EINVAL;
|
||
|
+ goto exit;
|
||
|
+ }
|
||
|
+ flush = nla_get_u8(iter);
|
||
|
+ break;
|
||
|
+ case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
|
||
|
+ if (nla_len(iter) != sizeof(uint32)) {
|
||
|
+ WL_DBG(("type:%d length:%d not matching.\n",
|
||
|
+ type, nla_len(inner)));
|
||
|
+ err = -EINVAL;
|
||
|
+ goto exit;
|
||
|
+ }
|
||
|
+ hotlist_params->lost_ap_window = (uint16)nla_get_u32(iter);
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ WL_DBG(("Unknown type %d\n", type));
|
||
|
+ err = -EINVAL;
|
||
|
+ goto exit;
|
||
|
+ }
|
||
|
|
||
|
}
|
||
|
|