--- /dev/null
+From 98128572084c3dd8067f48bb588aa3733d1355b5 Mon Sep 17 00:00:00 2001
+From: Namjae Jeon <namjae.jeon@samsung.com>
+Date: Mon, 9 Nov 2020 17:35:33 +0900
+Subject: cifs: fix a memleak with modefromsid
+
+From: Namjae Jeon <namjae.jeon@samsung.com>
+
+commit 98128572084c3dd8067f48bb588aa3733d1355b5 upstream.
+
+kmemleak reported a memory leak allocated in query_info() when cifs is
+working with modefromsid.
+
+ backtrace:
+ [<00000000aeef6a1e>] slab_post_alloc_hook+0x58/0x510
+ [<00000000b2f7a440>] __kmalloc+0x1a0/0x390
+ [<000000006d470ebc>] query_info+0x5b5/0x700 [cifs]
+ [<00000000bad76ce0>] SMB2_query_acl+0x2b/0x30 [cifs]
+ [<000000001fa09606>] get_smb2_acl_by_path+0x2f3/0x720 [cifs]
+ [<000000001b6ebab7>] get_smb2_acl+0x75/0x90 [cifs]
+ [<00000000abf43904>] cifs_acl_to_fattr+0x13b/0x1d0 [cifs]
+ [<00000000a5372ec3>] cifs_get_inode_info+0x4cd/0x9a0 [cifs]
+ [<00000000388e0a04>] cifs_revalidate_dentry_attr+0x1cd/0x510 [cifs]
+ [<0000000046b6b352>] cifs_getattr+0x8a/0x260 [cifs]
+ [<000000007692c95e>] vfs_getattr_nosec+0xa1/0xc0
+ [<00000000cbc7d742>] vfs_getattr+0x36/0x40
+ [<00000000de8acf67>] vfs_statx_fd+0x4a/0x80
+ [<00000000a58c6adb>] __do_sys_newfstat+0x31/0x70
+ [<00000000300b3b4e>] __x64_sys_newfstat+0x16/0x20
+ [<000000006d8e9c48>] do_syscall_64+0x37/0x80
+
+This patch add missing kfree for pntsd when mounting modefromsid option.
+
+Cc: Stable <stable@vger.kernel.org> # v5.4+
+Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
+Reviewed-by: Aurelien Aptel <aaptel@suse.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifsacl.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/cifs/cifsacl.c
++++ b/fs/cifs/cifsacl.c
+@@ -1266,6 +1266,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *c
+ cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
+ } else if (mode_from_special_sid) {
+ rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
++ kfree(pntsd);
+ } else {
+ /* get approximated mode from ACL */
+ rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
--- /dev/null
+From 073861ed77b6b957c3c8d54a11dc503f7d986ceb Mon Sep 17 00:00:00 2001
+From: Hugh Dickins <hughd@google.com>
+Date: Tue, 24 Nov 2020 08:46:43 -0800
+Subject: mm: fix VM_BUG_ON(PageTail) and BUG_ON(PageWriteback)
+
+From: Hugh Dickins <hughd@google.com>
+
+commit 073861ed77b6b957c3c8d54a11dc503f7d986ceb upstream.
+
+Twice now, when exercising ext4 looped on shmem huge pages, I have crashed
+on the PF_ONLY_HEAD check inside PageWaiters(): ext4_finish_bio() calling
+end_page_writeback() calling wake_up_page() on tail of a shmem huge page,
+no longer an ext4 page at all.
+
+The problem is that PageWriteback is not accompanied by a page reference
+(as the NOTE at the end of test_clear_page_writeback() acknowledges): as
+soon as TestClearPageWriteback has been done, that page could be removed
+from page cache, freed, and reused for something else by the time that
+wake_up_page() is reached.
+
+https://lore.kernel.org/linux-mm/20200827122019.GC14765@casper.infradead.org/
+Matthew Wilcox suggested avoiding or weakening the PageWaiters() tail
+check; but I'm paranoid about even looking at an unreferenced struct page,
+lest its memory might itself have already been reused or hotremoved (and
+wake_up_page_bit() may modify that memory with its ClearPageWaiters()).
+
+Then on crashing a second time, realized there's a stronger reason against
+that approach. If my testing just occasionally crashes on that check,
+when the page is reused for part of a compound page, wouldn't it be much
+more common for the page to get reused as an order-0 page before reaching
+wake_up_page()? And on rare occasions, might that reused page already be
+marked PageWriteback by its new user, and already be waited upon? What
+would that look like?
+
+It would look like BUG_ON(PageWriteback) after wait_on_page_writeback()
+in write_cache_pages() (though I have never seen that crash myself).
+
+Matthew Wilcox explaining this to himself:
+ "page is allocated, added to page cache, dirtied, writeback starts,
+
+ --- thread A ---
+ filesystem calls end_page_writeback()
+ test_clear_page_writeback()
+ --- context switch to thread B ---
+ truncate_inode_pages_range() finds the page, it doesn't have writeback set,
+ we delete it from the page cache. Page gets reallocated, dirtied, writeback
+ starts again. Then we call write_cache_pages(), see
+ PageWriteback() set, call wait_on_page_writeback()
+ --- context switch back to thread A ---
+ wake_up_page(page, PG_writeback);
+ ... thread B is woken, but because the wakeup was for the old use of
+ the page, PageWriteback is still set.
+
+ Devious"
+
+And prior to 2a9127fcf229 ("mm: rewrite wait_on_page_bit_common() logic")
+this would have been much less likely: before that, wake_page_function()'s
+non-exclusive case would stop walking and not wake if it found Writeback
+already set again; whereas now the non-exclusive case proceeds to wake.
+
+I have not thought of a fix that does not add a little overhead: the
+simplest fix is for end_page_writeback() to get_page() before calling
+test_clear_page_writeback(), then put_page() after wake_up_page().
+
+Was there a chance of missed wakeups before, since a page freed before
+reaching wake_up_page() would have PageWaiters cleared? I think not,
+because each waiter does hold a reference on the page. This bug comes
+when the old use of the page, the one we do TestClearPageWriteback on,
+had *no* waiters, so no additional page reference beyond the page cache
+(and whoever racily freed it). The reuse of the page has a waiter
+holding a reference, and its own PageWriteback set; but the belated
+wake_up_page() has woken the reuse to hit that BUG_ON(PageWriteback).
+
+Reported-by: syzbot+3622cea378100f45d59f@syzkaller.appspotmail.com
+Reported-by: Qian Cai <cai@lca.pw>
+Fixes: 2a9127fcf229 ("mm: rewrite wait_on_page_bit_common() logic")
+Signed-off-by: Hugh Dickins <hughd@google.com>
+Cc: stable@vger.kernel.org # v5.8+
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/filemap.c | 8 ++++++++
+ mm/page-writeback.c | 6 ------
+ 2 files changed, 8 insertions(+), 6 deletions(-)
+
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -1464,11 +1464,19 @@ void end_page_writeback(struct page *pag
+ rotate_reclaimable_page(page);
+ }
+
++ /*
++ * Writeback does not hold a page reference of its own, relying
++ * on truncation to wait for the clearing of PG_writeback.
++ * But here we must make sure that the page is not freed and
++ * reused before the wake_up_page().
++ */
++ get_page(page);
+ if (!test_clear_page_writeback(page))
+ BUG();
+
+ smp_mb__after_atomic();
+ wake_up_page(page, PG_writeback);
++ put_page(page);
+ }
+ EXPORT_SYMBOL(end_page_writeback);
+
+--- a/mm/page-writeback.c
++++ b/mm/page-writeback.c
+@@ -2754,12 +2754,6 @@ int test_clear_page_writeback(struct pag
+ } else {
+ ret = TestClearPageWriteback(page);
+ }
+- /*
+- * NOTE: Page might be free now! Writeback doesn't hold a page
+- * reference on its own, it relies on truncation to wait for
+- * the clearing of PG_writeback. The below can only access
+- * page state that is static across allocation cycles.
+- */
+ if (ret) {
+ dec_lruvec_state(lruvec, NR_WRITEBACK);
+ dec_zone_page_state(page, NR_ZONE_WRITE_PENDING);
--- /dev/null
+From 1179f170b6f0af7bb0b3b7628136eaac450ddf31 Mon Sep 17 00:00:00 2001
+From: Sven Schnelle <svens@linux.ibm.com>
+Date: Fri, 20 Nov 2020 14:17:52 +0100
+Subject: s390: fix fpu restore in entry.S
+
+From: Sven Schnelle <svens@linux.ibm.com>
+
+commit 1179f170b6f0af7bb0b3b7628136eaac450ddf31 upstream.
+
+We need to disable interrupts in load_fpu_regs(). Otherwise an
+interrupt might come in after the registers are loaded, but before
+CIF_FPU is cleared in load_fpu_regs(). When the interrupt returns,
+CIF_FPU will be cleared and the registers will never be restored.
+
+The entry.S code usually saves the interrupt state in __SF_EMPTY on the
+stack when disabling/restoring interrupts. sie64a however saves the pointer
+to the sie control block in __SF_SIE_CONTROL, which references the same
+location. This is non-obvious to the reader. To avoid thrashing the sie
+control block pointer in load_fpu_regs(), move the __SIE_* offsets eight
+bytes after __SF_EMPTY on the stack.
+
+Cc: <stable@vger.kernel.org> # 5.8
+Fixes: 0b0ed657fe00 ("s390: remove critical section cleanup from entry.S")
+Reported-by: Pierre Morel <pmorel@linux.ibm.com>
+Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
+Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
+Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/s390/kernel/asm-offsets.c | 10 +++++-----
+ arch/s390/kernel/entry.S | 2 ++
+ 2 files changed, 7 insertions(+), 5 deletions(-)
+
+--- a/arch/s390/kernel/asm-offsets.c
++++ b/arch/s390/kernel/asm-offsets.c
+@@ -53,11 +53,11 @@ int main(void)
+ /* stack_frame offsets */
+ OFFSET(__SF_BACKCHAIN, stack_frame, back_chain);
+ OFFSET(__SF_GPRS, stack_frame, gprs);
+- OFFSET(__SF_EMPTY, stack_frame, empty1);
+- OFFSET(__SF_SIE_CONTROL, stack_frame, empty1[0]);
+- OFFSET(__SF_SIE_SAVEAREA, stack_frame, empty1[1]);
+- OFFSET(__SF_SIE_REASON, stack_frame, empty1[2]);
+- OFFSET(__SF_SIE_FLAGS, stack_frame, empty1[3]);
++ OFFSET(__SF_EMPTY, stack_frame, empty1[0]);
++ OFFSET(__SF_SIE_CONTROL, stack_frame, empty1[1]);
++ OFFSET(__SF_SIE_SAVEAREA, stack_frame, empty1[2]);
++ OFFSET(__SF_SIE_REASON, stack_frame, empty1[3]);
++ OFFSET(__SF_SIE_FLAGS, stack_frame, empty1[4]);
+ BLANK();
+ /* timeval/timezone offsets for use by vdso */
+ OFFSET(__VDSO_UPD_COUNT, vdso_data, tb_update_count);
+--- a/arch/s390/kernel/entry.S
++++ b/arch/s390/kernel/entry.S
+@@ -1072,6 +1072,7 @@ EXPORT_SYMBOL(save_fpu_regs)
+ * %r4
+ */
+ load_fpu_regs:
++ stnsm __SF_EMPTY(%r15),0xfc
+ lg %r4,__LC_CURRENT
+ aghi %r4,__TASK_thread
+ TSTMSK __LC_CPU_FLAGS,_CIF_FPU
+@@ -1103,6 +1104,7 @@ load_fpu_regs:
+ .Lload_fpu_regs_done:
+ ni __LC_CPU_FLAGS+7,255-_CIF_FPU
+ .Lload_fpu_regs_exit:
++ ssm __SF_EMPTY(%r15)
+ BR_EX %r14
+ .Lload_fpu_regs_end:
+ ENDPROC(load_fpu_regs)
spi-bcm2835-fix-use-after-free-on-unbind.patch
ipv4-use-is_enabled-instead-of-ifdef.patch
rtc-pcf2127-fix-a-bug-when-not-specify-interrupts-property.patch
+s390-fix-fpu-restore-in-entry.s.patch
+mm-fix-vm_bug_on-pagetail-and-bug_on-pagewriteback.patch
+smb3-call-cifs-reconnect-from-demultiplex-thread.patch
+smb3-avoid-mid-pending-list-corruption.patch
+smb3-handle-error-case-during-offload-read-path.patch
+cifs-fix-a-memleak-with-modefromsid.patch
--- /dev/null
+From ac873aa3dc21707c47db5db6608b38981c731afe Mon Sep 17 00:00:00 2001
+From: Rohith Surabattula <rohiths@microsoft.com>
+Date: Thu, 29 Oct 2020 05:03:10 +0000
+Subject: smb3: Avoid Mid pending list corruption
+
+From: Rohith Surabattula <rohiths@microsoft.com>
+
+commit ac873aa3dc21707c47db5db6608b38981c731afe upstream.
+
+When reconnect happens Mid queue can be corrupted when both
+demultiplex and offload thread try to dequeue the MID from the
+pending list.
+
+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 | 55 +++++++++++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 46 insertions(+), 9 deletions(-)
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -262,7 +262,7 @@ smb2_revert_current_mid(struct TCP_Serve
+ }
+
+ static struct mid_q_entry *
+-smb2_find_mid(struct TCP_Server_Info *server, char *buf)
++__smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue)
+ {
+ struct mid_q_entry *mid;
+ struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
+@@ -279,6 +279,10 @@ smb2_find_mid(struct TCP_Server_Info *se
+ (mid->mid_state == MID_REQUEST_SUBMITTED) &&
+ (mid->command == shdr->Command)) {
+ kref_get(&mid->refcount);
++ if (dequeue) {
++ list_del_init(&mid->qhead);
++ mid->mid_flags |= MID_DELETED;
++ }
+ spin_unlock(&GlobalMid_Lock);
+ return mid;
+ }
+@@ -287,6 +291,18 @@ smb2_find_mid(struct TCP_Server_Info *se
+ return NULL;
+ }
+
++static struct mid_q_entry *
++smb2_find_mid(struct TCP_Server_Info *server, char *buf)
++{
++ return __smb2_find_mid(server, buf, false);
++}
++
++static struct mid_q_entry *
++smb2_find_dequeue_mid(struct TCP_Server_Info *server, char *buf)
++{
++ return __smb2_find_mid(server, buf, true);
++}
++
+ static void
+ smb2_dump_detail(void *buf, struct TCP_Server_Info *server)
+ {
+@@ -4260,7 +4276,10 @@ handle_read_data(struct TCP_Server_Info
+ cifs_dbg(FYI, "%s: server returned error %d\n",
+ __func__, rdata->result);
+ /* normal error on read response */
+- dequeue_mid(mid, false);
++ if (is_offloaded)
++ mid->mid_state = MID_RESPONSE_RECEIVED;
++ else
++ dequeue_mid(mid, false);
+ return 0;
+ }
+
+@@ -4284,7 +4303,10 @@ handle_read_data(struct TCP_Server_Info
+ cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
+ __func__, data_offset);
+ rdata->result = -EIO;
+- dequeue_mid(mid, rdata->result);
++ if (is_offloaded)
++ mid->mid_state = MID_RESPONSE_MALFORMED;
++ else
++ dequeue_mid(mid, rdata->result);
+ return 0;
+ }
+
+@@ -4300,21 +4322,30 @@ handle_read_data(struct TCP_Server_Info
+ cifs_dbg(FYI, "%s: data offset (%u) beyond 1st page of response\n",
+ __func__, data_offset);
+ rdata->result = -EIO;
+- dequeue_mid(mid, rdata->result);
++ if (is_offloaded)
++ mid->mid_state = MID_RESPONSE_MALFORMED;
++ else
++ dequeue_mid(mid, rdata->result);
+ return 0;
+ }
+
+ if (data_len > page_data_size - pad_len) {
+ /* data_len is corrupt -- discard frame */
+ rdata->result = -EIO;
+- dequeue_mid(mid, rdata->result);
++ if (is_offloaded)
++ mid->mid_state = MID_RESPONSE_MALFORMED;
++ else
++ dequeue_mid(mid, rdata->result);
+ return 0;
+ }
+
+ rdata->result = init_read_bvec(pages, npages, page_data_size,
+ cur_off, &bvec);
+ if (rdata->result != 0) {
+- dequeue_mid(mid, rdata->result);
++ if (is_offloaded)
++ mid->mid_state = MID_RESPONSE_MALFORMED;
++ else
++ dequeue_mid(mid, rdata->result);
+ return 0;
+ }
+
+@@ -4329,7 +4360,10 @@ handle_read_data(struct TCP_Server_Info
+ /* read response payload cannot be in both buf and pages */
+ WARN_ONCE(1, "buf can not contain only a part of read data");
+ rdata->result = -EIO;
+- dequeue_mid(mid, rdata->result);
++ if (is_offloaded)
++ mid->mid_state = MID_RESPONSE_MALFORMED;
++ else
++ dequeue_mid(mid, rdata->result);
+ return 0;
+ }
+
+@@ -4340,7 +4374,10 @@ handle_read_data(struct TCP_Server_Info
+ if (length < 0)
+ return length;
+
+- dequeue_mid(mid, false);
++ if (is_offloaded)
++ mid->mid_state = MID_RESPONSE_RECEIVED;
++ else
++ dequeue_mid(mid, false);
+ return length;
+ }
+
+@@ -4369,7 +4406,7 @@ static void smb2_decrypt_offload(struct
+ }
+
+ dw->server->lstrp = jiffies;
+- mid = smb2_find_mid(dw->server, dw->buf);
++ mid = smb2_find_dequeue_mid(dw->server, dw->buf);
+ if (mid == NULL)
+ cifs_dbg(FYI, "mid not found\n");
+ else {
--- /dev/null
+From de9ac0a6e9efdffc8cde18781f48fb56ca4157b7 Mon Sep 17 00:00:00 2001
+From: Rohith Surabattula <rohiths@microsoft.com>
+Date: Wed, 28 Oct 2020 13:42:21 +0000
+Subject: smb3: Call cifs reconnect from demultiplex thread
+
+From: Rohith Surabattula <rohiths@microsoft.com>
+
+commit de9ac0a6e9efdffc8cde18781f48fb56ca4157b7 upstream.
+
+cifs_reconnect needs to be called only from demultiplex thread.
+skip cifs_reconnect in offload thread. So, cifs_reconnect will be
+called by demultiplex thread in subsequent request.
+
+These patches address a problem found during decryption offload:
+ CIFS: VFS: trying to dequeue a deleted mid
+that can cause a refcount use after free:
+
+[ 1271.389453] Workqueue: smb3decryptd smb2_decrypt_offload [cifs]
+[ 1271.389456] RIP: 0010:refcount_warn_saturate+0xae/0xf0
+[ 1271.389457] Code: fa 1d 6a 01 01 e8 c7 44 b1 ff 0f 0b 5d c3 80 3d e7 1d 6a 01 00 75 91 48 c7 c7 d8 be 1d a2 c6 05 d7 1d 6a 01 01 e8 a7 44 b1 ff <0f> 0b 5d c3 80 3d c5 1d 6a 01 00 0f 85 6d ff ff ff 48 c7 c7 30 bf
+[ 1271.389458] RSP: 0018:ffffa4cdc1f87e30 EFLAGS: 00010286
+[ 1271.389458] RAX: 0000000000000000 RBX: ffff9974d2809f00 RCX: ffff9974df898cc8
+[ 1271.389459] RDX: 00000000ffffffd8 RSI: 0000000000000027 RDI: ffff9974df898cc0
+[ 1271.389460] RBP: ffffa4cdc1f87e30 R08: 0000000000000004 R09: 00000000000002c0
+[ 1271.389460] R10: 0000000000000000 R11: 0000000000000001 R12: ffff9974b7fdb5c0
+[ 1271.389461] R13: ffff9974d2809f00 R14: ffff9974ccea0a80 R15: ffff99748e60db80
+[ 1271.389462] FS: 0000000000000000(0000) GS:ffff9974df880000(0000) knlGS:0000000000000000
+[ 1271.389462] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 1271.389463] CR2: 000055c60f344fe4 CR3: 0000001031a3c002 CR4: 00000000003706e0
+[ 1271.389465] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[ 1271.389465] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[ 1271.389466] Call Trace:
+[ 1271.389483] cifs_mid_q_entry_release+0xce/0x110 [cifs]
+[ 1271.389499] smb2_decrypt_offload+0xa9/0x1c0 [cifs]
+[ 1271.389501] process_one_work+0x1e8/0x3b0
+[ 1271.389503] worker_thread+0x50/0x370
+[ 1271.389504] kthread+0x12f/0x150
+[ 1271.389506] ? process_one_work+0x3b0/0x3b0
+[ 1271.389507] ? __kthread_bind_mask+0x70/0x70
+[ 1271.389509] ret_from_fork+0x22/0x30
+
+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 | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -4212,7 +4212,8 @@ init_read_bvec(struct page **pages, unsi
+ static int
+ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
+ char *buf, unsigned int buf_len, struct page **pages,
+- unsigned int npages, unsigned int page_data_size)
++ unsigned int npages, unsigned int page_data_size,
++ bool is_offloaded)
+ {
+ unsigned int data_offset;
+ unsigned int data_len;
+@@ -4234,7 +4235,8 @@ handle_read_data(struct TCP_Server_Info
+
+ if (server->ops->is_session_expired &&
+ server->ops->is_session_expired(buf)) {
+- cifs_reconnect(server);
++ if (!is_offloaded)
++ cifs_reconnect(server);
+ return -1;
+ }
+
+@@ -4374,7 +4376,8 @@ static void smb2_decrypt_offload(struct
+ mid->decrypted = true;
+ rc = handle_read_data(dw->server, mid, dw->buf,
+ dw->server->vals->read_rsp_size,
+- dw->ppages, dw->npages, dw->len);
++ dw->ppages, dw->npages, dw->len,
++ true);
+ mid->callback(mid);
+ cifs_mid_q_entry_release(mid);
+ }
+@@ -4478,7 +4481,7 @@ non_offloaded_decrypt:
+ (*mid)->decrypted = true;
+ rc = handle_read_data(server, *mid, buf,
+ server->vals->read_rsp_size,
+- pages, npages, len);
++ pages, npages, len, false);
+ }
+
+ free_pages:
+@@ -4621,7 +4624,7 @@ smb3_handle_read_data(struct TCP_Server_
+ char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
+
+ return handle_read_data(server, mid, buf, server->pdu_size,
+- NULL, 0, 0);
++ NULL, 0, 0, false);
+ }
+
+ static int
--- /dev/null
+From 1254100030b3377e8302f9c75090ab191d73ee7c Mon Sep 17 00:00:00 2001
+From: Rohith Surabattula <rohiths@microsoft.com>
+Date: Thu, 29 Oct 2020 06:07:56 +0000
+Subject: smb3: Handle error case during offload read path
+
+From: Rohith Surabattula <rohiths@microsoft.com>
+
+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 | 20 +++++++++++++++++++-
+ 1 file changed, 19 insertions(+), 1 deletion(-)
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -4415,7 +4415,25 @@ static void smb2_decrypt_offload(struct
+ 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);
+ }
+