Commit c11e27a4 authored by Andreas Dilger's avatar Andreas Dilger Committed by Greg Kroah-Hartman

staging: lustre: libcfs: bug fixes for cfs_crypto_hash_final()

Change cfs_crypto_hash_final() to always clean up the hash descrptor
instead of not doing this in error cases.  All of the callers were
just calling cfs_crypto_hash_final() immediately to clean up the
descriptor anyway, and the old behaviour is unlike other init/fini
functions, and prone to memory leaks and other incorrect usage.  The
callers can call cfs_crypto_digest_size() to determine the hash size
in advance if needed, and avoid complexity in cfs_crypto_hash_final().
Signed-off-by: default avatarAndreas Dilger <andreas.dilger@intel.com>
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5053
Reviewed-on: http://review.whamcloud.com/9990Reviewed-by: default avatarBob Glossman <bob.glossman@intel.com>
Reviewed-by: default avatarJames Simmons <uja.ornl@gmail.com>
Reviewed-by: default avatarOleg Drokin <oleg.drokin@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 244cd87c
...@@ -265,8 +265,8 @@ EXPORT_SYMBOL(cfs_crypto_hash_update); ...@@ -265,8 +265,8 @@ EXPORT_SYMBOL(cfs_crypto_hash_update);
* \param[in,out] hash_len pointer to hash buffer size, if \a hdesc = NULL * \param[in,out] hash_len pointer to hash buffer size, if \a hdesc = NULL
* only free \a hdesc instead of computing the hash * only free \a hdesc instead of computing the hash
* *
* \retval -ENOSPC if \a hash = NULL, or \a hash_len < digest size
* \retval 0 for success * \retval 0 for success
* \retval -EOVERFLOW if hash_len is too small for the hash digest
* \retval negative errno for other errors from lower layers * \retval negative errno for other errors from lower layers
*/ */
int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *hdesc, int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *hdesc,
...@@ -276,22 +276,20 @@ int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *hdesc, ...@@ -276,22 +276,20 @@ int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *hdesc,
struct ahash_request *req = (void *)hdesc; struct ahash_request *req = (void *)hdesc;
int size = crypto_ahash_digestsize(crypto_ahash_reqtfm(req)); int size = crypto_ahash_digestsize(crypto_ahash_reqtfm(req));
if (!hash_len) { if (!hash || !hash_len) {
crypto_free_ahash(crypto_ahash_reqtfm(req)); err = 0;
ahash_request_free(req); goto free_ahash;
return 0;
} }
if (!hash || *hash_len < size) { if (*hash_len < size) {
*hash_len = size; err = -EOVERFLOW;
return -ENOSPC; goto free_ahash;
} }
ahash_request_set_crypt(req, NULL, hash, 0); ahash_request_set_crypt(req, NULL, hash, 0);
err = crypto_ahash_final(req); err = crypto_ahash_final(req);
if (!err)
if (err < 0) { *hash_len = size;
/* May be caller can fix error */ free_ahash:
return err;
}
crypto_free_ahash(crypto_ahash_reqtfm(req)); crypto_free_ahash(crypto_ahash_reqtfm(req));
ahash_request_free(req); ahash_request_free(req);
return err; return err;
......
...@@ -1208,12 +1208,9 @@ static u32 osc_checksum_bulk(int nob, u32 pg_count, ...@@ -1208,12 +1208,9 @@ static u32 osc_checksum_bulk(int nob, u32 pg_count,
i++; i++;
} }
bufsize = 4; bufsize = sizeof(cksum);
err = cfs_crypto_hash_final(hdesc, (unsigned char *)&cksum, &bufsize); err = cfs_crypto_hash_final(hdesc, (unsigned char *)&cksum, &bufsize);
if (err)
cfs_crypto_hash_final(hdesc, NULL, NULL);
/* For sending we only compute the wrong checksum instead /* For sending we only compute the wrong checksum instead
* of corrupting the data so it is still correct on a redo * of corrupting the data so it is still correct on a redo
*/ */
......
...@@ -41,7 +41,6 @@ ...@@ -41,7 +41,6 @@
#define DEBUG_SUBSYSTEM S_SEC #define DEBUG_SUBSYSTEM S_SEC
#include "../../include/linux/libcfs/libcfs.h" #include "../../include/linux/libcfs/libcfs.h"
#include <linux/crypto.h>
#include "../include/obd.h" #include "../include/obd.h"
#include "../include/obd_cksum.h" #include "../include/obd_cksum.h"
...@@ -511,7 +510,6 @@ int sptlrpc_get_bulk_checksum(struct ptlrpc_bulk_desc *desc, __u8 alg, ...@@ -511,7 +510,6 @@ int sptlrpc_get_bulk_checksum(struct ptlrpc_bulk_desc *desc, __u8 alg,
{ {
struct cfs_crypto_hash_desc *hdesc; struct cfs_crypto_hash_desc *hdesc;
int hashsize; int hashsize;
char hashbuf[64];
unsigned int bufsize; unsigned int bufsize;
int i, err; int i, err;
...@@ -532,18 +530,20 @@ int sptlrpc_get_bulk_checksum(struct ptlrpc_bulk_desc *desc, __u8 alg, ...@@ -532,18 +530,20 @@ int sptlrpc_get_bulk_checksum(struct ptlrpc_bulk_desc *desc, __u8 alg,
desc->bd_iov[i].kiov_offset & ~CFS_PAGE_MASK, desc->bd_iov[i].kiov_offset & ~CFS_PAGE_MASK,
desc->bd_iov[i].kiov_len); desc->bd_iov[i].kiov_len);
} }
if (hashsize > buflen) { if (hashsize > buflen) {
unsigned char hashbuf[CFS_CRYPTO_HASH_DIGESTSIZE_MAX];
bufsize = sizeof(hashbuf); bufsize = sizeof(hashbuf);
err = cfs_crypto_hash_final(hdesc, (unsigned char *)hashbuf, LASSERTF(bufsize >= hashsize, "bufsize = %u < hashsize %u\n",
&bufsize); bufsize, hashsize);
err = cfs_crypto_hash_final(hdesc, hashbuf, &bufsize);
memcpy(buf, hashbuf, buflen); memcpy(buf, hashbuf, buflen);
} else { } else {
bufsize = buflen; bufsize = buflen;
err = cfs_crypto_hash_final(hdesc, buf, &bufsize); err = cfs_crypto_hash_final(hdesc, buf, &bufsize);
} }
if (err)
cfs_crypto_hash_final(hdesc, NULL, NULL);
return err; return err;
} }
EXPORT_SYMBOL(sptlrpc_get_bulk_checksum); EXPORT_SYMBOL(sptlrpc_get_bulk_checksum);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment