Skip to content

Commit

Permalink
ANDROID: net: wireless: bcmdhd: Verify SSID length
Browse files Browse the repository at this point in the history
    Ensure SSID length is correct before memcpy

    Bug=26571522
    Bug=27240072

Change-Id: Ia650ec88268d0efc3ae33f3435c3e6ee91e6a642
Signed-off-by: Jerry Lee <jerrylee@broadcom.com>
Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/337262
  • Loading branch information
Jerry Lee authored and Andrew Bresticker committed Apr 5, 2016
1 parent 8aac200 commit 9c052ef
Showing 1 changed file with 53 additions and 27 deletions.
80 changes: 53 additions & 27 deletions drivers/net/wireless/bcmdhd/wl_cfg80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -2036,15 +2036,17 @@ static void wl_scan_prep(struct bcm_cfg80211 *cfg, struct wl_scan_params *params
WL_SCAN(("Scanning all channels\n"));
}
n_channels = j;

/* Copy ssid array if applicable */
WL_SCAN(("### List of SSIDs to scan ###\n"));
if (n_ssids > 0) {
offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16);
offset = roundup(offset, sizeof(u32));
ptr = (char*)params + offset;

for (i = 0; i < n_ssids; i++) {
memset(&ssid, 0, sizeof(wlc_ssid_t));
ssid.SSID_len = request->ssids[i].ssid_len;
ssid.SSID_len = MIN((int)request->ssids[i].ssid_len, DOT11_MAX_SSID_LEN);
memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
if (!ssid.SSID_len)
WL_SCAN(("%d: Broadcast scan\n", i));
Expand Down Expand Up @@ -3216,7 +3218,8 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
WL_TRACE(("In\n"));
RETURN_EIO_IF_NOT_UP(cfg);
WL_INFORM(("JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid)));
if (!params->ssid || params->ssid_len <= 0) {

if (!params->ssid || params->ssid_len <= 0 || params->ssid_len > DOT11_MAX_SSID_LEN) {
WL_ERR(("Invalid parameter\n"));
return -EINVAL;
}
Expand Down Expand Up @@ -6506,16 +6509,16 @@ static s32 wl_cfg80211_bcn_set_params(
}

if ((info->ssid) && (info->ssid_len > 0) &&
(info->ssid_len <= 32)) {
(info->ssid_len <= DOT11_MAX_SSID_LEN)) {
WL_DBG(("SSID (%s) len:%zd \n", info->ssid, info->ssid_len));
if (dev_role == NL80211_IFTYPE_AP) {
/* Store the hostapd SSID */
memset(cfg->hostapd_ssid.SSID, 0x00, 32);
memset(cfg->hostapd_ssid.SSID, 0x00, DOT11_MAX_SSID_LEN);
memcpy(cfg->hostapd_ssid.SSID, info->ssid, info->ssid_len);
cfg->hostapd_ssid.SSID_len = info->ssid_len;
} else {
/* P2P GO */
memset(cfg->p2p->ssid.SSID, 0x00, 32);
/* P2P GO */
memset(cfg->p2p->ssid.SSID, 0x00, DOT11_MAX_SSID_LEN);
memcpy(cfg->p2p->ssid.SSID, info->ssid, info->ssid_len);
cfg->p2p->ssid.SSID_len = info->ssid_len;
}
Expand Down Expand Up @@ -6654,11 +6657,14 @@ wl_cfg80211_bcn_bringup_ap(
}

memset(&join_params, 0, sizeof(join_params));

/* join parameters starts with ssid */
join_params_size = sizeof(join_params.ssid);
join_params.ssid.SSID_len = MIN(cfg->hostapd_ssid.SSID_len,
(uint32)DOT11_MAX_SSID_LEN);
memcpy(join_params.ssid.SSID, cfg->hostapd_ssid.SSID,
cfg->hostapd_ssid.SSID_len);
join_params.ssid.SSID_len = htod32(cfg->hostapd_ssid.SSID_len);
join_params.ssid.SSID_len);
join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);

/* create softap */
if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
Expand Down Expand Up @@ -7249,20 +7255,22 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
}

ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;

/* find the SSID */
if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
info->head_len - ie_offset,
DOT11_MNG_SSID_ID)) != NULL) {
if (dev_role == NL80211_IFTYPE_AP) {
/* Store the hostapd SSID */
memset(&cfg->hostapd_ssid.SSID[0], 0x00, 32);
memcpy(&cfg->hostapd_ssid.SSID[0], ssid_ie->data, ssid_ie->len);
cfg->hostapd_ssid.SSID_len = ssid_ie->len;
memset(&cfg->hostapd_ssid.SSID[0], 0x00, DOT11_MAX_SSID_LEN);
cfg->hostapd_ssid.SSID_len = MIN((int)ssid_ie->len, DOT11_MAX_SSID_LEN);
memcpy(&cfg->hostapd_ssid.SSID[0], ssid_ie->data,
cfg->hostapd_ssid.SSID_len);
} else {
/* P2P GO */
memset(&cfg->p2p->ssid.SSID[0], 0x00, 32);
memcpy(cfg->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len);
cfg->p2p->ssid.SSID_len = ssid_ie->len;
/* P2P GO */
memset(&cfg->p2p->ssid.SSID[0], 0x00, DOT11_MAX_SSID_LEN);
cfg->p2p->ssid.SSID_len = MIN((int)ssid_ie->len, DOT11_MAX_SSID_LEN);
memcpy(cfg->p2p->ssid.SSID, ssid_ie->data, cfg->p2p->ssid.SSID_len);
}
}

Expand Down Expand Up @@ -7410,8 +7418,10 @@ wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
ssid = &request->match_sets[i].ssid;
/* No need to include null ssid */
if (ssid->ssid_len) {
memcpy(ssids_local[ssid_cnt].SSID, ssid->ssid, ssid->ssid_len);
ssids_local[ssid_cnt].SSID_len = ssid->ssid_len;
ssids_local[ssid_cnt].SSID_len = MIN(ssid->ssid_len,
(uint32)DOT11_MAX_SSID_LEN);
memcpy(ssids_local[ssid_cnt].SSID, ssid->ssid,
ssids_local[ssid_cnt].SSID_len);
if (is_ssid_in_list(ssid, hidden_ssid_list, request->n_ssids)) {
ssids_local[ssid_cnt].hidden = TRUE;
WL_PNO((">>> PNO hidden SSID (%s) \n", ssid->ssid));
Expand Down Expand Up @@ -11800,8 +11810,8 @@ wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
ssid = (wlc_ssid_t *) data;
memset(profile->ssid.SSID, 0,
sizeof(profile->ssid.SSID));
memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
profile->ssid.SSID_len = ssid->SSID_len;
profile->ssid.SSID_len = MIN(ssid->SSID_len, (uint32)DOT11_MAX_SSID_LEN);
memcpy(profile->ssid.SSID, ssid->SSID, profile->ssid.SSID_len);
break;
case WL_PROF_BSSID:
if (data)
Expand Down Expand Up @@ -11884,27 +11894,43 @@ static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v)
static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size, bool roam)
{
u8 *ssidie;
int32 ssid_len = MIN((int)bi->SSID_len, DOT11_MAX_SSID_LEN);
int32 remaining_ie_buf_len, available_buffer_len;
ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);

/*
* ERROR out if
* 1. No ssid IE is FOUND or
* 2. New ssid length is > what was allocated for existing ssid (as
* we do not want to overwrite the rest of the IEs) or
* 3. If in case of erroneous buffer input where ssid length doesnt match the space
* allocated to it.
*/
if (!ssidie)
return;
if (ssidie[1] != bi->SSID_len) {

available_buffer_len = ((int)(*ie_size)) - (ssidie + 2 - ie_stream);
remaining_ie_buf_len = available_buffer_len - (int)ssidie[1];
if ((ssid_len > ssidie[1]) || (ssidie[1] > available_buffer_len))
return;

if (ssidie[1] != ssid_len) {
if (ssidie[1]) {
WL_ERR(("%s: Wrong SSID len: %d != %d\n",
__FUNCTION__, ssidie[1], bi->SSID_len));
}
if (roam) {
WL_ERR(("Changing the SSID Info.\n"));
memmove(ssidie + bi->SSID_len + 2,
(ssidie + 2) + ssidie[1],
*ie_size - (ssidie + 2 + ssidie[1] - ie_stream));
memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
*ie_size = *ie_size + bi->SSID_len - ssidie[1];
ssidie[1] = bi->SSID_len;
memmove(ssidie + ssid_len + 2,
(ssidie + 2) + ssidie[1], remaining_ie_buf_len);
memcpy(ssidie + 2, bi->SSID, ssid_len);
*ie_size = *ie_size + ssid_len - ssidie[1];
ssidie[1] = ssid_len;
}
return;
}
if (*(ssidie + 2) == '\0')
memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
memcpy(ssidie + 2, bi->SSID, ssid_len);
return;
}

Expand Down

0 comments on commit 9c052ef

Please sign in to comment.