Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ksmbd: fix use-after-free from async crypto on Qualcomm crypto engine

ksmbd_crypt_message() sets a NULL completion callback on AEAD requests
and does not handle the -EINPROGRESS return code from async hardware
crypto engines like the Qualcomm Crypto Engine (QCE). When QCE returns
-EINPROGRESS, ksmbd treats it as an error and immediately frees the
request while the hardware DMA operation is still in flight. The DMA
completion callback then dereferences freed memory, causing a NULL
pointer crash:

pc : qce_skcipher_done+0x24/0x174
lr : vchan_complete+0x230/0x27c
...
el1h_64_irq+0x68/0x6c
ksmbd_free_work_struct+0x20/0x118 [ksmbd]
ksmbd_exit_file_cache+0x694/0xa4c [ksmbd]

Use the standard crypto_wait_req() pattern with crypto_req_done() as
the completion callback, matching the approach used by the SMB client
in fs/smb/client/smb2ops.c. This properly handles both synchronous
engines (immediate return) and async engines (-EINPROGRESS followed
by callback notification).

Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
Link: https://github.com/openwrt/openwrt/issues/21822
Signed-off-by: Joshua Klinesmith <joshuaklinesmith@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by

Joshua Klinesmith and committed by
Steve French
3e298897 ad0057fb

+6 -5
+6 -5
fs/smb/server/auth.c
··· 827 827 struct smb2_transform_hdr *tr_hdr = smb_get_msg(iov[0].iov_base); 828 828 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20; 829 829 int rc; 830 + DECLARE_CRYPTO_WAIT(wait); 830 831 struct scatterlist *sg; 831 832 u8 sign[SMB2_SIGNATURE_SIZE] = {}; 832 833 u8 key[SMB3_ENC_DEC_KEY_SIZE]; ··· 914 913 915 914 aead_request_set_crypt(req, sg, sg, crypt_len, iv); 916 915 aead_request_set_ad(req, assoc_data_len); 917 - aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); 916 + aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | 917 + CRYPTO_TFM_REQ_MAY_SLEEP, 918 + crypto_req_done, &wait); 918 919 919 - if (enc) 920 - rc = crypto_aead_encrypt(req); 921 - else 922 - rc = crypto_aead_decrypt(req); 920 + rc = crypto_wait_req(enc ? crypto_aead_encrypt(req) : 921 + crypto_aead_decrypt(req), &wait); 923 922 if (rc) 924 923 goto free_iv; 925 924