Commit fe0a7776 authored by Dmitry Antipov's avatar Dmitry Antipov Committed by Kalle Valo
Browse files

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



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
parent 595b1280
Loading
Loading
Loading
Loading
+25 −17
Original line number Diff line number Diff line
@@ -336,29 +336,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,
@@ -376,8 +385,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,