rsi: fix use-after-free on probe errors
authorJohan Hovold <johan@kernel.org>
Thu, 28 Nov 2019 17:22:01 +0000 (18:22 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 1 Feb 2020 09:37:11 +0000 (09:37 +0000)
commit 92aafe77123ab478e5f5095878856ab0424910da upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/wireless/rsi/rsi_91x_hal.c

index 01edf96..a7b341e 100644 (file)
@@ -616,6 +616,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);
@@ -731,10 +732,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;
 }
 
@@ -822,10 +822,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;
 }
@@ -846,6 +845,7 @@ static int rsi_load_firmware(struct rsi_hw *adapter)
                status = hif_ops->master_reg_read(adapter, SWBL_REGOUT,
                                              &regout_val, 2);
                if (status < 0) {
+                       bl_stop_cmd_timer(adapter);
                        rsi_dbg(ERR_ZONE,
                                "%s: REGOUT read failed\n", __func__);
                        return status;