summaryrefslogtreecommitdiffstats
path: root/crypto/digest.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-12-10 10:45:28 +1100
committerHerbert Xu <herbert@gondor.apana.org.au>2007-02-07 09:20:58 +1100
commitfb469840b8c34b2f95b40a64b271f245cc1075b7 (patch)
tree8013f8beb39c83b80be0e40195005b0482cea69b /crypto/digest.c
parent62d0cfcb27cf755cebdc93ca95dabc83608007cd (diff)
downloadlinux-fb469840b8c34b2f95b40a64b271f245cc1075b7.tar.gz
linux-fb469840b8c34b2f95b40a64b271f245cc1075b7.tar.bz2
linux-fb469840b8c34b2f95b40a64b271f245cc1075b7.zip
[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>
Diffstat (limited to 'crypto/digest.c')
-rw-r--r--crypto/digest.c19
1 files changed, 16 insertions, 3 deletions
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);
}