Skip to content

Commit 8bf1e37

Browse files
committed
Merge: smb: client: fix UAF in async decryption
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/5690 JIRA: https://issues.redhat.com/browse/RHEL-63909 CVE: CVE-2024-50047 Signed-off-by: Paulo Alcantara <paalcant@redhat.com> Approved-by: Scott Mayhew <smayhew@redhat.com> Approved-by: Benjamin Coddington <bcodding@redhat.com> Approved-by: Jay Shin <jaeshin@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Rado Vrbovsky <rvrbovsk@redhat.com>
2 parents 4804cf7 + 0263939 commit 8bf1e37

File tree

2 files changed

+37
-20
lines changed

2 files changed

+37
-20
lines changed

fs/smb/client/smb2ops.c

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4226,7 +4226,7 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
42264226
*/
42274227
static int
42284228
crypt_message(struct TCP_Server_Info *server, int num_rqst,
4229-
struct smb_rqst *rqst, int enc)
4229+
struct smb_rqst *rqst, int enc, struct crypto_aead *tfm)
42304230
{
42314231
struct smb2_transform_hdr *tr_hdr =
42324232
(struct smb2_transform_hdr *)rqst[0].rq_iov[0].iov_base;
@@ -4237,8 +4237,6 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
42374237
u8 key[SMB3_ENC_DEC_KEY_SIZE];
42384238
struct aead_request *req;
42394239
u8 *iv;
4240-
DECLARE_CRYPTO_WAIT(wait);
4241-
struct crypto_aead *tfm;
42424240
unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
42434241
void *creq;
42444242

@@ -4249,14 +4247,6 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
42494247
return rc;
42504248
}
42514249

4252-
rc = smb3_crypto_aead_allocate(server);
4253-
if (rc) {
4254-
cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__);
4255-
return rc;
4256-
}
4257-
4258-
tfm = enc ? server->secmech.enc : server->secmech.dec;
4259-
42604250
if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
42614251
(server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
42624252
rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
@@ -4295,11 +4285,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
42954285
aead_request_set_crypt(req, sg, sg, crypt_len, iv);
42964286
aead_request_set_ad(req, assoc_data_len);
42974287

4298-
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
4299-
crypto_req_done, &wait);
4300-
4301-
rc = crypto_wait_req(enc ? crypto_aead_encrypt(req)
4302-
: crypto_aead_decrypt(req), &wait);
4288+
rc = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req);
43034289

43044290
if (!rc && enc)
43054291
memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
@@ -4389,7 +4375,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst,
43894375
/* fill the 1st iov with a transform header */
43904376
fill_transform_hdr(tr_hdr, orig_len, old_rq, server->cipher_type);
43914377

4392-
rc = crypt_message(server, num_rqst, new_rq, 1);
4378+
rc = crypt_message(server, num_rqst, new_rq, 1, server->secmech.enc);
43934379
cifs_dbg(FYI, "Encrypt message returned %d\n", rc);
43944380
if (rc)
43954381
goto err_free;
@@ -4415,8 +4401,9 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
44154401
unsigned int npages, unsigned int page_data_size,
44164402
bool is_offloaded)
44174403
{
4418-
struct kvec iov[2];
4404+
struct crypto_aead *tfm;
44194405
struct smb_rqst rqst = {NULL};
4406+
struct kvec iov[2];
44204407
int rc;
44214408

44224409
iov[0].iov_base = buf;
@@ -4431,9 +4418,31 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
44314418
rqst.rq_pagesz = PAGE_SIZE;
44324419
rqst.rq_tailsz = (page_data_size % PAGE_SIZE) ? : PAGE_SIZE;
44334420

4434-
rc = crypt_message(server, 1, &rqst, 0);
4421+
if (is_offloaded) {
4422+
if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
4423+
(server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
4424+
tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
4425+
else
4426+
tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
4427+
if (IS_ERR(tfm)) {
4428+
rc = PTR_ERR(tfm);
4429+
cifs_server_dbg(VFS, "%s: Failed alloc decrypt TFM, rc=%d\n", __func__, rc);
4430+
4431+
return rc;
4432+
}
4433+
} else {
4434+
if (unlikely(!server->secmech.dec))
4435+
return -EIO;
4436+
4437+
tfm = server->secmech.dec;
4438+
}
4439+
4440+
rc = crypt_message(server, 1, &rqst, 0, tfm);
44354441
cifs_dbg(FYI, "Decrypt message returned %d\n", rc);
44364442

4443+
if (is_offloaded)
4444+
crypto_free_aead(tfm);
4445+
44374446
if (rc)
44384447
return rc;
44394448

fs/smb/client/smb2pdu.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1228,7 +1228,9 @@ SMB2_negotiate(const unsigned int xid,
12281228
* SMB3.0 supports only 1 cipher and doesn't have a encryption neg context
12291229
* Set the cipher type manually.
12301230
*/
1231-
if (server->dialect == SMB30_PROT_ID && (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
1231+
if ((server->dialect == SMB30_PROT_ID ||
1232+
server->dialect == SMB302_PROT_ID) &&
1233+
(server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
12321234
server->cipher_type = SMB2_ENCRYPTION_AES128_CCM;
12331235

12341236
security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
@@ -1263,6 +1265,12 @@ SMB2_negotiate(const unsigned int xid,
12631265
else
12641266
cifs_server_dbg(VFS, "Missing expected negotiate contexts\n");
12651267
}
1268+
1269+
if (server->cipher_type && !rc) {
1270+
rc = smb3_crypto_aead_allocate(server);
1271+
if (rc)
1272+
cifs_server_dbg(VFS, "%s: crypto alloc failed, rc=%d\n", __func__, rc);
1273+
}
12661274
neg_exit:
12671275
free_rsp_buf(resp_buftype, rsp);
12681276
return rc;

0 commit comments

Comments
 (0)