--- /dev/null
+From d527f51331cace562393a8038d870b3e9916686f Mon Sep 17 00:00:00 2001
+From: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
+Date: Tue, 19 Sep 2023 13:38:04 -0500
+Subject: cifs: Fix UAF in cifs_demultiplex_thread()
+
+From: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
+
+commit d527f51331cace562393a8038d870b3e9916686f upstream.
+
+There is a UAF when xfstests on cifs:
+
+ BUG: KASAN: use-after-free in smb2_is_network_name_deleted+0x27/0x160
+ Read of size 4 at addr ffff88810103fc08 by task cifsd/923
+
+ CPU: 1 PID: 923 Comm: cifsd Not tainted 6.1.0-rc4+ #45
+ ...
+ Call Trace:
+ <TASK>
+ dump_stack_lvl+0x34/0x44
+ print_report+0x171/0x472
+ kasan_report+0xad/0x130
+ kasan_check_range+0x145/0x1a0
+ smb2_is_network_name_deleted+0x27/0x160
+ cifs_demultiplex_thread.cold+0x172/0x5a4
+ kthread+0x165/0x1a0
+ ret_from_fork+0x1f/0x30
+ </TASK>
+
+ Allocated by task 923:
+ kasan_save_stack+0x1e/0x40
+ kasan_set_track+0x21/0x30
+ __kasan_slab_alloc+0x54/0x60
+ kmem_cache_alloc+0x147/0x320
+ mempool_alloc+0xe1/0x260
+ cifs_small_buf_get+0x24/0x60
+ allocate_buffers+0xa1/0x1c0
+ cifs_demultiplex_thread+0x199/0x10d0
+ kthread+0x165/0x1a0
+ ret_from_fork+0x1f/0x30
+
+ Freed by task 921:
+ kasan_save_stack+0x1e/0x40
+ kasan_set_track+0x21/0x30
+ kasan_save_free_info+0x2a/0x40
+ ____kasan_slab_free+0x143/0x1b0
+ kmem_cache_free+0xe3/0x4d0
+ cifs_small_buf_release+0x29/0x90
+ SMB2_negotiate+0x8b7/0x1c60
+ smb2_negotiate+0x51/0x70
+ cifs_negotiate_protocol+0xf0/0x160
+ cifs_get_smb_ses+0x5fa/0x13c0
+ mount_get_conns+0x7a/0x750
+ cifs_mount+0x103/0xd00
+ cifs_smb3_do_mount+0x1dd/0xcb0
+ smb3_get_tree+0x1d5/0x300
+ vfs_get_tree+0x41/0xf0
+ path_mount+0x9b3/0xdd0
+ __x64_sys_mount+0x190/0x1d0
+ do_syscall_64+0x35/0x80
+ entry_SYSCALL_64_after_hwframe+0x46/0xb0
+
+The UAF is because:
+
+ mount(pid: 921) | cifsd(pid: 923)
+-------------------------------|-------------------------------
+ | cifs_demultiplex_thread
+SMB2_negotiate |
+ cifs_send_recv |
+ compound_send_recv |
+ smb_send_rqst |
+ wait_for_response |
+ wait_event_state [1] |
+ | standard_receive3
+ | cifs_handle_standard
+ | handle_mid
+ | mid->resp_buf = buf; [2]
+ | dequeue_mid [3]
+ KILL the process [4] |
+ resp_iov[i].iov_base = buf |
+ free_rsp_buf [5] |
+ | is_network_name_deleted [6]
+ | callback
+
+1. After send request to server, wait the response until
+ mid->mid_state != SUBMITTED;
+2. Receive response from server, and set it to mid;
+3. Set the mid state to RECEIVED;
+4. Kill the process, the mid state already RECEIVED, get 0;
+5. Handle and release the negotiate response;
+6. UAF.
+
+It can be easily reproduce with add some delay in [3] - [6].
+
+Only sync call has the problem since async call's callback is
+executed in cifsd process.
+
+Add an extra state to mark the mid state to READY before wakeup the
+waitter, then it can get the resp safely.
+
+Fixes: ec637e3ffb6b ("[CIFS] Avoid extra large buffer allocation (and memcpy) in cifs_readpages")
+Reviewed-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
+Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+[fs/cifs was moved to fs/smb/client since
+38c8a9a52082 ("smb: move client and server files to common directory fs/smb").
+We apply the patch to fs/cifs with some minor context changes.]
+Signed-off-by: He Zhe <zhe.he@windriver.com>
+Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/cifs/cifsglob.h | 1 +
+ fs/cifs/transport.c | 34 +++++++++++++++++++++++-----------
+ 2 files changed, 24 insertions(+), 11 deletions(-)
+
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -1768,6 +1768,7 @@ static inline bool is_retryable_error(in
+ #define MID_RETRY_NEEDED 8 /* session closed while this request out */
+ #define MID_RESPONSE_MALFORMED 0x10
+ #define MID_SHUTDOWN 0x20
++#define MID_RESPONSE_READY 0x40 /* ready for other process handle the rsp */
+
+ /* Flags */
+ #define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */
+--- a/fs/cifs/transport.c
++++ b/fs/cifs/transport.c
+@@ -47,6 +47,8 @@
+ void
+ cifs_wake_up_task(struct mid_q_entry *mid)
+ {
++ if (mid->mid_state == MID_RESPONSE_RECEIVED)
++ mid->mid_state = MID_RESPONSE_READY;
+ wake_up_process(mid->callback_data);
+ }
+
+@@ -99,7 +101,8 @@ static void _cifs_mid_q_entry_release(st
+ struct TCP_Server_Info *server = midEntry->server;
+
+ if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) &&
+- midEntry->mid_state == MID_RESPONSE_RECEIVED &&
++ (midEntry->mid_state == MID_RESPONSE_RECEIVED ||
++ midEntry->mid_state == MID_RESPONSE_READY) &&
+ server->ops->handle_cancelled_mid)
+ server->ops->handle_cancelled_mid(midEntry, server);
+
+@@ -733,7 +736,8 @@ wait_for_response(struct TCP_Server_Info
+ int error;
+
+ error = wait_event_freezekillable_unsafe(server->response_q,
+- midQ->mid_state != MID_REQUEST_SUBMITTED);
++ midQ->mid_state != MID_REQUEST_SUBMITTED &&
++ midQ->mid_state != MID_RESPONSE_RECEIVED);
+ if (error < 0)
+ return -ERESTARTSYS;
+
+@@ -885,7 +889,7 @@ cifs_sync_mid_result(struct mid_q_entry
+
+ spin_lock(&GlobalMid_Lock);
+ switch (mid->mid_state) {
+- case MID_RESPONSE_RECEIVED:
++ case MID_RESPONSE_READY:
+ spin_unlock(&GlobalMid_Lock);
+ return rc;
+ case MID_RETRY_NEEDED:
+@@ -984,6 +988,9 @@ cifs_compound_callback(struct mid_q_entr
+ credits.instance = server->reconnect_instance;
+
+ add_credits(server, &credits, mid->optype);
++
++ if (mid->mid_state == MID_RESPONSE_RECEIVED)
++ mid->mid_state = MID_RESPONSE_READY;
+ }
+
+ static void
+@@ -1172,7 +1179,8 @@ compound_send_recv(const unsigned int xi
+ send_cancel(server, &rqst[i], midQ[i]);
+ spin_lock(&GlobalMid_Lock);
+ midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
+- if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) {
++ if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED ||
++ midQ[i]->mid_state == MID_RESPONSE_RECEIVED) {
+ midQ[i]->callback = cifs_cancelled_callback;
+ cancelled_mid[i] = true;
+ credits[i].value = 0;
+@@ -1193,7 +1201,7 @@ compound_send_recv(const unsigned int xi
+ }
+
+ if (!midQ[i]->resp_buf ||
+- midQ[i]->mid_state != MID_RESPONSE_RECEIVED) {
++ midQ[i]->mid_state != MID_RESPONSE_READY) {
+ rc = -EIO;
+ cifs_dbg(FYI, "Bad MID state?\n");
+ goto out;
+@@ -1372,7 +1380,8 @@ SendReceive(const unsigned int xid, stru
+ if (rc != 0) {
+ send_cancel(server, &rqst, midQ);
+ spin_lock(&GlobalMid_Lock);
+- if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
++ if (midQ->mid_state == MID_REQUEST_SUBMITTED ||
++ midQ->mid_state == MID_RESPONSE_RECEIVED) {
+ /* no longer considered to be "in-flight" */
+ midQ->callback = DeleteMidQEntry;
+ spin_unlock(&GlobalMid_Lock);
+@@ -1389,7 +1398,7 @@ SendReceive(const unsigned int xid, stru
+ }
+
+ if (!midQ->resp_buf || !out_buf ||
+- midQ->mid_state != MID_RESPONSE_RECEIVED) {
++ midQ->mid_state != MID_RESPONSE_READY) {
+ rc = -EIO;
+ cifs_server_dbg(VFS, "Bad MID state?\n");
+ goto out;
+@@ -1509,13 +1518,15 @@ SendReceiveBlockingLock(const unsigned i
+
+ /* Wait for a reply - allow signals to interrupt. */
+ rc = wait_event_interruptible(server->response_q,
+- (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) ||
++ (!(midQ->mid_state == MID_REQUEST_SUBMITTED ||
++ midQ->mid_state == MID_RESPONSE_RECEIVED)) ||
+ ((server->tcpStatus != CifsGood) &&
+ (server->tcpStatus != CifsNew)));
+
+ /* Were we interrupted by a signal ? */
+ if ((rc == -ERESTARTSYS) &&
+- (midQ->mid_state == MID_REQUEST_SUBMITTED) &&
++ (midQ->mid_state == MID_REQUEST_SUBMITTED ||
++ midQ->mid_state == MID_RESPONSE_RECEIVED) &&
+ ((server->tcpStatus == CifsGood) ||
+ (server->tcpStatus == CifsNew))) {
+
+@@ -1545,7 +1556,8 @@ SendReceiveBlockingLock(const unsigned i
+ if (rc) {
+ send_cancel(server, &rqst, midQ);
+ spin_lock(&GlobalMid_Lock);
+- if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
++ if (midQ->mid_state == MID_REQUEST_SUBMITTED ||
++ midQ->mid_state == MID_RESPONSE_RECEIVED) {
+ /* no longer considered to be "in-flight" */
+ midQ->callback = DeleteMidQEntry;
+ spin_unlock(&GlobalMid_Lock);
+@@ -1563,7 +1575,7 @@ SendReceiveBlockingLock(const unsigned i
+ return rc;
+
+ /* rcvd frame is ok */
+- if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) {
++ if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_READY) {
+ rc = -EIO;
+ cifs_tcon_dbg(VFS, "Bad MID state?\n");
+ goto out;
--- /dev/null
+From e6322fd177c6885a21dd4609dc5e5c973d1a2eb7 Mon Sep 17 00:00:00 2001
+From: Paulo Alcantara <pc@manguebit.com>
+Date: Wed, 25 Oct 2023 14:58:35 -0300
+Subject: smb: client: fix potential deadlock when releasing mids
+
+From: Paulo Alcantara <pc@manguebit.com>
+
+commit e6322fd177c6885a21dd4609dc5e5c973d1a2eb7 upstream.
+
+All release_mid() callers seem to hold a reference of @mid so there is
+no need to call kref_put(&mid->refcount, __release_mid) under
+@server->mid_lock spinlock. If they don't, then an use-after-free bug
+would have occurred anyways.
+
+By getting rid of such spinlock also fixes a potential deadlock as
+shown below
+
+CPU 0 CPU 1
+------------------------------------------------------------------
+cifs_demultiplex_thread() cifs_debug_data_proc_show()
+ release_mid()
+ spin_lock(&server->mid_lock);
+ spin_lock(&cifs_tcp_ses_lock)
+ spin_lock(&server->mid_lock)
+ __release_mid()
+ smb2_find_smb_tcon()
+ spin_lock(&cifs_tcp_ses_lock) *deadlock*
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+[cifs_mid_q_entry_release() is renamed to release_mid() and
+ _cifs_mid_q_entry_release() is renamed to __release_mid() by
+ commit 70f08f914a37 ("cifs: remove useless DeleteMidQEntry()")
+ which is integrated into v6.0, so preserve old names in v5.10.]
+Signed-off-by: Cliff Liu <donghua.liu@windriver.com>
+Signed-off-by: He Zhe <Zhe.He@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/cifs/cifsproto.h | 7 ++++++-
+ fs/cifs/smb2misc.c | 2 +-
+ fs/cifs/transport.c | 9 +--------
+ 3 files changed, 8 insertions(+), 10 deletions(-)
+
+--- a/fs/cifs/cifsproto.h
++++ b/fs/cifs/cifsproto.h
+@@ -85,7 +85,7 @@ extern struct mid_q_entry *AllocMidQEntr
+ struct TCP_Server_Info *server);
+ extern void DeleteMidQEntry(struct mid_q_entry *midEntry);
+ extern void cifs_delete_mid(struct mid_q_entry *mid);
+-extern void cifs_mid_q_entry_release(struct mid_q_entry *midEntry);
++void _cifs_mid_q_entry_release(struct kref *refcount);
+ extern void cifs_wake_up_task(struct mid_q_entry *mid);
+ extern int cifs_handle_standard(struct TCP_Server_Info *server,
+ struct mid_q_entry *mid);
+@@ -646,4 +646,9 @@ static inline int cifs_create_options(st
+ return options;
+ }
+
++static inline void cifs_mid_q_entry_release(struct mid_q_entry *midEntry)
++{
++ kref_put(&midEntry->refcount, _cifs_mid_q_entry_release);
++}
++
+ #endif /* _CIFSPROTO_H */
+--- a/fs/cifs/smb2misc.c
++++ b/fs/cifs/smb2misc.c
+@@ -780,7 +780,7 @@ __smb2_handle_cancelled_cmd(struct cifs_
+ {
+ struct close_cancelled_open *cancelled;
+
+- cancelled = kzalloc(sizeof(*cancelled), GFP_ATOMIC);
++ cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);
+ if (!cancelled)
+ return -ENOMEM;
+
+--- a/fs/cifs/transport.c
++++ b/fs/cifs/transport.c
+@@ -88,7 +88,7 @@ AllocMidQEntry(const struct smb_hdr *smb
+ return temp;
+ }
+
+-static void _cifs_mid_q_entry_release(struct kref *refcount)
++void _cifs_mid_q_entry_release(struct kref *refcount)
+ {
+ struct mid_q_entry *midEntry =
+ container_of(refcount, struct mid_q_entry, refcount);
+@@ -168,13 +168,6 @@ static void _cifs_mid_q_entry_release(st
+ mempool_free(midEntry, cifs_mid_poolp);
+ }
+
+-void cifs_mid_q_entry_release(struct mid_q_entry *midEntry)
+-{
+- spin_lock(&GlobalMid_Lock);
+- kref_put(&midEntry->refcount, _cifs_mid_q_entry_release);
+- spin_unlock(&GlobalMid_Lock);
+-}
+-
+ void DeleteMidQEntry(struct mid_q_entry *midEntry)
+ {
+ cifs_mid_q_entry_release(midEntry);
--- /dev/null
+From d328c09ee9f15ee5a26431f5aad7c9239fa85e62 Mon Sep 17 00:00:00 2001
+From: Paulo Alcantara <pc@manguebit.com>
+Date: Tue, 24 Oct 2023 13:49:15 -0300
+Subject: smb: client: fix use-after-free bug in cifs_debug_data_proc_show()
+
+From: Paulo Alcantara <pc@manguebit.com>
+
+commit d328c09ee9f15ee5a26431f5aad7c9239fa85e62 upstream.
+
+Skip SMB sessions that are being teared down
+(e.g. @ses->ses_status == SES_EXITING) in cifs_debug_data_proc_show()
+to avoid use-after-free in @ses.
+
+This fixes the following GPF when reading from /proc/fs/cifs/DebugData
+while mounting and umounting
+
+ [ 816.251274] general protection fault, probably for non-canonical
+ address 0x6b6b6b6b6b6b6d81: 0000 [#1] PREEMPT SMP NOPTI
+ ...
+ [ 816.260138] Call Trace:
+ [ 816.260329] <TASK>
+ [ 816.260499] ? die_addr+0x36/0x90
+ [ 816.260762] ? exc_general_protection+0x1b3/0x410
+ [ 816.261126] ? asm_exc_general_protection+0x26/0x30
+ [ 816.261502] ? cifs_debug_tcon+0xbd/0x240 [cifs]
+ [ 816.261878] ? cifs_debug_tcon+0xab/0x240 [cifs]
+ [ 816.262249] cifs_debug_data_proc_show+0x516/0xdb0 [cifs]
+ [ 816.262689] ? seq_read_iter+0x379/0x470
+ [ 816.262995] seq_read_iter+0x118/0x470
+ [ 816.263291] proc_reg_read_iter+0x53/0x90
+ [ 816.263596] ? srso_alias_return_thunk+0x5/0x7f
+ [ 816.263945] vfs_read+0x201/0x350
+ [ 816.264211] ksys_read+0x75/0x100
+ [ 816.264472] do_syscall_64+0x3f/0x90
+ [ 816.264750] entry_SYSCALL_64_after_hwframe+0x6e/0xd8
+ [ 816.265135] RIP: 0033:0x7fd5e669d381
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+[ This patch removed lock/unlock operation due to ses_lock is
+not present in v5.10 and not ported yet. ses->status is protected
+by a global lock, cifs_tcp_ses_lock, in v5.10. ]
+Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com>
+Signed-off-by: He Zhe <zhe.he@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/cifs/cifs_debug.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/cifs/cifs_debug.c
++++ b/fs/cifs/cifs_debug.c
+@@ -358,6 +358,8 @@ skip_rdma:
+ list_for_each(tmp2, &server->smb_ses_list) {
+ ses = list_entry(tmp2, struct cifs_ses,
+ smb_ses_list);
++ if (ses->status == CifsExiting)
++ continue;
+ if ((ses->serverDomain == NULL) ||
+ (ses->serverOS == NULL) ||
+ (ses->serverNOS == NULL)) {