summaryrefslogtreecommitdiffstats
path: root/include/crypto/aead.h
diff options
context:
space:
mode:
authorCorentin Labbe <clabbe@baylibre.com>2018-11-29 14:42:21 +0000
committerHerbert Xu <herbert@gondor.apana.org.au>2018-12-07 14:15:00 +0800
commitf7d76e05d058b832b373237566cc1af8251371b5 (patch)
tree1b445b1e5904b27f826fe363056d63823f5f4e83 /include/crypto/aead.h
parent76d09ea7c22f2cabf1f66ffc287c23b19b120be9 (diff)
downloadlinux-f7d76e05d058b832b373237566cc1af8251371b5.tar.gz
linux-f7d76e05d058b832b373237566cc1af8251371b5.tar.bz2
linux-f7d76e05d058b832b373237566cc1af8251371b5.zip
crypto: user - fix use_after_free of struct xxx_request
All crypto_stats functions use the struct xxx_request for feeding stats, but in some case this structure could already be freed. For fixing this, the needed parameters (len and alg) will be stored before the request being executed. Fixes: cac5818c25d0 ("crypto: user - Implement a generic crypto statistics") Reported-by: syzbot <syzbot+6939a606a5305e9e9799@syzkaller.appspotmail.com> Signed-off-by: Corentin Labbe <clabbe@baylibre.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'include/crypto/aead.h')
-rw-r--r--include/crypto/aead.h38
1 files changed, 8 insertions, 30 deletions
diff --git a/include/crypto/aead.h b/include/crypto/aead.h
index 99afd78c665d..b7b8d24cf765 100644
--- a/include/crypto/aead.h
+++ b/include/crypto/aead.h
@@ -306,34 +306,6 @@ static inline struct crypto_aead *crypto_aead_reqtfm(struct aead_request *req)
return __crypto_aead_cast(req->base.tfm);
}
-static inline void crypto_stat_aead_encrypt(struct aead_request *req, int ret)
-{
-#ifdef CONFIG_CRYPTO_STATS
- struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-
- if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
- atomic64_inc(&tfm->base.__crt_alg->aead_err_cnt);
- } else {
- atomic64_inc(&tfm->base.__crt_alg->encrypt_cnt);
- atomic64_add(req->cryptlen, &tfm->base.__crt_alg->encrypt_tlen);
- }
-#endif
-}
-
-static inline void crypto_stat_aead_decrypt(struct aead_request *req, int ret)
-{
-#ifdef CONFIG_CRYPTO_STATS
- struct crypto_aead *tfm = crypto_aead_reqtfm(req);
-
- if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
- atomic64_inc(&tfm->base.__crt_alg->aead_err_cnt);
- } else {
- atomic64_inc(&tfm->base.__crt_alg->decrypt_cnt);
- atomic64_add(req->cryptlen, &tfm->base.__crt_alg->decrypt_tlen);
- }
-#endif
-}
-
/**
* crypto_aead_encrypt() - encrypt plaintext
* @req: reference to the aead_request handle that holds all information
@@ -356,13 +328,16 @@ static inline void crypto_stat_aead_decrypt(struct aead_request *req, int ret)
static inline int crypto_aead_encrypt(struct aead_request *req)
{
struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_alg *alg = aead->base.__crt_alg;
+ unsigned int cryptlen = req->cryptlen;
int ret;
+ crypto_stats_get(alg);
if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY)
ret = -ENOKEY;
else
ret = crypto_aead_alg(aead)->encrypt(req);
- crypto_stat_aead_encrypt(req, ret);
+ crypto_stats_aead_encrypt(cryptlen, alg, ret);
return ret;
}
@@ -391,15 +366,18 @@ static inline int crypto_aead_encrypt(struct aead_request *req)
static inline int crypto_aead_decrypt(struct aead_request *req)
{
struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_alg *alg = aead->base.__crt_alg;
+ unsigned int cryptlen = req->cryptlen;
int ret;
+ crypto_stats_get(alg);
if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY)
ret = -ENOKEY;
else if (req->cryptlen < crypto_aead_authsize(aead))
ret = -EINVAL;
else
ret = crypto_aead_alg(aead)->decrypt(req);
- crypto_stat_aead_decrypt(req, ret);
+ crypto_stats_aead_decrypt(cryptlen, alg, ret);
return ret;
}