From: Greg Kroah-Hartman Date: Tue, 22 Apr 2025 09:59:37 +0000 (+0200) Subject: 5.15-stable patches X-Git-Tag: v6.1.135~53 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8cdcc04f569e67c3c1f38080f4a22061b4e639ba;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches 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 --- 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 index 0000000000..c56a084a54 --- /dev/null +++ b/queue-5.15/cifs-fix-uaf-in-cifs_demultiplex_thread.patch @@ -0,0 +1,249 @@ +From d527f51331cace562393a8038d870b3e9916686f Mon Sep 17 00:00:00 2001 +From: Zhang Xiaoxu +Date: Tue, 19 Sep 2023 13:38:04 -0500 +Subject: cifs: Fix UAF in cifs_demultiplex_thread() + +From: Zhang Xiaoxu + +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: + + 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 + + + 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) +Signed-off-by: Zhang Xiaoxu +Signed-off-by: Steve French +[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 +Signed-off-by: Xiangyu Chen +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-5.15/series b/queue-5.15/series index 94d8c3edfc..6b03f03d01 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -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 index 0000000000..0ea2045f9a --- /dev/null +++ b/queue-5.15/smb-client-fix-null-ptr-deref-in-crypto_aead_setkey.patch @@ -0,0 +1,127 @@ +From 4bdec0d1f658f7c98749bd2c5a486e6cfa8565d2 Mon Sep 17 00:00:00 2001 +From: Paulo Alcantara +Date: Mon, 25 Nov 2024 17:17:23 -0300 +Subject: smb: client: fix NULL ptr deref in crypto_aead_setkey() + +From: Paulo Alcantara + +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: + + 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 +Reported-by: Jianhong Yin +Cc: stable@vger.kernel.org # v6.12 +Fixes: b0abcd65ec54 ("smb: client: fix UAF in async decryption") +Signed-off-by: Paulo Alcantara (Red Hat) +Signed-off-by: Steve French +[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 +Signed-off-by: He Zhe +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..66717afdbf --- /dev/null +++ b/queue-5.15/smb-client-fix-potential-deadlock-when-releasing-mids.patch @@ -0,0 +1,101 @@ +From e6322fd177c6885a21dd4609dc5e5c973d1a2eb7 Mon Sep 17 00:00:00 2001 +From: Paulo Alcantara +Date: Wed, 25 Oct 2023 14:58:35 -0300 +Subject: smb: client: fix potential deadlock when releasing mids + +From: Paulo Alcantara + +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) +Signed-off-by: Steve French +[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 +Signed-off-by: He Zhe +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..d6af190478 --- /dev/null +++ b/queue-5.15/smb-client-fix-uaf-in-async-decryption.patch @@ -0,0 +1,189 @@ +From b0abcd65ec545701b8793e12bc27dc98042b151a Mon Sep 17 00:00:00 2001 +From: Enzo Matsumiya +Date: Thu, 26 Sep 2024 14:46:13 -0300 +Subject: smb: client: fix UAF in async decryption + +From: Enzo Matsumiya + +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] + [ 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 +Signed-off-by: Steve French +[In linux-5.15, dec and enc fields are named ccmaesdecrypt and ccmaesencrypt.] +Signed-off-by: Jianqi Ren +Signed-off-by: He Zhe +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..a6e1b3d7b9 --- /dev/null +++ b/queue-5.15/smb-client-fix-use-after-free-bug-in-cifs_debug_data_proc_show.patch @@ -0,0 +1,61 @@ +From d328c09ee9f15ee5a26431f5aad7c9239fa85e62 Mon Sep 17 00:00:00 2001 +From: Paulo Alcantara +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 + +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] + [ 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) +Signed-off-by: Steve French +[ 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 +Signed-off-by: He Zhe +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..050ae45ec0 --- /dev/null +++ b/queue-5.15/smb-server-fix-potential-null-ptr-deref-of-lease_ctx_info-in-smb2_open.patch @@ -0,0 +1,52 @@ +From 4e8771a3666c8f216eefd6bd2fd50121c6c437db Mon Sep 17 00:00:00 2001 +From: ChenXiaoSong +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 + +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 +Signed-off-by: Steve French +[ 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 +Signed-off-by: He Zhe +Signed-off-by: Greg Kroah-Hartman +--- + 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