From: Greg Kroah-Hartman Date: Fri, 27 Nov 2020 15:49:09 +0000 (+0100) Subject: 5.4-stable patches X-Git-Tag: v4.4.247~35^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2d37bf4f7b8027c85a4e80736870d0e510e25def;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: cifs-fix-a-memleak-with-modefromsid.patch smb3-avoid-mid-pending-list-corruption.patch smb3-call-cifs-reconnect-from-demultiplex-thread.patch smb3-handle-error-case-during-offload-read-path.patch --- diff --git a/queue-5.4/cifs-fix-a-memleak-with-modefromsid.patch b/queue-5.4/cifs-fix-a-memleak-with-modefromsid.patch new file mode 100644 index 00000000000..94ba7ace44e --- /dev/null +++ b/queue-5.4/cifs-fix-a-memleak-with-modefromsid.patch @@ -0,0 +1,52 @@ +From 98128572084c3dd8067f48bb588aa3733d1355b5 Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Mon, 9 Nov 2020 17:35:33 +0900 +Subject: cifs: fix a memleak with modefromsid + +From: Namjae Jeon + +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 # v5.4+ +Signed-off-by: Namjae Jeon +Reviewed-by: Aurelien Aptel +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/cifsacl.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -1198,6 +1198,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); diff --git a/queue-5.4/series b/queue-5.4/series index 2c4b6b1c46e..404cd52ba8a 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -2,3 +2,7 @@ spi-bcm-qspi-fix-use-after-free-on-unbind.patch spi-bcm2835-fix-use-after-free-on-unbind.patch ipv4-use-is_enabled-instead-of-ifdef.patch wireless-use-linux-stddef.h-instead-of-stddef.h.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 diff --git a/queue-5.4/smb3-avoid-mid-pending-list-corruption.patch b/queue-5.4/smb3-avoid-mid-pending-list-corruption.patch new file mode 100644 index 00000000000..f54cac0e771 --- /dev/null +++ b/queue-5.4/smb3-avoid-mid-pending-list-corruption.patch @@ -0,0 +1,160 @@ +From ac873aa3dc21707c47db5db6608b38981c731afe Mon Sep 17 00:00:00 2001 +From: Rohith Surabattula +Date: Thu, 29 Oct 2020 05:03:10 +0000 +Subject: smb3: Avoid Mid pending list corruption + +From: Rohith Surabattula + +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 +Reviewed-by: Pavel Shilovsky +CC: Stable #5.4+ +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/smb2ops.c | 55 +++++++++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 46 insertions(+), 9 deletions(-) + +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -259,7 +259,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; +@@ -276,6 +276,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; + } +@@ -284,6 +288,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) + { +@@ -4028,7 +4044,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; + } + +@@ -4052,7 +4071,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; + } + +@@ -4068,21 +4090,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; + } + +@@ -4097,7 +4128,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; + } + +@@ -4108,7 +4142,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; + } + +@@ -4137,7 +4174,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 { diff --git a/queue-5.4/smb3-call-cifs-reconnect-from-demultiplex-thread.patch b/queue-5.4/smb3-call-cifs-reconnect-from-demultiplex-thread.patch new file mode 100644 index 00000000000..5175f31eb0d --- /dev/null +++ b/queue-5.4/smb3-call-cifs-reconnect-from-demultiplex-thread.patch @@ -0,0 +1,101 @@ +From de9ac0a6e9efdffc8cde18781f48fb56ca4157b7 Mon Sep 17 00:00:00 2001 +From: Rohith Surabattula +Date: Wed, 28 Oct 2020 13:42:21 +0000 +Subject: smb3: Call cifs reconnect from demultiplex thread + +From: Rohith Surabattula + +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 +Reviewed-by: Pavel Shilovsky +CC: Stable #5.4+ +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/smb2ops.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -3979,7 +3979,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; +@@ -4001,7 +4002,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); + wake_up(&server->response_q); + return -1; + } +@@ -4142,7 +4144,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); + } +@@ -4246,7 +4249,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: +@@ -4391,7 +4394,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 diff --git a/queue-5.4/smb3-handle-error-case-during-offload-read-path.patch b/queue-5.4/smb3-handle-error-case-during-offload-read-path.patch new file mode 100644 index 00000000000..781638c6261 --- /dev/null +++ b/queue-5.4/smb3-handle-error-case-during-offload-read-path.patch @@ -0,0 +1,56 @@ +From 1254100030b3377e8302f9c75090ab191d73ee7c Mon Sep 17 00:00:00 2001 +From: Rohith Surabattula +Date: Thu, 29 Oct 2020 06:07:56 +0000 +Subject: smb3: Handle error case during offload read path + +From: Rohith Surabattula + +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 +Reviewed-by: Pavel Shilovsky +CC: Stable #5.4+ +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/smb2ops.c | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -4183,7 +4183,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); + } +