OSDN Git Service

rsi: fix use-after-free on probe errors
authorJohan Hovold <johan@kernel.org>
Thu, 28 Nov 2019 17:22:01 +0000 (18:22 +0100)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 18 Dec 2019 18:57:04 +0000 (20:57 +0200)
The driver would fail to stop the command timer in most error paths,
something which specifically could lead to the timer being freed while
still active on I/O errors during probe.

Fix this by making sure that each function starting the timer also stops
it in all relevant error paths.

Reported-by: syzbot+1d1597a5aa3679c65b9f@syzkaller.appspotmail.com
Fixes: b78e91bcfb33 ("rsi: Add new firmware loading method")
Cc: stable <stable@vger.kernel.org> # 4.12
Cc: Prameela Rani Garnepudi <prameela.j04cs@gmail.com>
Cc: Amitkumar Karwar <amit.karwar@redpinesignals.com>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/rsi/rsi_91x_hal.c

index f84250b..6f8d5f9 100644 (file)
@@ -622,6 +622,7 @@ static int bl_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, char *str)
        bl_start_cmd_timer(adapter, timeout);
        status = bl_write_cmd(adapter, cmd, exp_resp, &regout_val);
        if (status < 0) {
+               bl_stop_cmd_timer(adapter);
                rsi_dbg(ERR_ZONE,
                        "%s: Command %s (%0x) writing failed..\n",
                        __func__, str, cmd);
@@ -737,10 +738,9 @@ static int ping_pong_write(struct rsi_hw *adapter, u8 cmd, u8 *addr, u32 size)
        }
 
        status = bl_cmd(adapter, cmd_req, cmd_resp, str);
-       if (status) {
-               bl_stop_cmd_timer(adapter);
+       if (status)
                return status;
-       }
+
        return 0;
 }
 
@@ -828,10 +828,9 @@ static int auto_fw_upgrade(struct rsi_hw *adapter, u8 *flash_content,
 
        status = bl_cmd(adapter, EOF_REACHED, FW_LOADING_SUCCESSFUL,
                        "EOF_REACHED");
-       if (status) {
-               bl_stop_cmd_timer(adapter);
+       if (status)
                return status;
-       }
+
        rsi_dbg(INFO_ZONE, "FW loading is done and FW is running..\n");
        return 0;
 }
@@ -849,6 +848,7 @@ static int rsi_hal_prepare_fwload(struct rsi_hw *adapter)
                                                  &regout_val,
                                                  RSI_COMMON_REG_SIZE);
                if (status < 0) {
+                       bl_stop_cmd_timer(adapter);
                        rsi_dbg(ERR_ZONE,
                                "%s: REGOUT read failed\n", __func__);
                        return status;