Skip to content

Commit d95984b

Browse files
Po-Hao HuangKalle Valo
authored andcommitted
rtw88: fix memory overrun and memory leak during hw_scan
Previously we allocated less memory than actual required, overwrite to the buffer causes the mm module to complaint and raise access violation faults. Along with potential memory leaks when returned early. Fix these by passing the correct size and proper deinit flow. Fixes: 10d162b ("rtw88: 8822c: add ieee80211_ops::hw_scan") Signed-off-by: Po-Hao Huang <[email protected]> Signed-off-by: Ping-Ke Shih <[email protected]> Signed-off-by: Kalle Valo <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent c17f271 commit d95984b

File tree

1 file changed

+24
-10
lines changed
  • drivers/net/wireless/realtek/rtw88

1 file changed

+24
-10
lines changed

drivers/net/wireless/realtek/rtw88/fw.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1784,9 +1784,9 @@ void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start)
17841784
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
17851785
}
17861786

1787-
static void rtw_append_probe_req_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
1788-
struct sk_buff_head *list,
1789-
struct rtw_vif *rtwvif)
1787+
static int rtw_append_probe_req_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
1788+
struct sk_buff_head *list, u8 *bands,
1789+
struct rtw_vif *rtwvif)
17901790
{
17911791
struct ieee80211_scan_ies *ies = rtwvif->scan_ies;
17921792
struct rtw_chip_info *chip = rtwdev->chip;
@@ -1797,19 +1797,24 @@ static void rtw_append_probe_req_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
17971797
if (!(BIT(idx) & chip->band))
17981798
continue;
17991799
new = skb_copy(skb, GFP_KERNEL);
1800+
if (!new)
1801+
return -ENOMEM;
18001802
skb_put_data(new, ies->ies[idx], ies->len[idx]);
18011803
skb_put_data(new, ies->common_ies, ies->common_ie_len);
18021804
skb_queue_tail(list, new);
1805+
(*bands)++;
18031806
}
1807+
1808+
return 0;
18041809
}
18051810

1806-
static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_ssids,
1811+
static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_probes,
18071812
struct sk_buff_head *probe_req_list)
18081813
{
18091814
struct rtw_chip_info *chip = rtwdev->chip;
18101815
struct sk_buff *skb, *tmp;
18111816
u8 page_offset = 1, *buf, page_size = chip->page_size;
1812-
u8 pages = page_offset + num_ssids * RTW_PROBE_PG_CNT;
1817+
u8 pages = page_offset + num_probes * RTW_PROBE_PG_CNT;
18131818
u16 pg_addr = rtwdev->fifo.rsvd_h2c_info_addr, loc;
18141819
u16 buf_offset = page_size * page_offset;
18151820
u8 tx_desc_sz = chip->tx_pkt_desc_sz;
@@ -1848,6 +1853,8 @@ static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_ssids,
18481853
rtwdev->scan_info.probe_pg_size = page_offset;
18491854
out:
18501855
kfree(buf);
1856+
skb_queue_walk(probe_req_list, skb)
1857+
kfree_skb(skb);
18511858

18521859
return ret;
18531860
}
@@ -1858,27 +1865,34 @@ static int rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev,
18581865
struct cfg80211_scan_request *req = rtwvif->scan_req;
18591866
struct sk_buff_head list;
18601867
struct sk_buff *skb;
1861-
u8 num = req->n_ssids, i;
1868+
u8 num = req->n_ssids, i, bands = 0;
1869+
int ret;
18621870

18631871
skb_queue_head_init(&list);
18641872
for (i = 0; i < num; i++) {
18651873
skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr,
18661874
req->ssids[i].ssid,
18671875
req->ssids[i].ssid_len,
18681876
req->ie_len);
1869-
if (!skb)
1877+
if (!skb) {
1878+
ret = -ENOMEM;
18701879
goto out;
1871-
rtw_append_probe_req_ie(rtwdev, skb, &list, rtwvif);
1880+
}
1881+
ret = rtw_append_probe_req_ie(rtwdev, skb, &list, &bands,
1882+
rtwvif);
1883+
if (ret)
1884+
goto out;
1885+
18721886
kfree_skb(skb);
18731887
}
18741888

1875-
return _rtw_hw_scan_update_probe_req(rtwdev, num, &list);
1889+
return _rtw_hw_scan_update_probe_req(rtwdev, num * bands, &list);
18761890

18771891
out:
18781892
skb_queue_walk(&list, skb)
18791893
kfree_skb(skb);
18801894

1881-
return -ENOMEM;
1895+
return ret;
18821896
}
18831897

18841898
static int rtw_add_chan_info(struct rtw_dev *rtwdev, struct rtw_chan_info *info,

0 commit comments

Comments
 (0)