On 11/11/2022 8:53 AM, Minsuk Kang wrote:
This patch fixes slab-out-of-bounds reads in brcmfmac that occur in brcmf_construct_chaninfo() and brcmf_enable_bw40_2g() when the count value of channel specifications provided by the device is greater than the length of 'list->element[]', decided by the size of the 'list' allocated with kzalloc(). The patch adds checks that make the functions free the buffer and return -EINVAL if that is the case. Note that the negative return is handled by the caller, brcmf_setup_wiphybands() or brcmf_cfg80211_attach(). Found by a modified version of syzkaller.
[snip]
Reported-by: Dokyung Song <dokyungs@xxxxxxxxxxxx> Reported-by: Jisoo Jang <jisoo.jang@xxxxxxxxxxxx> Reported-by: Minsuk Kang <linuxlovemin@xxxxxxxxxxxx> Signed-off-by: Minsuk Kang <linuxlovemin@xxxxxxxxxxxx> --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index ae9507dec74a..3a1c0743e19c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -6840,6 +6840,13 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, band->channels[i].flags = IEEE80211_CHAN_DISABLED;total = le32_to_cpu(list->count);+ if (total > BRCMF_DCMD_MEDLEN / sizeof(__le32) - 1) {
Please add and use macro definition here: #define BRCMF_MAX_CHANSPEC_LIST (BRCMF_DCMD_MEDLEN / sizeof(__le32) - 1)
+ bphy_err(drvr, "Invalid count of channel Spec. (%u)\n", + total); + err = -EINVAL; + goto fail_pbuf; + } + for (i = 0; i < total; i++) { ch.chspec = (u16)le32_to_cpu(list->element[i]); cfg->d11inf.decchspec(&ch); @@ -6985,6 +6992,13 @@ static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg) band = cfg_to_wiphy(cfg)->bands[NL80211_BAND_2GHZ]; list = (struct brcmf_chanspec_list *)pbuf; num_chan = le32_to_cpu(list->count); + if (num_chan > BRCMF_DCMD_MEDLEN / sizeof(__le32) - 1) {
...and here.
+ bphy_err(drvr, "Invalid count of channel Spec. (%u)\n", + num_chan); + kfree(pbuf); + return -EINVAL; + } + for (i = 0; i < num_chan; i++) { ch.chspec = (u16)le32_to_cpu(list->element[i]); cfg->d11inf.decchspec(&ch);
Attachment:
smime.p7s
Description: S/MIME Cryptographic Signature