mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-20 19:03:39 +00:00
70 lines
2.8 KiB
Diff
70 lines
2.8 KiB
Diff
From ec3f4711a4896adbc51cd2e68d2460718f87c1c4 Mon Sep 17 00:00:00 2001
|
|
From: Wen Gong <quic_wgong@quicinc.com>
|
|
Date: Sun, 23 Oct 2022 22:52:14 -0400
|
|
Subject: [PATCH 027/112] wifi: ath12k: Fix buffer overflow when scanning with
|
|
extraie
|
|
|
|
If cfg80211 is providing extraie's for a scanning process then ath12k will
|
|
copy that over to the firmware. The extraie.len is a 32 bit value in struct
|
|
element_info and describes the amount of bytes for the vendor information
|
|
elements.
|
|
|
|
The WMI_TLV packet is having a special WMI_TAG_ARRAY_BYTE section. This
|
|
section can have a (payload) length up to 65535 bytes because the
|
|
WMI_TLV_LEN can store up to 16 bits. The code was missing such a check and
|
|
could have created a scan request which cannot be parsed correctly by the
|
|
firmware.
|
|
|
|
But the bigger problem was the allocation of the buffer. It has to align
|
|
the TLV sections by 4 bytes. But the code was using an u8 to store the
|
|
newly calculated length of this section (with alignment). And the new
|
|
calculated length was then used to allocate the skbuff. But the actual code
|
|
to copy in the data is using the extraie.len and not the calculated
|
|
"aligned" length.
|
|
|
|
The length of extraie with IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS enabled
|
|
was 264 bytes during tests with a QCA Milan card. But it only allocated 8
|
|
bytes (264 bytes % 256) for it. As consequence, the code to memcpy the
|
|
extraie into the skb was then just overwriting data after skb->end. Things
|
|
like shinfo were therefore corrupted. This could usually be seen by a crash
|
|
in skb_zcopy_clear which tried to call a ubuf_info callback (using a bogus
|
|
address).
|
|
|
|
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-02582-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1
|
|
|
|
Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
|
|
Signed-off-by: Amutha Ravikumar <quic_aravikum@quicinc.com>
|
|
---
|
|
drivers/net/wireless/ath/ath12k/wmi.c | 6 +++---
|
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/ath/ath12k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
|
|
@@ -2950,7 +2950,7 @@ int ath12k_wmi_send_scan_start_cmd(struc
|
|
void *ptr;
|
|
int i, ret, len;
|
|
u32 *tmp_ptr;
|
|
- u8 extraie_len_with_pad = 0;
|
|
+ u16 extraie_len_with_pad = 0;
|
|
struct hint_short_ssid *s_ssid = NULL;
|
|
struct hint_bssid *hint_bssid = NULL;
|
|
|
|
@@ -2969,7 +2969,7 @@ int ath12k_wmi_send_scan_start_cmd(struc
|
|
len += sizeof(*bssid) * params->num_bssid;
|
|
|
|
len += TLV_HDR_SIZE;
|
|
- if (params->extraie.len)
|
|
+ if (params->extraie.len && params->extraie.len <= 0xFFFF)
|
|
extraie_len_with_pad =
|
|
roundup(params->extraie.len, sizeof(u32));
|
|
len += extraie_len_with_pad;
|
|
@@ -3072,7 +3072,7 @@ int ath12k_wmi_send_scan_start_cmd(struc
|
|
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, len);
|
|
ptr += TLV_HDR_SIZE;
|
|
|
|
- if (params->extraie.len)
|
|
+ if (extraie_len_with_pad)
|
|
memcpy(ptr, params->extraie.ptr,
|
|
params->extraie.len);
|
|
|