Commit 54a12a87 authored by Dmitry Antipov's avatar Dmitry Antipov Committed by Chen Ridong
Browse files

wifi: wfx: fix possible NULL pointer dereference in wfx_set_mfp_ap()

mainline inclusion
from mainline-v6.8-rc1
commit fe0a7776d4d19e613bb8dd80fe2d78ae49e8b49d
category: feature
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I96GAG
CVE: CVE-2023-52593

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=fe0a7776d4d19e613bb8dd80fe2d78ae49e8b49d



----------------------------------------------------------------------

Since 'ieee80211_beacon_get()' can return NULL, 'wfx_set_mfp_ap()'
should check the return value before examining skb data. So convert
the latter to return an appropriate error code and propagate it to
return from 'wfx_start_ap()' as well. Compile tested only.

Signed-off-by: default avatarDmitry Antipov <dmantipov@yandex.ru>
Tested-by: default avatarJérôme Pouiller <jerome.pouiller@silabs.com>
Acked-by: default avatarJérôme Pouiller <jerome.pouiller@silabs.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20231204171130.141394-1-dmantipov@yandex.ru


Signed-off-by: default avatarChen Ridong <chenridong@huawei.com>
parent 23534451
Loading
Loading
Loading
Loading
+25 −17
Original line number Diff line number Diff line
@@ -354,29 +354,38 @@ static int wfx_upload_ap_templates(struct wfx_vif *wvif)
	return 0;
}

static void wfx_set_mfp_ap(struct wfx_vif *wvif)
static int wfx_set_mfp_ap(struct wfx_vif *wvif)
{
	struct ieee80211_vif *vif = wvif_to_vif(wvif);
	struct sk_buff *skb = ieee80211_beacon_get(wvif->wdev->hw, vif, 0);
	const int ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
	const u16 *ptr = (u16 *)cfg80211_find_ie(WLAN_EID_RSN, skb->data + ieoffset,
						 skb->len - ieoffset);
	const int pairwise_cipher_suite_count_offset = 8 / sizeof(u16);
	const int pairwise_cipher_suite_size = 4 / sizeof(u16);
	const int akm_suite_size = 4 / sizeof(u16);
	const u16 *ptr;

	if (unlikely(!skb))
		return -ENOMEM;

	ptr = (u16 *)cfg80211_find_ie(WLAN_EID_RSN, skb->data + ieoffset,
				      skb->len - ieoffset);
	if (unlikely(!ptr))
		return -EINVAL;

	if (ptr) {
	ptr += pairwise_cipher_suite_count_offset;
	if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
			return;
		return -EINVAL;

	ptr += 1 + pairwise_cipher_suite_size * *ptr;
	if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
			return;
		return -EINVAL;

	ptr += 1 + akm_suite_size * *ptr;
	if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
			return;
		return -EINVAL;

	wfx_hif_set_mfp(wvif, *ptr & BIT(7), *ptr & BIT(6));
	}
	return 0;
}

int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
@@ -394,8 +403,7 @@ int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
	ret = wfx_hif_start(wvif, &vif->bss_conf, wvif->channel);
	if (ret > 0)
		return -EIO;
	wfx_set_mfp_ap(wvif);
	return ret;
	return wfx_set_mfp_ap(wvif);
}

void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,