mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 05:44:11 +00:00
[CRYPTO] all: Check for usage in hard IRQ context
Using blkcipher/hash crypto operations in hard IRQ context can lead to random memory corruption due to the reuse of kmap_atomic slots. Since crypto operations were never meant to be used in hard IRQ contexts, this patch checks for such usage and returns an error before kmap_atomic is performed. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
62d0cfcb27
commit
fb469840b8
3 changed files with 37 additions and 7 deletions
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include <linux/crypto.h>
|
#include <linux/crypto.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
#include <linux/hardirq.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/scatterlist.h>
|
#include <linux/scatterlist.h>
|
||||||
|
@ -313,6 +314,9 @@ static int blkcipher_walk_first(struct blkcipher_desc *desc,
|
||||||
struct crypto_blkcipher *tfm = desc->tfm;
|
struct crypto_blkcipher *tfm = desc->tfm;
|
||||||
unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
|
unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(in_irq()))
|
||||||
|
return -EDEADLK;
|
||||||
|
|
||||||
walk->nbytes = walk->total;
|
walk->nbytes = walk->total;
|
||||||
if (unlikely(!walk->total))
|
if (unlikely(!walk->total))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
|
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
#include <linux/hardirq.h>
|
||||||
#include <linux/highmem.h>
|
#include <linux/highmem.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/scatterlist.h>
|
#include <linux/scatterlist.h>
|
||||||
|
|
||||||
|
@ -29,8 +31,8 @@ static int init(struct hash_desc *desc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int update(struct hash_desc *desc,
|
static int update2(struct hash_desc *desc,
|
||||||
struct scatterlist *sg, unsigned int nbytes)
|
struct scatterlist *sg, unsigned int nbytes)
|
||||||
{
|
{
|
||||||
struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
|
struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
|
||||||
unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
|
unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
|
||||||
|
@ -81,6 +83,14 @@ static int update(struct hash_desc *desc,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int update(struct hash_desc *desc,
|
||||||
|
struct scatterlist *sg, unsigned int nbytes)
|
||||||
|
{
|
||||||
|
if (WARN_ON_ONCE(in_irq()))
|
||||||
|
return -EDEADLK;
|
||||||
|
return update2(desc, sg, nbytes);
|
||||||
|
}
|
||||||
|
|
||||||
static int final(struct hash_desc *desc, u8 *out)
|
static int final(struct hash_desc *desc, u8 *out)
|
||||||
{
|
{
|
||||||
struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
|
struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
|
||||||
|
@ -118,8 +128,11 @@ static int setkey(struct crypto_hash *hash, const u8 *key, unsigned int keylen)
|
||||||
static int digest(struct hash_desc *desc,
|
static int digest(struct hash_desc *desc,
|
||||||
struct scatterlist *sg, unsigned int nbytes, u8 *out)
|
struct scatterlist *sg, unsigned int nbytes, u8 *out)
|
||||||
{
|
{
|
||||||
|
if (WARN_ON_ONCE(in_irq()))
|
||||||
|
return -EDEADLK;
|
||||||
|
|
||||||
init(desc);
|
init(desc);
|
||||||
update(desc, sg, nbytes);
|
update2(desc, sg, nbytes);
|
||||||
return final(desc, out);
|
return final(desc, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include <linux/crypto.h>
|
#include <linux/crypto.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
#include <linux/hardirq.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
|
@ -108,9 +109,9 @@ static int crypto_xcbc_digest_init(struct hash_desc *pdesc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
|
static int crypto_xcbc_digest_update2(struct hash_desc *pdesc,
|
||||||
struct scatterlist *sg,
|
struct scatterlist *sg,
|
||||||
unsigned int nbytes)
|
unsigned int nbytes)
|
||||||
{
|
{
|
||||||
struct crypto_hash *parent = pdesc->tfm;
|
struct crypto_hash *parent = pdesc->tfm;
|
||||||
struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
|
struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
|
||||||
|
@ -183,6 +184,15 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
|
||||||
|
struct scatterlist *sg,
|
||||||
|
unsigned int nbytes)
|
||||||
|
{
|
||||||
|
if (WARN_ON_ONCE(in_irq()))
|
||||||
|
return -EDEADLK;
|
||||||
|
return crypto_xcbc_digest_update2(pdesc, sg, nbytes);
|
||||||
|
}
|
||||||
|
|
||||||
static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
|
static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
|
||||||
{
|
{
|
||||||
struct crypto_hash *parent = pdesc->tfm;
|
struct crypto_hash *parent = pdesc->tfm;
|
||||||
|
@ -234,8 +244,11 @@ static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
|
||||||
static int crypto_xcbc_digest(struct hash_desc *pdesc,
|
static int crypto_xcbc_digest(struct hash_desc *pdesc,
|
||||||
struct scatterlist *sg, unsigned int nbytes, u8 *out)
|
struct scatterlist *sg, unsigned int nbytes, u8 *out)
|
||||||
{
|
{
|
||||||
|
if (WARN_ON_ONCE(in_irq()))
|
||||||
|
return -EDEADLK;
|
||||||
|
|
||||||
crypto_xcbc_digest_init(pdesc);
|
crypto_xcbc_digest_init(pdesc);
|
||||||
crypto_xcbc_digest_update(pdesc, sg, nbytes);
|
crypto_xcbc_digest_update2(pdesc, sg, nbytes);
|
||||||
return crypto_xcbc_digest_final(pdesc, out);
|
return crypto_xcbc_digest_final(pdesc, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue