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>
Wed, 5 Feb 2020 14:18:09 +0000 (14:18 +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 120b0ff545c176410998d13149b0616c9d928a5a..d205947c4c55f3843409b606b3bd08fe18da22c2 100644 (file)
@@ -541,6 +541,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);
@@ -656,10 +657,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;
 }
 
@@ -749,10 +749,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;
 }
@@ -773,6 +772,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;