b4d56c34bc16361c26563dc9de084b039bcdde2b
[openwrt/staging/dangole.git] /
1 From e025da3d7aa4770bb1d1b3b0aa7cc4da1744852d Mon Sep 17 00:00:00 2001
2 From: Dan Carpenter <dan.carpenter@oracle.com>
3 Date: Wed, 24 Apr 2019 12:52:18 +0300
4 Subject: [PATCH] brcm80211: potential NULL dereference in
5 brcmf_cfg80211_vndr_cmds_dcmd_handler()
6
7 If "ret_len" is negative then it could lead to a NULL dereference.
8
9 The "ret_len" value comes from nl80211_vendor_cmd(), if it's negative
10 then we don't allocate the "dcmd_buf" buffer. Then we pass "ret_len" to
11 brcmf_fil_cmd_data_set() where it is cast to a very high u32 value.
12 Most of the functions in that call tree check whether the buffer we pass
13 is NULL but there are at least a couple places which don't such as
14 brcmf_dbg_hex_dump() and brcmf_msgbuf_query_dcmd(). We memcpy() to and
15 from the buffer so it would result in a NULL dereference.
16
17 The fix is to change the types so that "ret_len" can't be negative. (If
18 we memcpy() zero bytes to NULL, that's a no-op and doesn't cause an
19 issue).
20
21 Fixes: 1bacb0487d0e ("brcmfmac: replace cfg80211 testmode with vendor command")
22 Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
23 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
24 ---
25 drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c | 5 +++--
26 1 file changed, 3 insertions(+), 2 deletions(-)
27
28 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
29 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
30 @@ -35,9 +35,10 @@ static int brcmf_cfg80211_vndr_cmds_dcmd
31 struct brcmf_if *ifp;
32 const struct brcmf_vndr_dcmd_hdr *cmdhdr = data;
33 struct sk_buff *reply;
34 - int ret, payload, ret_len;
35 + unsigned int payload, ret_len;
36 void *dcmd_buf = NULL, *wr_pointer;
37 u16 msglen, maxmsglen = PAGE_SIZE - 0x100;
38 + int ret;
39
40 if (len < sizeof(*cmdhdr)) {
41 brcmf_err("vendor command too short: %d\n", len);
42 @@ -65,7 +66,7 @@ static int brcmf_cfg80211_vndr_cmds_dcmd
43 brcmf_err("oversize return buffer %d\n", ret_len);
44 ret_len = BRCMF_DCMD_MAXLEN;
45 }
46 - payload = max(ret_len, len) + 1;
47 + payload = max_t(unsigned int, ret_len, len) + 1;
48 dcmd_buf = vzalloc(payload);
49 if (NULL == dcmd_buf)
50 return -ENOMEM;