Skip to content

Commit 4ccb3a8

Browse files
committed
Merge tag '6.18-rc1-smb-client-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull smb client fixes from Steve French: "smb client fixes, security and smbdirect improvements, and some minor cleanup: - Important OOB DFS fix - Fix various potential tcon refcount leaks - smbdirect (RDMA) fixes (following up from test event a few weeks ago): - Fixes to improve and simplify handling of memory lifetime of smbdirect_mr_io structures, when a connection gets disconnected - Make sure we really wait to reach SMBDIRECT_SOCKET_DISCONNECTED before destroying resources - Make sure the send/recv submission/completion queues are large enough to avoid ib_post_send() from failing under pressure - convert cifs.ko to use the recommended crypto libraries (instead of crypto_shash), this also can improve performance - Three small cleanup patches" * tag '6.18-rc1-smb-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: (24 commits) smb: client: Consolidate cmac(aes) shash allocation smb: client: Remove obsolete crypto_shash allocations smb: client: Use HMAC-MD5 library for NTLMv2 smb: client: Use MD5 library for SMB1 signature calculation smb: client: Use MD5 library for M-F symlink hashing smb: client: Use HMAC-SHA256 library for SMB2 signature calculation smb: client: Use HMAC-SHA256 library for key generation smb: client: Use SHA-512 library for SMB3.1.1 preauth hash cifs: parse_dfs_referrals: prevent oob on malformed input smb: client: Fix refcount leak for cifs_sb_tlink smb: client: let smbd_destroy() wait for SMBDIRECT_SOCKET_DISCONNECTED smb: move some duplicate definitions to common/cifsglob.h smb: client: let destroy_mr_list() keep smbdirect_mr_io memory if registered smb: client: let destroy_mr_list() call ib_dereg_mr() before ib_dma_unmap_sg() smb: client: call ib_dma_unmap_sg if mr->sgt.nents is not 0 smb: client: improve logic in smbd_deregister_mr() smb: client: improve logic in smbd_register_mr() smb: client: improve logic in allocate_mr_list() smb: client: let destroy_mr_list() remove locked from the list smb: client: let destroy_mr_list() call list_del(&mr->list) ...
2 parents 02e5f74 + 3c15a6d commit 4ccb3a8

File tree

20 files changed

+419
-498
lines changed

20 files changed

+419
-498
lines changed

fs/smb/client/Kconfig

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,16 @@ config CIFS
55
select NLS
66
select NLS_UCS2_UTILS
77
select CRYPTO
8-
select CRYPTO_MD5
9-
select CRYPTO_SHA256
10-
select CRYPTO_SHA512
118
select CRYPTO_CMAC
12-
select CRYPTO_HMAC
139
select CRYPTO_AEAD2
1410
select CRYPTO_CCM
1511
select CRYPTO_GCM
1612
select CRYPTO_ECB
1713
select CRYPTO_AES
1814
select CRYPTO_LIB_ARC4
15+
select CRYPTO_LIB_MD5
16+
select CRYPTO_LIB_SHA256
17+
select CRYPTO_LIB_SHA512
1918
select KEYS
2019
select DNS_RESOLVER
2120
select ASN1

fs/smb/client/cifsacl.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,6 @@ int
339339
sid_to_id(struct cifs_sb_info *cifs_sb, struct smb_sid *psid,
340340
struct cifs_fattr *fattr, uint sidtype)
341341
{
342-
int rc = 0;
343342
struct key *sidkey;
344343
char *sidstr;
345344
const struct cred *saved_cred;
@@ -446,12 +445,12 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct smb_sid *psid,
446445
* fails then we just fall back to using the ctx->linux_uid/linux_gid.
447446
*/
448447
got_valid_id:
449-
rc = 0;
450448
if (sidtype == SIDOWNER)
451449
fattr->cf_uid = fuid;
452450
else
453451
fattr->cf_gid = fgid;
454-
return rc;
452+
453+
return 0;
455454
}
456455

457456
int

fs/smb/client/cifsencrypt.c

Lines changed: 74 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,43 @@
2424
#include <linux/iov_iter.h>
2525
#include <crypto/aead.h>
2626
#include <crypto/arc4.h>
27+
#include <crypto/md5.h>
28+
#include <crypto/sha2.h>
2729

28-
static size_t cifs_shash_step(void *iter_base, size_t progress, size_t len,
29-
void *priv, void *priv2)
30+
static int cifs_sig_update(struct cifs_calc_sig_ctx *ctx,
31+
const u8 *data, size_t len)
3032
{
31-
struct shash_desc *shash = priv;
33+
if (ctx->md5) {
34+
md5_update(ctx->md5, data, len);
35+
return 0;
36+
}
37+
if (ctx->hmac) {
38+
hmac_sha256_update(ctx->hmac, data, len);
39+
return 0;
40+
}
41+
return crypto_shash_update(ctx->shash, data, len);
42+
}
43+
44+
static int cifs_sig_final(struct cifs_calc_sig_ctx *ctx, u8 *out)
45+
{
46+
if (ctx->md5) {
47+
md5_final(ctx->md5, out);
48+
return 0;
49+
}
50+
if (ctx->hmac) {
51+
hmac_sha256_final(ctx->hmac, out);
52+
return 0;
53+
}
54+
return crypto_shash_final(ctx->shash, out);
55+
}
56+
57+
static size_t cifs_sig_step(void *iter_base, size_t progress, size_t len,
58+
void *priv, void *priv2)
59+
{
60+
struct cifs_calc_sig_ctx *ctx = priv;
3261
int ret, *pret = priv2;
3362

34-
ret = crypto_shash_update(shash, iter_base, len);
63+
ret = cifs_sig_update(ctx, iter_base, len);
3564
if (ret < 0) {
3665
*pret = ret;
3766
return len;
@@ -42,21 +71,20 @@ static size_t cifs_shash_step(void *iter_base, size_t progress, size_t len,
4271
/*
4372
* Pass the data from an iterator into a hash.
4473
*/
45-
static int cifs_shash_iter(const struct iov_iter *iter, size_t maxsize,
46-
struct shash_desc *shash)
74+
static int cifs_sig_iter(const struct iov_iter *iter, size_t maxsize,
75+
struct cifs_calc_sig_ctx *ctx)
4776
{
4877
struct iov_iter tmp_iter = *iter;
4978
int err = -EIO;
5079

51-
if (iterate_and_advance_kernel(&tmp_iter, maxsize, shash, &err,
52-
cifs_shash_step) != maxsize)
80+
if (iterate_and_advance_kernel(&tmp_iter, maxsize, ctx, &err,
81+
cifs_sig_step) != maxsize)
5382
return err;
5483
return 0;
5584
}
5685

57-
int __cifs_calc_signature(struct smb_rqst *rqst,
58-
struct TCP_Server_Info *server, char *signature,
59-
struct shash_desc *shash)
86+
int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
87+
char *signature, struct cifs_calc_sig_ctx *ctx)
6088
{
6189
int i;
6290
ssize_t rc;
@@ -82,20 +110,19 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
82110
return -EIO;
83111
}
84112

85-
rc = crypto_shash_update(shash,
86-
iov[i].iov_base, iov[i].iov_len);
113+
rc = cifs_sig_update(ctx, iov[i].iov_base, iov[i].iov_len);
87114
if (rc) {
88115
cifs_dbg(VFS, "%s: Could not update with payload\n",
89116
__func__);
90117
return rc;
91118
}
92119
}
93120

94-
rc = cifs_shash_iter(&rqst->rq_iter, iov_iter_count(&rqst->rq_iter), shash);
121+
rc = cifs_sig_iter(&rqst->rq_iter, iov_iter_count(&rqst->rq_iter), ctx);
95122
if (rc < 0)
96123
return rc;
97124

98-
rc = crypto_shash_final(shash, signature);
125+
rc = cifs_sig_final(ctx, signature);
99126
if (rc)
100127
cifs_dbg(VFS, "%s: Could not generate hash\n", __func__);
101128

@@ -112,29 +139,22 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
112139
static int cifs_calc_signature(struct smb_rqst *rqst,
113140
struct TCP_Server_Info *server, char *signature)
114141
{
115-
int rc;
142+
struct md5_ctx ctx;
116143

117144
if (!rqst->rq_iov || !signature || !server)
118145
return -EINVAL;
119-
120-
rc = cifs_alloc_hash("md5", &server->secmech.md5);
121-
if (rc)
122-
return -1;
123-
124-
rc = crypto_shash_init(server->secmech.md5);
125-
if (rc) {
126-
cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
127-
return rc;
146+
if (fips_enabled) {
147+
cifs_dbg(VFS,
148+
"MD5 signature support is disabled due to FIPS\n");
149+
return -EOPNOTSUPP;
128150
}
129151

130-
rc = crypto_shash_update(server->secmech.md5,
131-
server->session_key.response, server->session_key.len);
132-
if (rc) {
133-
cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
134-
return rc;
135-
}
152+
md5_init(&ctx);
153+
md5_update(&ctx, server->session_key.response, server->session_key.len);
136154

137-
return __cifs_calc_signature(rqst, server, signature, server->secmech.md5);
155+
return __cifs_calc_signature(
156+
rqst, server, signature,
157+
&(struct cifs_calc_sig_ctx){ .md5 = &ctx });
138158
}
139159

140160
/* must be called with server->srv_mutex held */
@@ -405,29 +425,19 @@ static __le64 find_timestamp(struct cifs_ses *ses)
405425
}
406426

407427
static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
408-
const struct nls_table *nls_cp, struct shash_desc *hmacmd5)
428+
const struct nls_table *nls_cp)
409429
{
410-
int rc = 0;
411430
int len;
412431
char nt_hash[CIFS_NTHASH_SIZE];
432+
struct hmac_md5_ctx hmac_ctx;
413433
__le16 *user;
414434
wchar_t *domain;
415435
wchar_t *server;
416436

417437
/* calculate md4 hash of password */
418438
E_md4hash(ses->password, nt_hash, nls_cp);
419439

420-
rc = crypto_shash_setkey(hmacmd5->tfm, nt_hash, CIFS_NTHASH_SIZE);
421-
if (rc) {
422-
cifs_dbg(VFS, "%s: Could not set NT hash as a key, rc=%d\n", __func__, rc);
423-
return rc;
424-
}
425-
426-
rc = crypto_shash_init(hmacmd5);
427-
if (rc) {
428-
cifs_dbg(VFS, "%s: Could not init HMAC-MD5, rc=%d\n", __func__, rc);
429-
return rc;
430-
}
440+
hmac_md5_init_usingrawkey(&hmac_ctx, nt_hash, CIFS_NTHASH_SIZE);
431441

432442
/* convert ses->user_name to unicode */
433443
len = ses->user_name ? strlen(ses->user_name) : 0;
@@ -442,12 +452,8 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
442452
*(u16 *)user = 0;
443453
}
444454

445-
rc = crypto_shash_update(hmacmd5, (char *)user, 2 * len);
455+
hmac_md5_update(&hmac_ctx, (const u8 *)user, 2 * len);
446456
kfree(user);
447-
if (rc) {
448-
cifs_dbg(VFS, "%s: Could not update with user, rc=%d\n", __func__, rc);
449-
return rc;
450-
}
451457

452458
/* convert ses->domainName to unicode and uppercase */
453459
if (ses->domainName) {
@@ -459,12 +465,8 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
459465

460466
len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
461467
nls_cp);
462-
rc = crypto_shash_update(hmacmd5, (char *)domain, 2 * len);
468+
hmac_md5_update(&hmac_ctx, (const u8 *)domain, 2 * len);
463469
kfree(domain);
464-
if (rc) {
465-
cifs_dbg(VFS, "%s: Could not update with domain, rc=%d\n", __func__, rc);
466-
return rc;
467-
}
468470
} else {
469471
/* We use ses->ip_addr if no domain name available */
470472
len = strlen(ses->ip_addr);
@@ -474,25 +476,16 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
474476
return -ENOMEM;
475477

476478
len = cifs_strtoUTF16((__le16 *)server, ses->ip_addr, len, nls_cp);
477-
rc = crypto_shash_update(hmacmd5, (char *)server, 2 * len);
479+
hmac_md5_update(&hmac_ctx, (const u8 *)server, 2 * len);
478480
kfree(server);
479-
if (rc) {
480-
cifs_dbg(VFS, "%s: Could not update with server, rc=%d\n", __func__, rc);
481-
return rc;
482-
}
483481
}
484482

485-
rc = crypto_shash_final(hmacmd5, ntlmv2_hash);
486-
if (rc)
487-
cifs_dbg(VFS, "%s: Could not generate MD5 hash, rc=%d\n", __func__, rc);
488-
489-
return rc;
483+
hmac_md5_final(&hmac_ctx, ntlmv2_hash);
484+
return 0;
490485
}
491486

492-
static int
493-
CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash, struct shash_desc *hmacmd5)
487+
static void CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
494488
{
495-
int rc;
496489
struct ntlmv2_resp *ntlmv2 = (struct ntlmv2_resp *)
497490
(ses->auth_key.response + CIFS_SESS_KEY_SIZE);
498491
unsigned int hash_len;
@@ -501,35 +494,15 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash, struct shash_
501494
hash_len = ses->auth_key.len - (CIFS_SESS_KEY_SIZE +
502495
offsetof(struct ntlmv2_resp, challenge.key[0]));
503496

504-
rc = crypto_shash_setkey(hmacmd5->tfm, ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
505-
if (rc) {
506-
cifs_dbg(VFS, "%s: Could not set NTLMv2 hash as a key, rc=%d\n", __func__, rc);
507-
return rc;
508-
}
509-
510-
rc = crypto_shash_init(hmacmd5);
511-
if (rc) {
512-
cifs_dbg(VFS, "%s: Could not init HMAC-MD5, rc=%d\n", __func__, rc);
513-
return rc;
514-
}
515-
516497
if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
517498
memcpy(ntlmv2->challenge.key, ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
518499
else
519500
memcpy(ntlmv2->challenge.key, ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
520501

521-
rc = crypto_shash_update(hmacmd5, ntlmv2->challenge.key, hash_len);
522-
if (rc) {
523-
cifs_dbg(VFS, "%s: Could not update with response, rc=%d\n", __func__, rc);
524-
return rc;
525-
}
526-
527-
/* Note that the MD5 digest over writes anon.challenge_key.key */
528-
rc = crypto_shash_final(hmacmd5, ntlmv2->ntlmv2_hash);
529-
if (rc)
530-
cifs_dbg(VFS, "%s: Could not generate MD5 hash, rc=%d\n", __func__, rc);
531-
532-
return rc;
502+
/* Note that the HMAC-MD5 value overwrites ntlmv2->challenge.key */
503+
hmac_md5_usingrawkey(ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE,
504+
ntlmv2->challenge.key, hash_len,
505+
ntlmv2->ntlmv2_hash);
533506
}
534507

535508
/*
@@ -586,7 +559,6 @@ static int set_auth_key_response(struct cifs_ses *ses)
586559
int
587560
setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
588561
{
589-
struct shash_desc *hmacmd5 = NULL;
590562
unsigned char *tiblob = NULL; /* target info blob */
591563
struct ntlmv2_resp *ntlmv2;
592564
char ntlmv2_hash[16];
@@ -657,51 +629,29 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
657629
ntlmv2->client_chal = cc;
658630
ntlmv2->reserved2 = 0;
659631

660-
rc = cifs_alloc_hash("hmac(md5)", &hmacmd5);
661-
if (rc) {
662-
cifs_dbg(VFS, "Could not allocate HMAC-MD5, rc=%d\n", rc);
632+
if (fips_enabled) {
633+
cifs_dbg(VFS, "NTLMv2 support is disabled due to FIPS\n");
634+
rc = -EOPNOTSUPP;
663635
goto unlock;
664636
}
665637

666638
/* calculate ntlmv2_hash */
667-
rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp, hmacmd5);
639+
rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
668640
if (rc) {
669641
cifs_dbg(VFS, "Could not get NTLMv2 hash, rc=%d\n", rc);
670642
goto unlock;
671643
}
672644

673645
/* calculate first part of the client response (CR1) */
674-
rc = CalcNTLMv2_response(ses, ntlmv2_hash, hmacmd5);
675-
if (rc) {
676-
cifs_dbg(VFS, "Could not calculate CR1, rc=%d\n", rc);
677-
goto unlock;
678-
}
646+
CalcNTLMv2_response(ses, ntlmv2_hash);
679647

680648
/* now calculate the session key for NTLMv2 */
681-
rc = crypto_shash_setkey(hmacmd5->tfm, ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
682-
if (rc) {
683-
cifs_dbg(VFS, "%s: Could not set NTLMv2 hash as a key, rc=%d\n", __func__, rc);
684-
goto unlock;
685-
}
686-
687-
rc = crypto_shash_init(hmacmd5);
688-
if (rc) {
689-
cifs_dbg(VFS, "%s: Could not init HMAC-MD5, rc=%d\n", __func__, rc);
690-
goto unlock;
691-
}
692-
693-
rc = crypto_shash_update(hmacmd5, ntlmv2->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
694-
if (rc) {
695-
cifs_dbg(VFS, "%s: Could not update with response, rc=%d\n", __func__, rc);
696-
goto unlock;
697-
}
698-
699-
rc = crypto_shash_final(hmacmd5, ses->auth_key.response);
700-
if (rc)
701-
cifs_dbg(VFS, "%s: Could not generate MD5 hash, rc=%d\n", __func__, rc);
649+
hmac_md5_usingrawkey(ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE,
650+
ntlmv2->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE,
651+
ses->auth_key.response);
652+
rc = 0;
702653
unlock:
703654
cifs_server_unlock(ses->server);
704-
cifs_free_hash(&hmacmd5);
705655
setup_ntlmv2_rsp_ret:
706656
kfree_sensitive(tiblob);
707657

@@ -743,9 +693,6 @@ void
743693
cifs_crypto_secmech_release(struct TCP_Server_Info *server)
744694
{
745695
cifs_free_hash(&server->secmech.aes_cmac);
746-
cifs_free_hash(&server->secmech.hmacsha256);
747-
cifs_free_hash(&server->secmech.md5);
748-
cifs_free_hash(&server->secmech.sha512);
749696

750697
if (server->secmech.enc) {
751698
crypto_free_aead(server->secmech.enc);

0 commit comments

Comments
 (0)