]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 22 Apr 2025 10:47:00 +0000 (12:47 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 22 Apr 2025 10:47:00 +0000 (12:47 +0200)
added patches:
bpf-avoid-holding-freeze_mutex-during-mmap-operation.patch
bpf-check-rcu_read_lock_trace_held-before-calling-bpf-map-helpers.patch
smb-client-fix-null-ptr-deref-in-crypto_aead_setkey.patch
smb-client-fix-uaf-in-async-decryption.patch

queue-5.10/bpf-avoid-holding-freeze_mutex-during-mmap-operation.patch [new file with mode: 0644]
queue-5.10/bpf-check-rcu_read_lock_trace_held-before-calling-bpf-map-helpers.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/smb-client-fix-null-ptr-deref-in-crypto_aead_setkey.patch [new file with mode: 0644]
queue-5.10/smb-client-fix-uaf-in-async-decryption.patch [new file with mode: 0644]

diff --git a/queue-5.10/bpf-avoid-holding-freeze_mutex-during-mmap-operation.patch b/queue-5.10/bpf-avoid-holding-freeze_mutex-during-mmap-operation.patch
new file mode 100644 (file)
index 0000000..3a6979e
--- /dev/null
@@ -0,0 +1,75 @@
+From bc27c52eea189e8f7492d40739b7746d67b65beb Mon Sep 17 00:00:00 2001
+From: Andrii Nakryiko <andrii@kernel.org>
+Date: Tue, 28 Jan 2025 17:22:46 -0800
+Subject: bpf: avoid holding freeze_mutex during mmap operation
+
+From: Andrii Nakryiko <andrii@kernel.org>
+
+commit bc27c52eea189e8f7492d40739b7746d67b65beb upstream.
+
+We use map->freeze_mutex to prevent races between map_freeze() and
+memory mapping BPF map contents with writable permissions. The way we
+naively do this means we'll hold freeze_mutex for entire duration of all
+the mm and VMA manipulations, which is completely unnecessary. This can
+potentially also lead to deadlocks, as reported by syzbot in [0].
+
+So, instead, hold freeze_mutex only during writeability checks, bump
+(proactively) "write active" count for the map, unlock the mutex and
+proceed with mmap logic. And only if something went wrong during mmap
+logic, then undo that "write active" counter increment.
+
+  [0] https://lore.kernel.org/bpf/678dcbc9.050a0220.303755.0066.GAE@google.com/
+
+Fixes: fc9702273e2e ("bpf: Add mmap() support for BPF_MAP_TYPE_ARRAY")
+Reported-by: syzbot+4dc041c686b7c816a71e@syzkaller.appspotmail.com
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/r/20250129012246.1515826-2-andrii@kernel.org
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: David Sauerwein <dssauerw@amazon.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/syscall.c |   17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+--- a/kernel/bpf/syscall.c
++++ b/kernel/bpf/syscall.c
+@@ -647,7 +647,7 @@ static const struct vm_operations_struct
+ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma)
+ {
+       struct bpf_map *map = filp->private_data;
+-      int err;
++      int err = 0;
+       if (!map->ops->map_mmap || map_value_has_spin_lock(map))
+               return -ENOTSUPP;
+@@ -671,7 +671,12 @@ static int bpf_map_mmap(struct file *fil
+                       err = -EACCES;
+                       goto out;
+               }
++              bpf_map_write_active_inc(map);
+       }
++out:
++      mutex_unlock(&map->freeze_mutex);
++      if (err)
++              return err;
+       /* set default open/close callbacks */
+       vma->vm_ops = &bpf_map_default_vmops;
+@@ -682,13 +687,11 @@ static int bpf_map_mmap(struct file *fil
+               vma->vm_flags &= ~VM_MAYWRITE;
+       err = map->ops->map_mmap(map, vma);
+-      if (err)
+-              goto out;
++      if (err) {
++              if (vma->vm_flags & VM_WRITE)
++                      bpf_map_write_active_dec(map);
++      }
+-      if (vma->vm_flags & VM_MAYWRITE)
+-              bpf_map_write_active_inc(map);
+-out:
+-      mutex_unlock(&map->freeze_mutex);
+       return err;
+ }
diff --git a/queue-5.10/bpf-check-rcu_read_lock_trace_held-before-calling-bpf-map-helpers.patch b/queue-5.10/bpf-check-rcu_read_lock_trace_held-before-calling-bpf-map-helpers.patch
new file mode 100644 (file)
index 0000000..f619689
--- /dev/null
@@ -0,0 +1,98 @@
+From 169410eba271afc9f0fb476d996795aa26770c6d Mon Sep 17 00:00:00 2001
+From: Hou Tao <houtao1@huawei.com>
+Date: Mon, 4 Dec 2023 22:04:19 +0800
+Subject: bpf: Check rcu_read_lock_trace_held() before calling bpf map helpers
+
+From: Hou Tao <houtao1@huawei.com>
+
+commit 169410eba271afc9f0fb476d996795aa26770c6d upstream.
+
+These three bpf_map_{lookup,update,delete}_elem() helpers are also
+available for sleepable bpf program, so add the corresponding lock
+assertion for sleepable bpf program, otherwise the following warning
+will be reported when a sleepable bpf program manipulates bpf map under
+interpreter mode (aka bpf_jit_enable=0):
+
+  WARNING: CPU: 3 PID: 4985 at kernel/bpf/helpers.c:40 ......
+  CPU: 3 PID: 4985 Comm: test_progs Not tainted 6.6.0+ #2
+  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996) ......
+  RIP: 0010:bpf_map_lookup_elem+0x54/0x60
+  ......
+  Call Trace:
+   <TASK>
+   ? __warn+0xa5/0x240
+   ? bpf_map_lookup_elem+0x54/0x60
+   ? report_bug+0x1ba/0x1f0
+   ? handle_bug+0x40/0x80
+   ? exc_invalid_op+0x18/0x50
+   ? asm_exc_invalid_op+0x1b/0x20
+   ? __pfx_bpf_map_lookup_elem+0x10/0x10
+   ? rcu_lockdep_current_cpu_online+0x65/0xb0
+   ? rcu_is_watching+0x23/0x50
+   ? bpf_map_lookup_elem+0x54/0x60
+   ? __pfx_bpf_map_lookup_elem+0x10/0x10
+   ___bpf_prog_run+0x513/0x3b70
+   __bpf_prog_run32+0x9d/0xd0
+   ? __bpf_prog_enter_sleepable_recur+0xad/0x120
+   ? __bpf_prog_enter_sleepable_recur+0x3e/0x120
+   bpf_trampoline_6442580665+0x4d/0x1000
+   __x64_sys_getpgid+0x5/0x30
+   ? do_syscall_64+0x36/0xb0
+   entry_SYSCALL_64_after_hwframe+0x6e/0x76
+   </TASK>
+
+Signed-off-by: Hou Tao <houtao1@huawei.com>
+Link: https://lore.kernel.org/r/20231204140425.1480317-2-houtao@huaweicloud.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+[Minor conflict resolved due to code context change.]
+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>
+---
+ kernel/bpf/helpers.c |   11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/kernel/bpf/helpers.c
++++ b/kernel/bpf/helpers.c
+@@ -3,6 +3,7 @@
+  */
+ #include <linux/bpf.h>
+ #include <linux/rcupdate.h>
++#include <linux/rcupdate_trace.h>
+ #include <linux/random.h>
+ #include <linux/smp.h>
+ #include <linux/topology.h>
+@@ -24,12 +25,12 @@
+  *
+  * Different map implementations will rely on rcu in map methods
+  * lookup/update/delete, therefore eBPF programs must run under rcu lock
+- * if program is allowed to access maps, so check rcu_read_lock_held in
+- * all three functions.
++ * if program is allowed to access maps, so check rcu_read_lock_held() or
++ * rcu_read_lock_trace_held() in all three functions.
+  */
+ BPF_CALL_2(bpf_map_lookup_elem, struct bpf_map *, map, void *, key)
+ {
+-      WARN_ON_ONCE(!rcu_read_lock_held());
++      WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held());
+       return (unsigned long) map->ops->map_lookup_elem(map, key);
+ }
+@@ -45,7 +46,7 @@ const struct bpf_func_proto bpf_map_look
+ BPF_CALL_4(bpf_map_update_elem, struct bpf_map *, map, void *, key,
+          void *, value, u64, flags)
+ {
+-      WARN_ON_ONCE(!rcu_read_lock_held());
++      WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held());
+       return map->ops->map_update_elem(map, key, value, flags);
+ }
+@@ -62,7 +63,7 @@ const struct bpf_func_proto bpf_map_upda
+ BPF_CALL_2(bpf_map_delete_elem, struct bpf_map *, map, void *, key)
+ {
+-      WARN_ON_ONCE(!rcu_read_lock_held());
++      WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held());
+       return map->ops->map_delete_elem(map, key);
+ }
index e195712bf0487ff0d0270536b80f024b0aa2e6e4..31356db87d7ad31af7d6e825fc6b2f3746c64aff 100644 (file)
@@ -161,3 +161,7 @@ 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-potential-deadlock-when-releasing-mids.patch
 smb-client-fix-potential-uaf-in-cifs_stats_proc_show.patch
+smb-client-fix-uaf-in-async-decryption.patch
+smb-client-fix-null-ptr-deref-in-crypto_aead_setkey.patch
+bpf-avoid-holding-freeze_mutex-during-mmap-operation.patch
+bpf-check-rcu_read_lock_trace_held-before-calling-bpf-map-helpers.patch
diff --git a/queue-5.10/smb-client-fix-null-ptr-deref-in-crypto_aead_setkey.patch b/queue-5.10/smb-client-fix-null-ptr-deref-in-crypto_aead_setkey.patch
new file mode 100644 (file)
index 0000000..0ad1f2a
--- /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
+@@ -963,7 +963,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.10/smb-client-fix-uaf-in-async-decryption.patch b/queue-5.10/smb-client-fix-uaf-in-async-decryption.patch
new file mode 100644 (file)
index 0000000..16d766a
--- /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.10, 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
+@@ -4291,7 +4291,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;
+@@ -4302,8 +4302,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;
+@@ -4314,15 +4312,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);
+@@ -4361,11 +4350,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);
+@@ -4454,7 +4439,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;
+@@ -4480,8 +4465,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;
+@@ -4496,9 +4482,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
+@@ -998,6 +998,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;