]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
smb3: Handle error case during offload read path
authorRohith Surabattula <rohiths@microsoft.com>
Thu, 29 Oct 2020 06:07:56 +0000 (06:07 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 2 Dec 2020 07:51:45 +0000 (08:51 +0100)
commit 1254100030b3377e8302f9c75090ab191d73ee7c upstream.

Mid callback needs to be called only when valid data is
read into pages.

These patches address a problem found during decryption offload:
      CIFS: VFS: trying to dequeue a deleted mid
that could cause a refcount use after free:
      Workqueue: smb3decryptd smb2_decrypt_offload [cifs]

Signed-off-by: Rohith Surabattula <rohiths@microsoft.com>
Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
CC: Stable <stable@vger.kernel.org> #5.4+
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/cifs/smb2ops.c

index 8ca43f603d8041274ceebb77a4d66533fdd25223..475c2b9e799d8917b02c5753e22eaccd0946e79a 100644 (file)
@@ -4415,7 +4415,25 @@ static void smb2_decrypt_offload(struct work_struct *work)
                                      dw->server->vals->read_rsp_size,
                                      dw->ppages, dw->npages, dw->len,
                                      true);
-               mid->callback(mid);
+               if (rc >= 0) {
+#ifdef CONFIG_CIFS_STATS2
+                       mid->when_received = jiffies;
+#endif
+                       mid->callback(mid);
+               } else {
+                       spin_lock(&GlobalMid_Lock);
+                       if (dw->server->tcpStatus == CifsNeedReconnect) {
+                               mid->mid_state = MID_RETRY_NEEDED;
+                               spin_unlock(&GlobalMid_Lock);
+                               mid->callback(mid);
+                       } else {
+                               mid->mid_state = MID_REQUEST_SUBMITTED;
+                               mid->mid_flags &= ~(MID_DELETED);
+                               list_add_tail(&mid->qhead,
+                                       &dw->server->pending_mid_q);
+                               spin_unlock(&GlobalMid_Lock);
+                       }
+               }
                cifs_mid_q_entry_release(mid);
        }