diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2006-12-10 02:45:28 +0300 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2007-02-07 01:20:58 +0300 |
commit | fb469840b8c34b2f95b40a64b271f245cc1075b7 (patch) | |
tree | 8013f8beb39c83b80be0e40195005b0482cea69b | |
parent | 62d0cfcb27cf755cebdc93ca95dabc83608007cd (diff) | |
download | linux-fb469840b8c34b2f95b40a64b271f245cc1075b7.tar.xz |
[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>
-rw-r--r-- | crypto/blkcipher.c | 4 | ||||
-rw-r--r-- | crypto/digest.c | 19 | ||||
-rw-r--r-- | crypto/xcbc.c | 21 |
3 files changed, 37 insertions, 7 deletions
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index 6e93004f2181..cbb4c4e5c229 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c @@ -16,6 +16,7 @@ #include <linux/crypto.h> #include <linux/errno.h> +#include <linux/hardirq.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/scatterlist.h> @@ -313,6 +314,9 @@ static int blkcipher_walk_first(struct blkcipher_desc *desc, struct crypto_blkcipher *tfm = desc->tfm; unsigned int alignmask = crypto_blkcipher_alignmask(tfm); + if (WARN_ON_ONCE(in_irq())) + return -EDEADLK; + walk->nbytes = walk->total; if (unlikely(!walk->total)) return 0; diff --git a/crypto/digest.c b/crypto/digest.c index 8f4593268ce0..bc47af648cb1 100644 --- a/crypto/digest.c +++ b/crypto/digest.c @@ -14,7 +14,9 @@ #include <linux/mm.h> #include <linux/errno.h> +#include <linux/hardirq.h> #include <linux/highmem.h> +#include <linux/kernel.h> #include <linux/module.h> #include <linux/scatterlist.h> @@ -29,8 +31,8 @@ static int init(struct hash_desc *desc) return 0; } -static int update(struct hash_desc *desc, - struct scatterlist *sg, unsigned int nbytes) +static int update2(struct hash_desc *desc, + struct scatterlist *sg, unsigned int nbytes) { struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm); unsigned int alignmask = crypto_tfm_alg_alignmask(tfm); @@ -81,6 +83,14 @@ static int update(struct hash_desc *desc, 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) { 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, struct scatterlist *sg, unsigned int nbytes, u8 *out) { + if (WARN_ON_ONCE(in_irq())) + return -EDEADLK; + init(desc); - update(desc, sg, nbytes); + update2(desc, sg, nbytes); return final(desc, out); } diff --git a/crypto/xcbc.c b/crypto/xcbc.c index 9347eb6bcf69..317e9f08fc04 100644 --- a/crypto/xcbc.c +++ b/crypto/xcbc.c @@ -21,6 +21,7 @@ #include <linux/crypto.h> #include <linux/err.h> +#include <linux/hardirq.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/rtnetlink.h> @@ -108,9 +109,9 @@ static int crypto_xcbc_digest_init(struct hash_desc *pdesc) return 0; } -static int crypto_xcbc_digest_update(struct hash_desc *pdesc, - struct scatterlist *sg, - unsigned int nbytes) +static int crypto_xcbc_digest_update2(struct hash_desc *pdesc, + struct scatterlist *sg, + unsigned int nbytes) { struct crypto_hash *parent = pdesc->tfm; 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; } +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) { 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, struct scatterlist *sg, unsigned int nbytes, u8 *out) { + if (WARN_ON_ONCE(in_irq())) + return -EDEADLK; + 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); } |