| From 82fb82be05585426405667dd5f0510aa953ba439 Mon Sep 17 00:00:00 2001 |
| From: Aurelien Aptel <aaptel@suse.com> |
| Date: Fri, 16 Feb 2018 19:19:27 +0100 |
| Subject: CIFS: refactor crypto shash/sdesc allocation&free |
| |
| From: Aurelien Aptel <aaptel@suse.com> |
| |
| commit 82fb82be05585426405667dd5f0510aa953ba439 upstream. |
| |
| shash and sdesc and always allocated and freed together. |
| * abstract this in new functions cifs_alloc_hash() and cifs_free_hash(). |
| * make smb2/3 crypto allocation independent from each other. |
| |
| Signed-off-by: Aurelien Aptel <aaptel@suse.com> |
| Signed-off-by: Steve French <smfrench@gmail.com> |
| Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com> |
| CC: Stable <stable@vger.kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/cifs/cifsencrypt.c | 78 ++++-------------------------------------------- |
| fs/cifs/cifsproto.h | 5 +++ |
| fs/cifs/link.c | 25 +++------------ |
| fs/cifs/misc.c | 54 +++++++++++++++++++++++++++++++++ |
| fs/cifs/smb2transport.c | 75 +++++++++------------------------------------- |
| fs/cifs/smbencrypt.c | 25 +++------------ |
| 6 files changed, 91 insertions(+), 171 deletions(-) |
| |
| --- a/fs/cifs/cifsencrypt.c |
| +++ b/fs/cifs/cifsencrypt.c |
| @@ -36,37 +36,6 @@ |
| #include <crypto/skcipher.h> |
| #include <crypto/aead.h> |
| |
| -static int |
| -cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server) |
| -{ |
| - int rc; |
| - unsigned int size; |
| - |
| - if (server->secmech.sdescmd5 != NULL) |
| - return 0; /* already allocated */ |
| - |
| - server->secmech.md5 = crypto_alloc_shash("md5", 0, 0); |
| - if (IS_ERR(server->secmech.md5)) { |
| - cifs_dbg(VFS, "could not allocate crypto md5\n"); |
| - rc = PTR_ERR(server->secmech.md5); |
| - server->secmech.md5 = NULL; |
| - return rc; |
| - } |
| - |
| - size = sizeof(struct shash_desc) + |
| - crypto_shash_descsize(server->secmech.md5); |
| - server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL); |
| - if (!server->secmech.sdescmd5) { |
| - crypto_free_shash(server->secmech.md5); |
| - server->secmech.md5 = NULL; |
| - return -ENOMEM; |
| - } |
| - server->secmech.sdescmd5->shash.tfm = server->secmech.md5; |
| - server->secmech.sdescmd5->shash.flags = 0x0; |
| - |
| - return 0; |
| -} |
| - |
| int __cifs_calc_signature(struct smb_rqst *rqst, |
| struct TCP_Server_Info *server, char *signature, |
| struct shash_desc *shash) |
| @@ -132,13 +101,10 @@ static int cifs_calc_signature(struct sm |
| if (!rqst->rq_iov || !signature || !server) |
| return -EINVAL; |
| |
| - if (!server->secmech.sdescmd5) { |
| - rc = cifs_crypto_shash_md5_allocate(server); |
| - if (rc) { |
| - cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__); |
| - return -1; |
| - } |
| - } |
| + rc = cifs_alloc_hash("md5", &server->secmech.md5, |
| + &server->secmech.sdescmd5); |
| + if (rc) |
| + return -1; |
| |
| rc = crypto_shash_init(&server->secmech.sdescmd5->shash); |
| if (rc) { |
| @@ -663,37 +629,6 @@ CalcNTLMv2_response(const struct cifs_se |
| return rc; |
| } |
| |
| -static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server) |
| -{ |
| - int rc; |
| - unsigned int size; |
| - |
| - /* check if already allocated */ |
| - if (server->secmech.sdeschmacmd5) |
| - return 0; |
| - |
| - server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); |
| - if (IS_ERR(server->secmech.hmacmd5)) { |
| - cifs_dbg(VFS, "could not allocate crypto hmacmd5\n"); |
| - rc = PTR_ERR(server->secmech.hmacmd5); |
| - server->secmech.hmacmd5 = NULL; |
| - return rc; |
| - } |
| - |
| - size = sizeof(struct shash_desc) + |
| - crypto_shash_descsize(server->secmech.hmacmd5); |
| - server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); |
| - if (!server->secmech.sdeschmacmd5) { |
| - crypto_free_shash(server->secmech.hmacmd5); |
| - server->secmech.hmacmd5 = NULL; |
| - return -ENOMEM; |
| - } |
| - server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5; |
| - server->secmech.sdeschmacmd5->shash.flags = 0x0; |
| - |
| - return 0; |
| -} |
| - |
| int |
| setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) |
| { |
| @@ -757,9 +692,10 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, c |
| |
| mutex_lock(&ses->server->srv_mutex); |
| |
| - rc = crypto_hmacmd5_alloc(ses->server); |
| + rc = cifs_alloc_hash("hmac(md5)", |
| + &ses->server->secmech.hmacmd5, |
| + &ses->server->secmech.sdeschmacmd5); |
| if (rc) { |
| - cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc); |
| goto unlock; |
| } |
| |
| --- a/fs/cifs/cifsproto.h |
| +++ b/fs/cifs/cifsproto.h |
| @@ -538,4 +538,9 @@ enum securityEnum cifs_select_sectype(st |
| struct cifs_aio_ctx *cifs_aio_ctx_alloc(void); |
| void cifs_aio_ctx_release(struct kref *refcount); |
| int setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw); |
| + |
| +int cifs_alloc_hash(const char *name, struct crypto_shash **shash, |
| + struct sdesc **sdesc); |
| +void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc); |
| + |
| #endif /* _CIFSPROTO_H */ |
| --- a/fs/cifs/link.c |
| +++ b/fs/cifs/link.c |
| @@ -50,25 +50,12 @@ static int |
| symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash) |
| { |
| int rc; |
| - unsigned int size; |
| - struct crypto_shash *md5; |
| - struct sdesc *sdescmd5; |
| + struct crypto_shash *md5 = NULL; |
| + struct sdesc *sdescmd5 = NULL; |
| |
| - md5 = crypto_alloc_shash("md5", 0, 0); |
| - if (IS_ERR(md5)) { |
| - rc = PTR_ERR(md5); |
| - cifs_dbg(VFS, "%s: Crypto md5 allocation error %d\n", |
| - __func__, rc); |
| - return rc; |
| - } |
| - size = sizeof(struct shash_desc) + crypto_shash_descsize(md5); |
| - sdescmd5 = kmalloc(size, GFP_KERNEL); |
| - if (!sdescmd5) { |
| - rc = -ENOMEM; |
| + rc = cifs_alloc_hash("md5", &md5, &sdescmd5); |
| + if (rc) |
| goto symlink_hash_err; |
| - } |
| - sdescmd5->shash.tfm = md5; |
| - sdescmd5->shash.flags = 0x0; |
| |
| rc = crypto_shash_init(&sdescmd5->shash); |
| if (rc) { |
| @@ -85,9 +72,7 @@ symlink_hash(unsigned int link_len, cons |
| cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__); |
| |
| symlink_hash_err: |
| - crypto_free_shash(md5); |
| - kfree(sdescmd5); |
| - |
| + cifs_free_hash(&md5, &sdescmd5); |
| return rc; |
| } |
| |
| --- a/fs/cifs/misc.c |
| +++ b/fs/cifs/misc.c |
| @@ -848,3 +848,57 @@ setup_aio_ctx_iter(struct cifs_aio_ctx * |
| iov_iter_bvec(&ctx->iter, ITER_BVEC | rw, ctx->bv, npages, ctx->len); |
| return 0; |
| } |
| + |
| +/** |
| + * cifs_alloc_hash - allocate hash and hash context together |
| + * |
| + * The caller has to make sure @sdesc is initialized to either NULL or |
| + * a valid context. Both can be freed via cifs_free_hash(). |
| + */ |
| +int |
| +cifs_alloc_hash(const char *name, |
| + struct crypto_shash **shash, struct sdesc **sdesc) |
| +{ |
| + int rc = 0; |
| + size_t size; |
| + |
| + if (*sdesc != NULL) |
| + return 0; |
| + |
| + *shash = crypto_alloc_shash(name, 0, 0); |
| + if (IS_ERR(*shash)) { |
| + cifs_dbg(VFS, "could not allocate crypto %s\n", name); |
| + rc = PTR_ERR(*shash); |
| + *shash = NULL; |
| + *sdesc = NULL; |
| + return rc; |
| + } |
| + |
| + size = sizeof(struct shash_desc) + crypto_shash_descsize(*shash); |
| + *sdesc = kmalloc(size, GFP_KERNEL); |
| + if (*sdesc == NULL) { |
| + cifs_dbg(VFS, "no memory left to allocate crypto %s\n", name); |
| + crypto_free_shash(*shash); |
| + *shash = NULL; |
| + return -ENOMEM; |
| + } |
| + |
| + (*sdesc)->shash.tfm = *shash; |
| + (*sdesc)->shash.flags = 0x0; |
| + return 0; |
| +} |
| + |
| +/** |
| + * cifs_free_hash - free hash and hash context together |
| + * |
| + * Freeing a NULL hash or context is safe. |
| + */ |
| +void |
| +cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc) |
| +{ |
| + kfree(*sdesc); |
| + *sdesc = NULL; |
| + if (*shash) |
| + crypto_free_shash(*shash); |
| + *shash = NULL; |
| +} |
| --- a/fs/cifs/smb2transport.c |
| +++ b/fs/cifs/smb2transport.c |
| @@ -43,76 +43,31 @@ |
| static int |
| smb2_crypto_shash_allocate(struct TCP_Server_Info *server) |
| { |
| - int rc; |
| - unsigned int size; |
| - |
| - if (server->secmech.sdeschmacsha256 != NULL) |
| - return 0; /* already allocated */ |
| - |
| - server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0); |
| - if (IS_ERR(server->secmech.hmacsha256)) { |
| - cifs_dbg(VFS, "could not allocate crypto hmacsha256\n"); |
| - rc = PTR_ERR(server->secmech.hmacsha256); |
| - server->secmech.hmacsha256 = NULL; |
| - return rc; |
| - } |
| - |
| - size = sizeof(struct shash_desc) + |
| - crypto_shash_descsize(server->secmech.hmacsha256); |
| - server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL); |
| - if (!server->secmech.sdeschmacsha256) { |
| - crypto_free_shash(server->secmech.hmacsha256); |
| - server->secmech.hmacsha256 = NULL; |
| - return -ENOMEM; |
| - } |
| - server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256; |
| - server->secmech.sdeschmacsha256->shash.flags = 0x0; |
| - |
| - return 0; |
| + return cifs_alloc_hash("hmac(sha256)", |
| + &server->secmech.hmacsha256, |
| + &server->secmech.sdeschmacsha256); |
| } |
| |
| static int |
| smb3_crypto_shash_allocate(struct TCP_Server_Info *server) |
| { |
| - unsigned int size; |
| + struct cifs_secmech *p = &server->secmech; |
| int rc; |
| |
| - if (server->secmech.sdesccmacaes != NULL) |
| - return 0; /* already allocated */ |
| - |
| - rc = smb2_crypto_shash_allocate(server); |
| + rc = cifs_alloc_hash("hmac(sha256)", |
| + &p->hmacsha256, |
| + &p->sdeschmacsha256); |
| if (rc) |
| - return rc; |
| - |
| - server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0); |
| - if (IS_ERR(server->secmech.cmacaes)) { |
| - cifs_dbg(VFS, "could not allocate crypto cmac-aes"); |
| - kfree(server->secmech.sdeschmacsha256); |
| - server->secmech.sdeschmacsha256 = NULL; |
| - crypto_free_shash(server->secmech.hmacsha256); |
| - server->secmech.hmacsha256 = NULL; |
| - rc = PTR_ERR(server->secmech.cmacaes); |
| - server->secmech.cmacaes = NULL; |
| - return rc; |
| - } |
| + goto err; |
| |
| - size = sizeof(struct shash_desc) + |
| - crypto_shash_descsize(server->secmech.cmacaes); |
| - server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL); |
| - if (!server->secmech.sdesccmacaes) { |
| - cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__); |
| - kfree(server->secmech.sdeschmacsha256); |
| - server->secmech.sdeschmacsha256 = NULL; |
| - crypto_free_shash(server->secmech.hmacsha256); |
| - crypto_free_shash(server->secmech.cmacaes); |
| - server->secmech.hmacsha256 = NULL; |
| - server->secmech.cmacaes = NULL; |
| - return -ENOMEM; |
| - } |
| - server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes; |
| - server->secmech.sdesccmacaes->shash.flags = 0x0; |
| + rc = cifs_alloc_hash("cmac(aes)", &p->cmacaes, &p->sdesccmacaes); |
| + if (rc) |
| + goto err; |
| |
| return 0; |
| +err: |
| + cifs_free_hash(&p->hmacsha256, &p->sdeschmacsha256); |
| + return rc; |
| } |
| |
| static struct cifs_ses * |
| @@ -457,7 +412,7 @@ smb3_calc_signature(struct smb_rqst *rqs |
| cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__); |
| return rc; |
| } |
| - |
| + |
| rc = __cifs_calc_signature(rqst, server, sigptr, |
| &server->secmech.sdesccmacaes->shash); |
| |
| --- a/fs/cifs/smbencrypt.c |
| +++ b/fs/cifs/smbencrypt.c |
| @@ -121,25 +121,12 @@ int |
| mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len) |
| { |
| int rc; |
| - unsigned int size; |
| - struct crypto_shash *md4; |
| - struct sdesc *sdescmd4; |
| + struct crypto_shash *md4 = NULL; |
| + struct sdesc *sdescmd4 = NULL; |
| |
| - md4 = crypto_alloc_shash("md4", 0, 0); |
| - if (IS_ERR(md4)) { |
| - rc = PTR_ERR(md4); |
| - cifs_dbg(VFS, "%s: Crypto md4 allocation error %d\n", |
| - __func__, rc); |
| - return rc; |
| - } |
| - size = sizeof(struct shash_desc) + crypto_shash_descsize(md4); |
| - sdescmd4 = kmalloc(size, GFP_KERNEL); |
| - if (!sdescmd4) { |
| - rc = -ENOMEM; |
| + rc = cifs_alloc_hash("md4", &md4, &sdescmd4); |
| + if (rc) |
| goto mdfour_err; |
| - } |
| - sdescmd4->shash.tfm = md4; |
| - sdescmd4->shash.flags = 0x0; |
| |
| rc = crypto_shash_init(&sdescmd4->shash); |
| if (rc) { |
| @@ -156,9 +143,7 @@ mdfour(unsigned char *md4_hash, unsigned |
| cifs_dbg(VFS, "%s: Could not generate md4 hash\n", __func__); |
| |
| mdfour_err: |
| - crypto_free_shash(md4); |
| - kfree(sdescmd4); |
| - |
| + cifs_free_hash(&md4, &sdescmd4); |
| return rc; |
| } |
| |