[PATCH X 3/3] UBUNTU: SAUCE: mwifiex: Fix heap overflow in mmwifiex_process_tdls_action_frame()
Kleber Souza
kleber.souza at canonical.com
Wed Nov 27 15:45:58 UTC 2019
On 26.11.19 09:39, Stefan Bader wrote:
> From: qize wang <wangqize888888888 at gmail.com>
>
> 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: qize wang <wangqize888888888 at 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: Stefan Bader <stefan.bader at canonical.com>
> ---
> drivers/net/wireless/mwifiex/tdls.c | 69 ++++++++++++++++++++++++++---
> 1 file changed, 63 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c
> index 9275f9c3f869..de59251158ad 100644
> --- a/drivers/net/wireless/mwifiex/tdls.c
> +++ b/drivers/net/wireless/mwifiex/tdls.c
> @@ -910,59 +910,116 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
>
> switch (*pos) {
> case WLAN_EID_SUPP_RATES:
> + if (pos[1] > 32)
> + return;
> sta_ptr->tdls_cap.rates_len = pos[1];
> for (i = 0; i < pos[1]; i++)
> sta_ptr->tdls_cap.rates[i] = pos[i + 2];
> break;
>
> case WLAN_EID_EXT_SUPP_RATES:
> + if (pos[1] > 32)
> + return;
> basic = sta_ptr->tdls_cap.rates_len;
> + if (pos[1] > 32 - basic)
> + return;
> for (i = 0; i < pos[1]; i++)
> sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
> sta_ptr->tdls_cap.rates_len += pos[1];
> break;
> 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));
> sta_ptr->is_11n_enabled = 1;
> break;
> 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));
> break;
> case WLAN_EID_BSS_COEX_2040:
> + if (pos > end - 3)
> + return;
> + if (pos[1] != 1)
> + return;
> sta_ptr->tdls_cap.coex_2040 = pos[2];
> break;
> 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,
> sizeof(struct ieee_types_header) +
> min_t(u8, pos[1], 8));
> break;
> 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,
> sizeof(struct ieee_types_header) +
> min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
> sizeof(struct ieee_types_header)));
> break;
> case WLAN_EID_QOS_CAPA:
> + if (pos > end - 3)
> + return;
> + if (pos[1] != 1)
> + return;
> sta_ptr->tdls_cap.qos_info = pos[2];
> break;
> case WLAN_EID_VHT_OPERATION:
> - if (priv->adapter->is_hw_11ac_capable)
> - memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
> + if (priv->adapter->is_hw_11ac_capable) {
> + 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));
> + }
> break;
> case WLAN_EID_VHT_CAPABILITY:
> 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));
> sta_ptr->is_11ac_enabled = 1;
> }
> break;
> 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 =
> le16_to_cpu(*(__le16 *)(pos + 2));
> + }
> + break;
> default:
> break;
> }
>
More information about the kernel-team
mailing list