mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-28 01:28:59 +00:00
c52054e568
This improves FullMAC firmware compatibility, adds logging in case of
firmware crash and *may* fix "Invalid packet id" errors.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
(cherry picked from commit 8888cb725d
)
51 lines
2.1 KiB
Diff
51 lines
2.1 KiB
Diff
From e025da3d7aa4770bb1d1b3b0aa7cc4da1744852d Mon Sep 17 00:00:00 2001
|
|
From: Dan Carpenter <dan.carpenter@oracle.com>
|
|
Date: Wed, 24 Apr 2019 12:52:18 +0300
|
|
Subject: [PATCH] brcm80211: potential NULL dereference in
|
|
brcmf_cfg80211_vndr_cmds_dcmd_handler()
|
|
|
|
If "ret_len" is negative then it could lead to a NULL dereference.
|
|
|
|
The "ret_len" value comes from nl80211_vendor_cmd(), if it's negative
|
|
then we don't allocate the "dcmd_buf" buffer. Then we pass "ret_len" to
|
|
brcmf_fil_cmd_data_set() where it is cast to a very high u32 value.
|
|
Most of the functions in that call tree check whether the buffer we pass
|
|
is NULL but there are at least a couple places which don't such as
|
|
brcmf_dbg_hex_dump() and brcmf_msgbuf_query_dcmd(). We memcpy() to and
|
|
from the buffer so it would result in a NULL dereference.
|
|
|
|
The fix is to change the types so that "ret_len" can't be negative. (If
|
|
we memcpy() zero bytes to NULL, that's a no-op and doesn't cause an
|
|
issue).
|
|
|
|
Fixes: 1bacb0487d0e ("brcmfmac: replace cfg80211 testmode with vendor command")
|
|
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
|
|
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
|
---
|
|
drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c | 5 +++--
|
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
|
|
@@ -35,9 +35,10 @@ static int brcmf_cfg80211_vndr_cmds_dcmd
|
|
struct brcmf_if *ifp;
|
|
const struct brcmf_vndr_dcmd_hdr *cmdhdr = data;
|
|
struct sk_buff *reply;
|
|
- int ret, payload, ret_len;
|
|
+ unsigned int payload, ret_len;
|
|
void *dcmd_buf = NULL, *wr_pointer;
|
|
u16 msglen, maxmsglen = PAGE_SIZE - 0x100;
|
|
+ int ret;
|
|
|
|
if (len < sizeof(*cmdhdr)) {
|
|
brcmf_err("vendor command too short: %d\n", len);
|
|
@@ -65,7 +66,7 @@ static int brcmf_cfg80211_vndr_cmds_dcmd
|
|
brcmf_err("oversize return buffer %d\n", ret_len);
|
|
ret_len = BRCMF_DCMD_MAXLEN;
|
|
}
|
|
- payload = max(ret_len, len) + 1;
|
|
+ payload = max_t(unsigned int, ret_len, len) + 1;
|
|
dcmd_buf = vzalloc(payload);
|
|
if (NULL == dcmd_buf)
|
|
return -ENOMEM;
|