cd2279dd65c819b2890dead015622913441aca96
[oweals/openwrt.git] /
1 From 0b5c0305e57ca940713bcb2b202fd2b412c62f31 Mon Sep 17 00:00:00 2001
2 From: Arend Van Spriel <arend.vanspriel@broadcom.com>
3 Date: Tue, 3 Apr 2018 10:18:15 +0200
4 Subject: [PATCH] brcmfmac: fix firmware request processing if nvram load fails
5
6 When nvram loading fails a double free occurred. Fix this and reorg the
7 code a little.
8
9 Fixes: d09ae51a4b67 ("brcmfmac: pass struct in brcmf_fw_get_firmwares()")
10 Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
11 Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
12 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
13 ---
14  .../broadcom/brcm80211/brcmfmac/firmware.c         | 36 ++++++++++++----------
15  1 file changed, 20 insertions(+), 16 deletions(-)
16
17 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
18 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
19 @@ -459,7 +459,7 @@ static void brcmf_fw_free_request(struct
20         kfree(req);
21  }
22  
23 -static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
24 +static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
25  {
26         struct brcmf_fw *fwctx = ctx;
27         struct brcmf_fw_item *cur;
28 @@ -498,13 +498,10 @@ static void brcmf_fw_request_nvram_done(
29         brcmf_dbg(TRACE, "nvram %p len %d\n", nvram, nvram_length);
30         cur->nv_data.data = nvram;
31         cur->nv_data.len = nvram_length;
32 -       return;
33 +       return 0;
34  
35  fail:
36 -       brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
37 -       fwctx->done(fwctx->dev, -ENOENT, NULL);
38 -       brcmf_fw_free_request(fwctx->req);
39 -       kfree(fwctx);
40 +       return -ENOENT;
41  }
42  
43  static int brcmf_fw_request_next_item(struct brcmf_fw *fwctx, bool async)
44 @@ -553,20 +550,27 @@ static void brcmf_fw_request_done(const
45         brcmf_dbg(TRACE, "enter: firmware %s %sfound\n", cur->path,
46                   fw ? "" : "not ");
47  
48 -       if (fw) {
49 -               if (cur->type == BRCMF_FW_TYPE_BINARY)
50 -                       cur->binary = fw;
51 -               else if (cur->type == BRCMF_FW_TYPE_NVRAM)
52 -                       brcmf_fw_request_nvram_done(fw, fwctx);
53 -               else
54 -                       release_firmware(fw);
55 -       } else if (cur->type == BRCMF_FW_TYPE_NVRAM) {
56 -               brcmf_fw_request_nvram_done(NULL, fwctx);
57 -       } else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL)) {
58 +       if (!fw)
59                 ret = -ENOENT;
60 +
61 +       switch (cur->type) {
62 +       case BRCMF_FW_TYPE_NVRAM:
63 +               ret = brcmf_fw_request_nvram_done(fw, fwctx);
64 +               break;
65 +       case BRCMF_FW_TYPE_BINARY:
66 +               cur->binary = fw;
67 +               break;
68 +       default:
69 +               /* something fishy here so bail out early */
70 +               brcmf_err("unknown fw type: %d\n", cur->type);
71 +               release_firmware(fw);
72 +               ret = -EINVAL;
73                 goto fail;
74         }
75  
76 +       if (ret < 0 && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
77 +               goto fail;
78 +
79         do {
80                 if (++fwctx->curpos == fwctx->req->n_items) {
81                         ret = 0;