Skip to content

Commit 95dc8dd

Browse files
committed
Limit allocation of crypto mechanisms to dialect which requires
Updated patch to try to prevent allocation of cifs, smb2 or smb3 crypto secmech structures unless needed. Currently cifs allocates all crypto mechanisms when the first session is established (4 functions and 4 contexts), rather than only allocating these when needed (smb3 needs two, the rest of the dialects only need one). Acked-by: Jeff Layton <[email protected]> Reviewed-by: Shirish Pargaonkar <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 80cc38b commit 95dc8dd

File tree

4 files changed

+174
-118
lines changed

4 files changed

+174
-118
lines changed

fs/cifs/cifsencrypt.c

+85-110
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* fs/cifs/cifsencrypt.c
33
*
4-
* Copyright (C) International Business Machines Corp., 2005,2006
4+
* Copyright (C) International Business Machines Corp., 2005,2013
55
* Author(s): Steve French ([email protected])
66
*
77
* This library is free software; you can redistribute it and/or modify
@@ -31,6 +31,36 @@
3131
#include <linux/random.h>
3232
#include <linux/highmem.h>
3333

34+
static int
35+
cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server)
36+
{
37+
int rc;
38+
unsigned int size;
39+
40+
if (server->secmech.sdescmd5 != NULL)
41+
return 0; /* already allocated */
42+
43+
server->secmech.md5 = crypto_alloc_shash("md5", 0, 0);
44+
if (IS_ERR(server->secmech.md5)) {
45+
cifs_dbg(VFS, "could not allocate crypto md5\n");
46+
return PTR_ERR(server->secmech.md5);
47+
}
48+
49+
size = sizeof(struct shash_desc) +
50+
crypto_shash_descsize(server->secmech.md5);
51+
server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
52+
if (!server->secmech.sdescmd5) {
53+
rc = -ENOMEM;
54+
crypto_free_shash(server->secmech.md5);
55+
server->secmech.md5 = NULL;
56+
return rc;
57+
}
58+
server->secmech.sdescmd5->shash.tfm = server->secmech.md5;
59+
server->secmech.sdescmd5->shash.flags = 0x0;
60+
61+
return 0;
62+
}
63+
3464
/*
3565
* Calculate and return the CIFS signature based on the mac key and SMB PDU.
3666
* The 16 byte signature must be allocated by the caller. Note we only use the
@@ -50,8 +80,11 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
5080
return -EINVAL;
5181

5282
if (!server->secmech.sdescmd5) {
53-
cifs_dbg(VFS, "%s: Can't generate signature\n", __func__);
54-
return -1;
83+
rc = cifs_crypto_shash_md5_allocate(server);
84+
if (rc) {
85+
cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__);
86+
return -1;
87+
}
5588
}
5689

5790
rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
@@ -556,6 +589,33 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
556589
return rc;
557590
}
558591

592+
static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server)
593+
{
594+
unsigned int size;
595+
596+
/* check if already allocated */
597+
if (server->secmech.sdeschmacmd5)
598+
return 0;
599+
600+
server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
601+
if (IS_ERR(server->secmech.hmacmd5)) {
602+
cifs_dbg(VFS, "could not allocate crypto hmacmd5\n");
603+
return PTR_ERR(server->secmech.hmacmd5);
604+
}
605+
606+
size = sizeof(struct shash_desc) +
607+
crypto_shash_descsize(server->secmech.hmacmd5);
608+
server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
609+
if (!server->secmech.sdeschmacmd5) {
610+
crypto_free_shash(server->secmech.hmacmd5);
611+
server->secmech.hmacmd5 = NULL;
612+
return -ENOMEM;
613+
}
614+
server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5;
615+
server->secmech.sdeschmacmd5->shash.flags = 0x0;
616+
617+
return 0;
618+
}
559619

560620
int
561621
setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
@@ -606,6 +666,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
606666

607667
memcpy(ses->auth_key.response + baselen, tiblob, tilen);
608668

669+
rc = crypto_hmacmd5_alloc(ses->server);
670+
if (rc) {
671+
cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc);
672+
goto setup_ntlmv2_rsp_ret;
673+
}
674+
609675
/* calculate ntlmv2_hash */
610676
rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
611677
if (rc) {
@@ -705,123 +771,32 @@ calc_seckey(struct cifs_ses *ses)
705771
void
706772
cifs_crypto_shash_release(struct TCP_Server_Info *server)
707773
{
708-
if (server->secmech.cmacaes)
774+
if (server->secmech.cmacaes) {
709775
crypto_free_shash(server->secmech.cmacaes);
776+
server->secmech.cmacaes = NULL;
777+
}
710778

711-
if (server->secmech.hmacsha256)
779+
if (server->secmech.hmacsha256) {
712780
crypto_free_shash(server->secmech.hmacsha256);
781+
server->secmech.hmacsha256 = NULL;
782+
}
713783

714-
if (server->secmech.md5)
784+
if (server->secmech.md5) {
715785
crypto_free_shash(server->secmech.md5);
786+
server->secmech.md5 = NULL;
787+
}
716788

717-
if (server->secmech.hmacmd5)
789+
if (server->secmech.hmacmd5) {
718790
crypto_free_shash(server->secmech.hmacmd5);
791+
server->secmech.hmacmd5 = NULL;
792+
}
719793

720794
kfree(server->secmech.sdesccmacaes);
721-
795+
server->secmech.sdesccmacaes = NULL;
722796
kfree(server->secmech.sdeschmacsha256);
723-
797+
server->secmech.sdeschmacsha256 = NULL;
724798
kfree(server->secmech.sdeschmacmd5);
725-
799+
server->secmech.sdeschmacmd5 = NULL;
726800
kfree(server->secmech.sdescmd5);
727-
}
728-
729-
int
730-
cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
731-
{
732-
int rc;
733-
unsigned int size;
734-
735-
server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
736-
if (IS_ERR(server->secmech.hmacmd5)) {
737-
cifs_dbg(VFS, "could not allocate crypto hmacmd5\n");
738-
return PTR_ERR(server->secmech.hmacmd5);
739-
}
740-
741-
server->secmech.md5 = crypto_alloc_shash("md5", 0, 0);
742-
if (IS_ERR(server->secmech.md5)) {
743-
cifs_dbg(VFS, "could not allocate crypto md5\n");
744-
rc = PTR_ERR(server->secmech.md5);
745-
goto crypto_allocate_md5_fail;
746-
}
747-
748-
server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
749-
if (IS_ERR(server->secmech.hmacsha256)) {
750-
cifs_dbg(VFS, "could not allocate crypto hmacsha256\n");
751-
rc = PTR_ERR(server->secmech.hmacsha256);
752-
goto crypto_allocate_hmacsha256_fail;
753-
}
754-
755-
server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0);
756-
if (IS_ERR(server->secmech.cmacaes)) {
757-
cifs_dbg(VFS, "could not allocate crypto cmac-aes");
758-
rc = PTR_ERR(server->secmech.cmacaes);
759-
goto crypto_allocate_cmacaes_fail;
760-
}
761-
762-
size = sizeof(struct shash_desc) +
763-
crypto_shash_descsize(server->secmech.hmacmd5);
764-
server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
765-
if (!server->secmech.sdeschmacmd5) {
766-
rc = -ENOMEM;
767-
goto crypto_allocate_hmacmd5_sdesc_fail;
768-
}
769-
server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5;
770-
server->secmech.sdeschmacmd5->shash.flags = 0x0;
771-
772-
size = sizeof(struct shash_desc) +
773-
crypto_shash_descsize(server->secmech.md5);
774-
server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
775-
if (!server->secmech.sdescmd5) {
776-
rc = -ENOMEM;
777-
goto crypto_allocate_md5_sdesc_fail;
778-
}
779-
server->secmech.sdescmd5->shash.tfm = server->secmech.md5;
780-
server->secmech.sdescmd5->shash.flags = 0x0;
781-
782-
size = sizeof(struct shash_desc) +
783-
crypto_shash_descsize(server->secmech.hmacsha256);
784-
server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL);
785-
if (!server->secmech.sdeschmacsha256) {
786-
rc = -ENOMEM;
787-
goto crypto_allocate_hmacsha256_sdesc_fail;
788-
}
789-
server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256;
790-
server->secmech.sdeschmacsha256->shash.flags = 0x0;
791-
792-
size = sizeof(struct shash_desc) +
793-
crypto_shash_descsize(server->secmech.cmacaes);
794-
server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL);
795-
if (!server->secmech.sdesccmacaes) {
796-
cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__);
797-
rc = -ENOMEM;
798-
goto crypto_allocate_cmacaes_sdesc_fail;
799-
}
800-
server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes;
801-
server->secmech.sdesccmacaes->shash.flags = 0x0;
802-
803-
return 0;
804-
805-
crypto_allocate_cmacaes_sdesc_fail:
806-
kfree(server->secmech.sdeschmacsha256);
807-
808-
crypto_allocate_hmacsha256_sdesc_fail:
809-
kfree(server->secmech.sdescmd5);
810-
811-
crypto_allocate_md5_sdesc_fail:
812-
kfree(server->secmech.sdeschmacmd5);
813-
814-
crypto_allocate_hmacmd5_sdesc_fail:
815-
crypto_free_shash(server->secmech.cmacaes);
816-
817-
crypto_allocate_cmacaes_fail:
818-
crypto_free_shash(server->secmech.hmacsha256);
819-
820-
crypto_allocate_hmacsha256_fail:
821-
crypto_free_shash(server->secmech.md5);
822-
823-
crypto_allocate_md5_fail:
824-
crypto_free_shash(server->secmech.hmacmd5);
825-
826-
return rc;
801+
server->secmech.sdescmd5 = NULL;
827802
}

fs/cifs/cifsproto.h

-1
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,6 @@ extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *,
433433
const struct nls_table *);
434434
extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *);
435435
extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
436-
extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *);
437436
extern void cifs_crypto_shash_release(struct TCP_Server_Info *);
438437
extern int calc_seckey(struct cifs_ses *);
439438
extern void generate_smb3signingkey(struct TCP_Server_Info *);

fs/cifs/connect.c

-6
Original file line numberDiff line numberDiff line change
@@ -2108,12 +2108,6 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
21082108
goto out_err;
21092109
}
21102110

2111-
rc = cifs_crypto_shash_allocate(tcp_ses);
2112-
if (rc) {
2113-
cifs_dbg(VFS, "could not setup hash structures rc %d\n", rc);
2114-
goto out_err;
2115-
}
2116-
21172111
tcp_ses->ops = volume_info->ops;
21182112
tcp_ses->vals = volume_info->vals;
21192113
cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));

fs/cifs/smb2transport.c

+89-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,77 @@
3939
#include "smb2status.h"
4040
#include "smb2glob.h"
4141

42+
static int
43+
smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
44+
{
45+
unsigned int size;
46+
47+
if (server->secmech.sdeschmacsha256 != NULL)
48+
return 0; /* already allocated */
49+
50+
server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
51+
if (IS_ERR(server->secmech.hmacsha256)) {
52+
cifs_dbg(VFS, "could not allocate crypto hmacsha256\n");
53+
return PTR_ERR(server->secmech.hmacsha256);
54+
}
55+
56+
size = sizeof(struct shash_desc) +
57+
crypto_shash_descsize(server->secmech.hmacsha256);
58+
server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL);
59+
if (!server->secmech.sdeschmacsha256) {
60+
crypto_free_shash(server->secmech.hmacsha256);
61+
server->secmech.hmacsha256 = NULL;
62+
return -ENOMEM;
63+
}
64+
server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256;
65+
server->secmech.sdeschmacsha256->shash.flags = 0x0;
66+
67+
return 0;
68+
}
69+
70+
static int
71+
smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
72+
{
73+
unsigned int size;
74+
int rc;
75+
76+
if (server->secmech.sdesccmacaes != NULL)
77+
return 0; /* already allocated */
78+
79+
rc = smb2_crypto_shash_allocate(server);
80+
if (rc)
81+
return rc;
82+
83+
server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0);
84+
if (IS_ERR(server->secmech.cmacaes)) {
85+
cifs_dbg(VFS, "could not allocate crypto cmac-aes");
86+
kfree(server->secmech.sdeschmacsha256);
87+
server->secmech.sdeschmacsha256 = NULL;
88+
crypto_free_shash(server->secmech.hmacsha256);
89+
server->secmech.hmacsha256 = NULL;
90+
return PTR_ERR(server->secmech.cmacaes);
91+
}
92+
93+
size = sizeof(struct shash_desc) +
94+
crypto_shash_descsize(server->secmech.cmacaes);
95+
server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL);
96+
if (!server->secmech.sdesccmacaes) {
97+
cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__);
98+
kfree(server->secmech.sdeschmacsha256);
99+
server->secmech.sdeschmacsha256 = NULL;
100+
crypto_free_shash(server->secmech.hmacsha256);
101+
crypto_free_shash(server->secmech.cmacaes);
102+
server->secmech.hmacsha256 = NULL;
103+
server->secmech.cmacaes = NULL;
104+
return -ENOMEM;
105+
}
106+
server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes;
107+
server->secmech.sdesccmacaes->shash.flags = 0x0;
108+
109+
return 0;
110+
}
111+
112+
42113
int
43114
smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
44115
{
@@ -52,6 +123,12 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
52123
memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
53124
memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE);
54125

126+
rc = smb2_crypto_shash_allocate(server);
127+
if (rc) {
128+
cifs_dbg(VFS, "%s: shah256 alloc failed\n", __func__);
129+
return rc;
130+
}
131+
55132
rc = crypto_shash_setkey(server->secmech.hmacsha256,
56133
server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
57134
if (rc) {
@@ -61,7 +138,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
61138

62139
rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
63140
if (rc) {
64-
cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
141+
cifs_dbg(VFS, "%s: Could not init sha256", __func__);
65142
return rc;
66143
}
67144

@@ -129,6 +206,12 @@ generate_smb3signingkey(struct TCP_Server_Info *server)
129206
memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
130207
memset(server->smb3signingkey, 0x0, SMB3_SIGNKEY_SIZE);
131208

209+
rc = smb3_crypto_shash_allocate(server);
210+
if (rc) {
211+
cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
212+
goto smb3signkey_ret;
213+
}
214+
132215
rc = crypto_shash_setkey(server->secmech.hmacsha256,
133216
server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
134217
if (rc) {
@@ -210,6 +293,11 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
210293
return rc;
211294
}
212295

296+
/*
297+
* we already allocate sdesccmacaes when we init smb3 signing key,
298+
* so unlike smb2 case we do not have to check here if secmech are
299+
* initialized
300+
*/
213301
rc = crypto_shash_init(&server->secmech.sdesccmacaes->shash);
214302
if (rc) {
215303
cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__);

0 commit comments

Comments
 (0)