]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 22 Apr 2025 09:59:37 +0000 (11:59 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 22 Apr 2025 09:59:37 +0000 (11:59 +0200)
added patches:
cifs-fix-uaf-in-cifs_demultiplex_thread.patch
smb-client-fix-null-ptr-deref-in-crypto_aead_setkey.patch
smb-client-fix-potential-deadlock-when-releasing-mids.patch
smb-client-fix-uaf-in-async-decryption.patch
smb-client-fix-use-after-free-bug-in-cifs_debug_data_proc_show.patch
smb-server-fix-potential-null-ptr-deref-of-lease_ctx_info-in-smb2_open.patch

queue-5.15/cifs-fix-uaf-in-cifs_demultiplex_thread.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/smb-client-fix-null-ptr-deref-in-crypto_aead_setkey.patch [new file with mode: 0644]
queue-5.15/smb-client-fix-potential-deadlock-when-releasing-mids.patch [new file with mode: 0644]
queue-5.15/smb-client-fix-uaf-in-async-decryption.patch [new file with mode: 0644]
queue-5.15/smb-client-fix-use-after-free-bug-in-cifs_debug_data_proc_show.patch [new file with mode: 0644]
queue-5.15/smb-server-fix-potential-null-ptr-deref-of-lease_ctx_info-in-smb2_open.patch [new file with mode: 0644]

diff --git a/queue-5.15/cifs-fix-uaf-in-cifs_demultiplex_thread.patch b/queue-5.15/cifs-fix-uaf-in-cifs_demultiplex_thread.patch
new file mode 100644 (file)
index 0000000..c56a084
--- /dev/null
@@ -0,0 +1,249 @@
+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
+@@ -1719,6 +1719,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
+@@ -34,6 +34,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);
+ }
+@@ -86,7 +88,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);
+@@ -762,7 +765,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;
+@@ -914,7 +918,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:
+@@ -1013,6 +1017,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
+@@ -1204,7 +1211,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;
+@@ -1225,7 +1233,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;
+@@ -1404,7 +1412,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);
+@@ -1421,7 +1430,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;
+@@ -1541,13 +1550,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))) {
+@@ -1577,7 +1588,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);
+@@ -1595,7 +1607,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;
index 94d8c3edfc144904d0398c4984baf140c47abf6c..6b03f03d01120a44ffd5ee41c195084c5dd87852 100644 (file)
@@ -221,3 +221,9 @@ smb-client-fix-potential-uaf-in-cifs_dump_full_key.patch
 ksmbd-fix-potencial-out-of-bounds-when-buffer-offset-is-invalid.patch
 net-make-sock_inuse_add-available.patch
 smb-client-fix-use-after-free-of-network-namespace.patch
+smb-client-fix-use-after-free-bug-in-cifs_debug_data_proc_show.patch
+cifs-fix-uaf-in-cifs_demultiplex_thread.patch
+smb-client-fix-uaf-in-async-decryption.patch
+smb-client-fix-null-ptr-deref-in-crypto_aead_setkey.patch
+smb-server-fix-potential-null-ptr-deref-of-lease_ctx_info-in-smb2_open.patch
+smb-client-fix-potential-deadlock-when-releasing-mids.patch
diff --git a/queue-5.15/smb-client-fix-null-ptr-deref-in-crypto_aead_setkey.patch b/queue-5.15/smb-client-fix-null-ptr-deref-in-crypto_aead_setkey.patch
new file mode 100644 (file)
index 0000000..0ea2045
--- /dev/null
@@ -0,0 +1,127 @@
+From 4bdec0d1f658f7c98749bd2c5a486e6cfa8565d2 Mon Sep 17 00:00:00 2001
+From: Paulo Alcantara <pc@manguebit.com>
+Date: Mon, 25 Nov 2024 17:17:23 -0300
+Subject: smb: client: fix NULL ptr deref in crypto_aead_setkey()
+
+From: Paulo Alcantara <pc@manguebit.com>
+
+commit 4bdec0d1f658f7c98749bd2c5a486e6cfa8565d2 upstream.
+
+Neither SMB3.0 or SMB3.02 supports encryption negotiate context, so
+when SMB2_GLOBAL_CAP_ENCRYPTION flag is set in the negotiate response,
+the client uses AES-128-CCM as the default cipher.  See MS-SMB2
+3.3.5.4.
+
+Commit b0abcd65ec54 ("smb: client: fix UAF in async decryption") added
+a @server->cipher_type check to conditionally call
+smb3_crypto_aead_allocate(), but that check would always be false as
+@server->cipher_type is unset for SMB3.02.
+
+Fix the following KASAN splat by setting @server->cipher_type for
+SMB3.02 as well.
+
+mount.cifs //srv/share /mnt -o vers=3.02,seal,...
+
+BUG: KASAN: null-ptr-deref in crypto_aead_setkey+0x2c/0x130
+Read of size 8 at addr 0000000000000020 by task mount.cifs/1095
+CPU: 1 UID: 0 PID: 1095 Comm: mount.cifs Not tainted 6.12.0 #1
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-3.fc41
+04/01/2014
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x5d/0x80
+ ? crypto_aead_setkey+0x2c/0x130
+ kasan_report+0xda/0x110
+ ? crypto_aead_setkey+0x2c/0x130
+ crypto_aead_setkey+0x2c/0x130
+ crypt_message+0x258/0xec0 [cifs]
+ ? __asan_memset+0x23/0x50
+ ? __pfx_crypt_message+0x10/0x10 [cifs]
+ ? mark_lock+0xb0/0x6a0
+ ? hlock_class+0x32/0xb0
+ ? mark_lock+0xb0/0x6a0
+ smb3_init_transform_rq+0x352/0x3f0 [cifs]
+ ? lock_acquire.part.0+0xf4/0x2a0
+ smb_send_rqst+0x144/0x230 [cifs]
+ ? __pfx_smb_send_rqst+0x10/0x10 [cifs]
+ ? hlock_class+0x32/0xb0
+ ? smb2_setup_request+0x225/0x3a0 [cifs]
+ ? __pfx_cifs_compound_last_callback+0x10/0x10 [cifs]
+ compound_send_recv+0x59b/0x1140 [cifs]
+ ? __pfx_compound_send_recv+0x10/0x10 [cifs]
+ ? __create_object+0x5e/0x90
+ ? hlock_class+0x32/0xb0
+ ? do_raw_spin_unlock+0x9a/0xf0
+ cifs_send_recv+0x23/0x30 [cifs]
+ SMB2_tcon+0x3ec/0xb30 [cifs]
+ ? __pfx_SMB2_tcon+0x10/0x10 [cifs]
+ ? lock_acquire.part.0+0xf4/0x2a0
+ ? __pfx_lock_release+0x10/0x10
+ ? do_raw_spin_trylock+0xc6/0x120
+ ? lock_acquire+0x3f/0x90
+ ? _get_xid+0x16/0xd0 [cifs]
+ ? __pfx_SMB2_tcon+0x10/0x10 [cifs]
+ ? cifs_get_smb_ses+0xcdd/0x10a0 [cifs]
+ cifs_get_smb_ses+0xcdd/0x10a0 [cifs]
+ ? __pfx_cifs_get_smb_ses+0x10/0x10 [cifs]
+ ? cifs_get_tcp_session+0xaa0/0xca0 [cifs]
+ cifs_mount_get_session+0x8a/0x210 [cifs]
+ dfs_mount_share+0x1b0/0x11d0 [cifs]
+ ? __pfx___lock_acquire+0x10/0x10
+ ? __pfx_dfs_mount_share+0x10/0x10 [cifs]
+ ? lock_acquire.part.0+0xf4/0x2a0
+ ? find_held_lock+0x8a/0xa0
+ ? hlock_class+0x32/0xb0
+ ? lock_release+0x203/0x5d0
+ cifs_mount+0xb3/0x3d0 [cifs]
+ ? do_raw_spin_trylock+0xc6/0x120
+ ? __pfx_cifs_mount+0x10/0x10 [cifs]
+ ? lock_acquire+0x3f/0x90
+ ? find_nls+0x16/0xa0
+ ? smb3_update_mnt_flags+0x372/0x3b0 [cifs]
+ cifs_smb3_do_mount+0x1e2/0xc80 [cifs]
+ ? __pfx_vfs_parse_fs_string+0x10/0x10
+ ? __pfx_cifs_smb3_do_mount+0x10/0x10 [cifs]
+ smb3_get_tree+0x1bf/0x330 [cifs]
+ vfs_get_tree+0x4a/0x160
+ path_mount+0x3c1/0xfb0
+ ? kasan_quarantine_put+0xc7/0x1d0
+ ? __pfx_path_mount+0x10/0x10
+ ? kmem_cache_free+0x118/0x3e0
+ ? user_path_at+0x74/0xa0
+ __x64_sys_mount+0x1a6/0x1e0
+ ? __pfx___x64_sys_mount+0x10/0x10
+ ? mark_held_locks+0x1a/0x90
+ do_syscall_64+0xbb/0x1d0
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Cc: Tom Talpey <tom@talpey.com>
+Reported-by: Jianhong Yin <jiyin@redhat.com>
+Cc: stable@vger.kernel.org # v6.12
+Fixes: b0abcd65ec54 ("smb: client: fix UAF in async decryption")
+Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+[Commit b0abcd65ec54 ("smb: client: fix UAF in async decryption")
+fixes CVE-2024-50047 but brings NULL-pointer dereferebce. So
+commit 4bdec0d1f658 ("smb: client: fix NULL ptr deref in crypto_aead_setkey()")
+should be backported too.]
+Signed-off-by: Jianqi Ren <jianqi.ren.cn@windriver.com>
+Signed-off-by: He Zhe <zhe.he@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/cifs/smb2pdu.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -1028,7 +1028,9 @@ SMB2_negotiate(const unsigned int xid, s
+        * SMB3.0 supports only 1 cipher and doesn't have a encryption neg context
+        * Set the cipher type manually.
+        */
+-      if (server->dialect == SMB30_PROT_ID && (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
++      if ((server->dialect == SMB30_PROT_ID ||
++           server->dialect == SMB302_PROT_ID) &&
++          (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
+               server->cipher_type = SMB2_ENCRYPTION_AES128_CCM;
+       security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
diff --git a/queue-5.15/smb-client-fix-potential-deadlock-when-releasing-mids.patch b/queue-5.15/smb-client-fix-potential-deadlock-when-releasing-mids.patch
new file mode 100644 (file)
index 0000000..66717af
--- /dev/null
@@ -0,0 +1,101 @@
+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.15.]
+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
+@@ -83,7 +83,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);
+@@ -637,4 +637,9 @@ static inline int cifs_create_options(st
+ struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon);
+ void cifs_put_tcon_super(struct super_block *sb);
++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
+@@ -759,7 +759,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
+@@ -75,7 +75,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);
+@@ -155,13 +155,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);
diff --git a/queue-5.15/smb-client-fix-uaf-in-async-decryption.patch b/queue-5.15/smb-client-fix-uaf-in-async-decryption.patch
new file mode 100644 (file)
index 0000000..d6af190
--- /dev/null
@@ -0,0 +1,189 @@
+From b0abcd65ec545701b8793e12bc27dc98042b151a Mon Sep 17 00:00:00 2001
+From: Enzo Matsumiya <ematsumiya@suse.de>
+Date: Thu, 26 Sep 2024 14:46:13 -0300
+Subject: smb: client: fix UAF in async decryption
+
+From: Enzo Matsumiya <ematsumiya@suse.de>
+
+commit b0abcd65ec545701b8793e12bc27dc98042b151a upstream.
+
+Doing an async decryption (large read) crashes with a
+slab-use-after-free way down in the crypto API.
+
+Reproducer:
+    # mount.cifs -o ...,seal,esize=1 //srv/share /mnt
+    # dd if=/mnt/largefile of=/dev/null
+    ...
+    [  194.196391] ==================================================================
+    [  194.196844] BUG: KASAN: slab-use-after-free in gf128mul_4k_lle+0xc1/0x110
+    [  194.197269] Read of size 8 at addr ffff888112bd0448 by task kworker/u77:2/899
+    [  194.197707]
+    [  194.197818] CPU: 12 UID: 0 PID: 899 Comm: kworker/u77:2 Not tainted 6.11.0-lku-00028-gfca3ca14a17a-dirty #43
+    [  194.198400] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.2-3-gd478f380-prebuilt.qemu.org 04/01/2014
+    [  194.199046] Workqueue: smb3decryptd smb2_decrypt_offload [cifs]
+    [  194.200032] Call Trace:
+    [  194.200191]  <TASK>
+    [  194.200327]  dump_stack_lvl+0x4e/0x70
+    [  194.200558]  ? gf128mul_4k_lle+0xc1/0x110
+    [  194.200809]  print_report+0x174/0x505
+    [  194.201040]  ? __pfx__raw_spin_lock_irqsave+0x10/0x10
+    [  194.201352]  ? srso_return_thunk+0x5/0x5f
+    [  194.201604]  ? __virt_addr_valid+0xdf/0x1c0
+    [  194.201868]  ? gf128mul_4k_lle+0xc1/0x110
+    [  194.202128]  kasan_report+0xc8/0x150
+    [  194.202361]  ? gf128mul_4k_lle+0xc1/0x110
+    [  194.202616]  gf128mul_4k_lle+0xc1/0x110
+    [  194.202863]  ghash_update+0x184/0x210
+    [  194.203103]  shash_ahash_update+0x184/0x2a0
+    [  194.203377]  ? __pfx_shash_ahash_update+0x10/0x10
+    [  194.203651]  ? srso_return_thunk+0x5/0x5f
+    [  194.203877]  ? crypto_gcm_init_common+0x1ba/0x340
+    [  194.204142]  gcm_hash_assoc_remain_continue+0x10a/0x140
+    [  194.204434]  crypt_message+0xec1/0x10a0 [cifs]
+    [  194.206489]  ? __pfx_crypt_message+0x10/0x10 [cifs]
+    [  194.208507]  ? srso_return_thunk+0x5/0x5f
+    [  194.209205]  ? srso_return_thunk+0x5/0x5f
+    [  194.209925]  ? srso_return_thunk+0x5/0x5f
+    [  194.210443]  ? srso_return_thunk+0x5/0x5f
+    [  194.211037]  decrypt_raw_data+0x15f/0x250 [cifs]
+    [  194.212906]  ? __pfx_decrypt_raw_data+0x10/0x10 [cifs]
+    [  194.214670]  ? srso_return_thunk+0x5/0x5f
+    [  194.215193]  smb2_decrypt_offload+0x12a/0x6c0 [cifs]
+
+This is because TFM is being used in parallel.
+
+Fix this by allocating a new AEAD TFM for async decryption, but keep
+the existing one for synchronous READ cases (similar to what is done
+in smb3_calc_signature()).
+
+Also remove the calls to aead_request_set_callback() and
+crypto_wait_req() since it's always going to be a synchronous operation.
+
+Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+[In linux-5.15, dec and enc fields are named ccmaesdecrypt and ccmaesencrypt.]
+Signed-off-by: Jianqi Ren <jianqi.ren.cn@windriver.com>
+Signed-off-by: He Zhe <zhe.he@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/cifs/smb2ops.c |   48 ++++++++++++++++++++++++++++--------------------
+ fs/cifs/smb2pdu.c |    6 ++++++
+ 2 files changed, 34 insertions(+), 20 deletions(-)
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -4541,7 +4541,7 @@ smb2_get_enc_key(struct TCP_Server_Info
+  */
+ static int
+ crypt_message(struct TCP_Server_Info *server, int num_rqst,
+-            struct smb_rqst *rqst, int enc)
++            struct smb_rqst *rqst, int enc, struct crypto_aead *tfm)
+ {
+       struct smb2_transform_hdr *tr_hdr =
+               (struct smb2_transform_hdr *)rqst[0].rq_iov[0].iov_base;
+@@ -4552,8 +4552,6 @@ crypt_message(struct TCP_Server_Info *se
+       u8 key[SMB3_ENC_DEC_KEY_SIZE];
+       struct aead_request *req;
+       u8 *iv;
+-      DECLARE_CRYPTO_WAIT(wait);
+-      struct crypto_aead *tfm;
+       unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
+       void *creq;
+@@ -4564,15 +4562,6 @@ crypt_message(struct TCP_Server_Info *se
+               return rc;
+       }
+-      rc = smb3_crypto_aead_allocate(server);
+-      if (rc) {
+-              cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__);
+-              return rc;
+-      }
+-
+-      tfm = enc ? server->secmech.ccmaesencrypt :
+-                                              server->secmech.ccmaesdecrypt;
+-
+       if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
+               (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
+               rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
+@@ -4611,11 +4600,7 @@ crypt_message(struct TCP_Server_Info *se
+       aead_request_set_crypt(req, sg, sg, crypt_len, iv);
+       aead_request_set_ad(req, assoc_data_len);
+-      aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+-                                crypto_req_done, &wait);
+-
+-      rc = crypto_wait_req(enc ? crypto_aead_encrypt(req)
+-                              : crypto_aead_decrypt(req), &wait);
++      rc = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req);
+       if (!rc && enc)
+               memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
+@@ -4704,7 +4689,7 @@ smb3_init_transform_rq(struct TCP_Server
+       /* fill the 1st iov with a transform header */
+       fill_transform_hdr(tr_hdr, orig_len, old_rq, server->cipher_type);
+-      rc = crypt_message(server, num_rqst, new_rq, 1);
++      rc = crypt_message(server, num_rqst, new_rq, 1, server->secmech.ccmaesencrypt);
+       cifs_dbg(FYI, "Encrypt message returned %d\n", rc);
+       if (rc)
+               goto err_free;
+@@ -4730,8 +4715,9 @@ decrypt_raw_data(struct TCP_Server_Info
+                unsigned int npages, unsigned int page_data_size,
+                bool is_offloaded)
+ {
+-      struct kvec iov[2];
++      struct crypto_aead *tfm;
+       struct smb_rqst rqst = {NULL};
++      struct kvec iov[2];
+       int rc;
+       iov[0].iov_base = buf;
+@@ -4746,9 +4732,31 @@ decrypt_raw_data(struct TCP_Server_Info
+       rqst.rq_pagesz = PAGE_SIZE;
+       rqst.rq_tailsz = (page_data_size % PAGE_SIZE) ? : PAGE_SIZE;
+-      rc = crypt_message(server, 1, &rqst, 0);
++      if (is_offloaded) {
++              if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
++                  (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
++                      tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
++              else
++                      tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
++              if (IS_ERR(tfm)) {
++                      rc = PTR_ERR(tfm);
++                      cifs_server_dbg(VFS, "%s: Failed alloc decrypt TFM, rc=%d\n", __func__, rc);
++
++                      return rc;
++              }
++      } else {
++              if (unlikely(!server->secmech.ccmaesdecrypt))
++                      return -EIO;
++
++              tfm = server->secmech.ccmaesdecrypt;
++      }
++
++      rc = crypt_message(server, 1, &rqst, 0, tfm);
+       cifs_dbg(FYI, "Decrypt message returned %d\n", rc);
++      if (is_offloaded)
++              crypto_free_aead(tfm);
++
+       if (rc)
+               return rc;
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -1063,6 +1063,12 @@ SMB2_negotiate(const unsigned int xid, s
+               else
+                       cifs_server_dbg(VFS, "Missing expected negotiate contexts\n");
+       }
++
++      if (server->cipher_type && !rc) {
++              rc = smb3_crypto_aead_allocate(server);
++              if (rc)
++                      cifs_server_dbg(VFS, "%s: crypto alloc failed, rc=%d\n", __func__, rc);
++      }
+ neg_exit:
+       free_rsp_buf(resp_buftype, rsp);
+       return rc;
diff --git a/queue-5.15/smb-client-fix-use-after-free-bug-in-cifs_debug_data_proc_show.patch b/queue-5.15/smb-client-fix-use-after-free-bug-in-cifs_debug_data_proc_show.patch
new file mode 100644 (file)
index 0000000..a6e1b3d
--- /dev/null
@@ -0,0 +1,61 @@
+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.15 and not ported yet. ses->status is protected
+by a global lock, cifs_tcp_ses_lock, in v5.15. ]
+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
+@@ -382,6 +382,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;
+                       i++;
+                       if ((ses->serverDomain == NULL) ||
+                               (ses->serverOS == NULL) ||
diff --git a/queue-5.15/smb-server-fix-potential-null-ptr-deref-of-lease_ctx_info-in-smb2_open.patch b/queue-5.15/smb-server-fix-potential-null-ptr-deref-of-lease_ctx_info-in-smb2_open.patch
new file mode 100644 (file)
index 0000000..050ae45
--- /dev/null
@@ -0,0 +1,52 @@
+From 4e8771a3666c8f216eefd6bd2fd50121c6c437db Mon Sep 17 00:00:00 2001
+From: ChenXiaoSong <chenxiaosong@kylinos.cn>
+Date: Thu, 22 Aug 2024 08:20:51 +0000
+Subject: smb/server: fix potential null-ptr-deref of lease_ctx_info in smb2_open()
+
+From: ChenXiaoSong <chenxiaosong@kylinos.cn>
+
+commit 4e8771a3666c8f216eefd6bd2fd50121c6c437db upstream.
+
+null-ptr-deref will occur when (req_op_level == SMB2_OPLOCK_LEVEL_LEASE)
+and parse_lease_state() return NULL.
+
+Fix this by check if 'lease_ctx_info' is NULL.
+
+Additionally, remove the redundant parentheses in
+parse_durable_handle_context().
+
+Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+[ Drop the parentheses clean-up since the parentheses was introduced by
+  c8efcc786146 ("ksmbd: add support for durable handles v1/v2") in v6.9
+  Minor context change fixed ]
+Signed-off-by: Jianqi Ren <jianqi.ren.cn@windriver.com>
+Signed-off-by: He Zhe <zhe.he@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ksmbd/oplock.c  |    2 +-
+ fs/ksmbd/smb2pdu.c |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/ksmbd/oplock.c
++++ b/fs/ksmbd/oplock.c
+@@ -1498,7 +1498,7 @@ void create_lease_buf(u8 *rbuf, struct l
+  * @open_req: buffer containing smb2 file open(create) request
+  * @is_dir:   whether leasing file is directory
+  *
+- * Return:  oplock state, -ENOENT if create lease context not found
++ * Return: allocated lease context object on success, otherwise NULL
+  */
+ struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir)
+ {
+--- a/fs/ksmbd/smb2pdu.c
++++ b/fs/ksmbd/smb2pdu.c
+@@ -3230,7 +3230,7 @@ int smb2_open(struct ksmbd_work *work)
+                       goto err_out1;
+               }
+       } else {
+-              if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) {
++              if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE && lc) {
+                       /*
+                        * Compare parent lease using parent key. If there is no
+                        * a lease that has same parent key, Send lease break