Commit 4e390d0b authored by qize wang's avatar qize wang Committed by Kleber Sacilotto de Souza

UBUNTU: SAUCE: mwifiex: Fix heap overflow in mmwifiex_process_tdls_action_frame()

mwifiex_process_tdls_action_frame() without checking
the incoming tdls infomation element's vality before use it,
this may cause multi heap buffer overflows.

Fix them by putting vality check before use it.
Signed-off-by: default avatarqize wang <wangqize888888888@gmail.com>

CVE-2019-14901

(backported from https://patchwork.kernel.org/patch/11257535/)
[smb: drop marvell subdirectory from path, plus manual context
      adjustments]
Signed-off-by: default avatarStefan Bader <stefan.bader@canonical.com>
Acked-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
Acked-by: default avatarAndrea Righi <andrea.righi@canonical.com>
Signed-off-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
parent f41dbb3e
...@@ -910,59 +910,116 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, ...@@ -910,59 +910,116 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
switch (*pos) { switch (*pos) {
case WLAN_EID_SUPP_RATES: case WLAN_EID_SUPP_RATES:
if (pos[1] > 32)
return;
sta_ptr->tdls_cap.rates_len = pos[1]; sta_ptr->tdls_cap.rates_len = pos[1];
for (i = 0; i < pos[1]; i++) for (i = 0; i < pos[1]; i++)
sta_ptr->tdls_cap.rates[i] = pos[i + 2]; sta_ptr->tdls_cap.rates[i] = pos[i + 2];
break; break;
case WLAN_EID_EXT_SUPP_RATES: case WLAN_EID_EXT_SUPP_RATES:
if (pos[1] > 32)
return;
basic = sta_ptr->tdls_cap.rates_len; basic = sta_ptr->tdls_cap.rates_len;
if (pos[1] > 32 - basic)
return;
for (i = 0; i < pos[1]; i++) for (i = 0; i < pos[1]; i++)
sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2]; sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
sta_ptr->tdls_cap.rates_len += pos[1]; sta_ptr->tdls_cap.rates_len += pos[1];
break; break;
case WLAN_EID_HT_CAPABILITY: case WLAN_EID_HT_CAPABILITY:
memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos, if (pos > end - sizeof(struct ieee80211_ht_cap) - 2)
return;
if (pos[1] != sizeof(struct ieee80211_ht_cap))
return;
/* copy the ie's value into ht_capb*/
memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos + 2,
sizeof(struct ieee80211_ht_cap)); sizeof(struct ieee80211_ht_cap));
sta_ptr->is_11n_enabled = 1; sta_ptr->is_11n_enabled = 1;
break; break;
case WLAN_EID_HT_OPERATION: case WLAN_EID_HT_OPERATION:
memcpy(&sta_ptr->tdls_cap.ht_oper, pos, if (pos > end -
sizeof(struct ieee80211_ht_operation) - 2)
return;
if (pos[1] != sizeof(struct ieee80211_ht_operation))
return;
memcpy(&sta_ptr->tdls_cap.ht_oper, pos + 2,
sizeof(struct ieee80211_ht_operation)); sizeof(struct ieee80211_ht_operation));
break; break;
case WLAN_EID_BSS_COEX_2040: case WLAN_EID_BSS_COEX_2040:
if (pos > end - 3)
return;
if (pos[1] != 1)
return;
sta_ptr->tdls_cap.coex_2040 = pos[2]; sta_ptr->tdls_cap.coex_2040 = pos[2];
break; break;
case WLAN_EID_EXT_CAPABILITY: case WLAN_EID_EXT_CAPABILITY:
if (pos > end - sizeof(struct ieee_types_header))
return;
if (pos[1] < sizeof(struct ieee_types_header))
return;
if (pos[1] > 8)
return;
memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos, memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
sizeof(struct ieee_types_header) + sizeof(struct ieee_types_header) +
min_t(u8, pos[1], 8)); min_t(u8, pos[1], 8));
break; break;
case WLAN_EID_RSN: case WLAN_EID_RSN:
if (pos > end - sizeof(struct ieee_types_header))
return;
if (pos[1] < sizeof(struct ieee_types_header))
return;
if (pos[1] > IEEE_MAX_IE_SIZE -
sizeof(struct ieee_types_header))
return;
memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos, memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
sizeof(struct ieee_types_header) + sizeof(struct ieee_types_header) +
min_t(u8, pos[1], IEEE_MAX_IE_SIZE - min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
sizeof(struct ieee_types_header))); sizeof(struct ieee_types_header)));
break; break;
case WLAN_EID_QOS_CAPA: case WLAN_EID_QOS_CAPA:
if (pos > end - 3)
return;
if (pos[1] != 1)
return;
sta_ptr->tdls_cap.qos_info = pos[2]; sta_ptr->tdls_cap.qos_info = pos[2];
break; break;
case WLAN_EID_VHT_OPERATION: case WLAN_EID_VHT_OPERATION:
if (priv->adapter->is_hw_11ac_capable) if (priv->adapter->is_hw_11ac_capable) {
memcpy(&sta_ptr->tdls_cap.vhtoper, pos, if (pos > end -
sizeof(struct ieee80211_vht_operation) - 2)
return;
if (pos[1] !=
sizeof(struct ieee80211_vht_operation))
return;
/* copy the ie's value into vhtoper*/
memcpy(&sta_ptr->tdls_cap.vhtoper, pos + 2,
sizeof(struct ieee80211_vht_operation)); sizeof(struct ieee80211_vht_operation));
}
break; break;
case WLAN_EID_VHT_CAPABILITY: case WLAN_EID_VHT_CAPABILITY:
if (priv->adapter->is_hw_11ac_capable) { if (priv->adapter->is_hw_11ac_capable) {
memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos, if (pos > end -
sizeof(struct ieee80211_vht_cap) - 2)
return;
if (pos[1] != sizeof(struct ieee80211_vht_cap))
return;
/* copy the ie's value into vhtcap*/
memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos + 2,
sizeof(struct ieee80211_vht_cap)); sizeof(struct ieee80211_vht_cap));
sta_ptr->is_11ac_enabled = 1; sta_ptr->is_11ac_enabled = 1;
} }
break; break;
case WLAN_EID_AID: case WLAN_EID_AID:
if (priv->adapter->is_hw_11ac_capable) if (priv->adapter->is_hw_11ac_capable) {
if (pos > end - 4)
return;
if (pos[1] != 2)
return;
sta_ptr->tdls_cap.aid = sta_ptr->tdls_cap.aid =
le16_to_cpu(*(__le16 *)(pos + 2)); le16_to_cpu(*(__le16 *)(pos + 2));
}
break;
default: default:
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment