347-v5.2-brcm80211-potential-NULL-dereference-in-brcmf_cfg802.patch 2.1 KB

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