diff options
author | Arend Van Spriel <arend.vanspriel@broadcom.com> | 2017-09-12 04:47:53 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2017-09-20 00:46:29 -0400 |
commit | 17df6453d4be17910456e99c5a85025aa1b7a246 (patch) | |
tree | ef84bc921d2e6fda33f14a1c5e3af899674bbc33 /drivers/net/wireless | |
parent | 4c707c04f622a7a8570a8db6389e5a2310b92195 (diff) |
brcmfmac: add length check in brcmf_cfg80211_escan_handler()
Upon handling the firmware notification for scans the length was
checked properly and may result in corrupting kernel heap memory
due to buffer overruns. This fix addresses CVE-2017-0786.
Cc: stable@vger.kernel.org # v4.0.x
Cc: Kevin Cernekee <cernekee@chromium.org>
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index aaed4ab503ad..26a0de371c26 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | |||
@@ -3162,6 +3162,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, | |||
3162 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; | 3162 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; |
3163 | s32 status; | 3163 | s32 status; |
3164 | struct brcmf_escan_result_le *escan_result_le; | 3164 | struct brcmf_escan_result_le *escan_result_le; |
3165 | u32 escan_buflen; | ||
3165 | struct brcmf_bss_info_le *bss_info_le; | 3166 | struct brcmf_bss_info_le *bss_info_le; |
3166 | struct brcmf_bss_info_le *bss = NULL; | 3167 | struct brcmf_bss_info_le *bss = NULL; |
3167 | u32 bi_length; | 3168 | u32 bi_length; |
@@ -3181,11 +3182,23 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, | |||
3181 | 3182 | ||
3182 | if (status == BRCMF_E_STATUS_PARTIAL) { | 3183 | if (status == BRCMF_E_STATUS_PARTIAL) { |
3183 | brcmf_dbg(SCAN, "ESCAN Partial result\n"); | 3184 | brcmf_dbg(SCAN, "ESCAN Partial result\n"); |
3185 | if (e->datalen < sizeof(*escan_result_le)) { | ||
3186 | brcmf_err("invalid event data length\n"); | ||
3187 | goto exit; | ||
3188 | } | ||
3184 | escan_result_le = (struct brcmf_escan_result_le *) data; | 3189 | escan_result_le = (struct brcmf_escan_result_le *) data; |
3185 | if (!escan_result_le) { | 3190 | if (!escan_result_le) { |
3186 | brcmf_err("Invalid escan result (NULL pointer)\n"); | 3191 | brcmf_err("Invalid escan result (NULL pointer)\n"); |
3187 | goto exit; | 3192 | goto exit; |
3188 | } | 3193 | } |
3194 | escan_buflen = le32_to_cpu(escan_result_le->buflen); | ||
3195 | if (escan_buflen > BRCMF_ESCAN_BUF_SIZE || | ||
3196 | escan_buflen > e->datalen || | ||
3197 | escan_buflen < sizeof(*escan_result_le)) { | ||
3198 | brcmf_err("Invalid escan buffer length: %d\n", | ||
3199 | escan_buflen); | ||
3200 | goto exit; | ||
3201 | } | ||
3189 | if (le16_to_cpu(escan_result_le->bss_count) != 1) { | 3202 | if (le16_to_cpu(escan_result_le->bss_count) != 1) { |
3190 | brcmf_err("Invalid bss_count %d: ignoring\n", | 3203 | brcmf_err("Invalid bss_count %d: ignoring\n", |
3191 | escan_result_le->bss_count); | 3204 | escan_result_le->bss_count); |
@@ -3202,9 +3215,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, | |||
3202 | } | 3215 | } |
3203 | 3216 | ||
3204 | bi_length = le32_to_cpu(bss_info_le->length); | 3217 | bi_length = le32_to_cpu(bss_info_le->length); |
3205 | if (bi_length != (le32_to_cpu(escan_result_le->buflen) - | 3218 | if (bi_length != escan_buflen - WL_ESCAN_RESULTS_FIXED_SIZE) { |
3206 | WL_ESCAN_RESULTS_FIXED_SIZE)) { | 3219 | brcmf_err("Ignoring invalid bss_info length: %d\n", |
3207 | brcmf_err("Invalid bss_info length %d: ignoring\n", | ||
3208 | bi_length); | 3220 | bi_length); |
3209 | goto exit; | 3221 | goto exit; |
3210 | } | 3222 | } |