diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2006-12-09 18:45:28 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2007-02-06 17:20:58 -0500 |
commit | fb469840b8c34b2f95b40a64b271f245cc1075b7 (patch) | |
tree | 8013f8beb39c83b80be0e40195005b0482cea69b /crypto/digest.c | |
parent | 62d0cfcb27cf755cebdc93ca95dabc83608007cd (diff) |
[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.c | 19 |
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 @@ | |||
14 | 14 | ||
15 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/hardirq.h> | ||
17 | #include <linux/highmem.h> | 18 | #include <linux/highmem.h> |
19 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | 20 | #include <linux/module.h> |
19 | #include <linux/scatterlist.h> | 21 | #include <linux/scatterlist.h> |
20 | 22 | ||
@@ -29,8 +31,8 @@ static int init(struct hash_desc *desc) | |||
29 | return 0; | 31 | return 0; |
30 | } | 32 | } |
31 | 33 | ||
32 | static int update(struct hash_desc *desc, | 34 | static int update2(struct hash_desc *desc, |
33 | struct scatterlist *sg, unsigned int nbytes) | 35 | struct scatterlist *sg, unsigned int nbytes) |
34 | { | 36 | { |
35 | struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm); | 37 | struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm); |
36 | unsigned int alignmask = crypto_tfm_alg_alignmask(tfm); | 38 | unsigned int alignmask = crypto_tfm_alg_alignmask(tfm); |
@@ -81,6 +83,14 @@ static int update(struct hash_desc *desc, | |||
81 | return 0; | 83 | return 0; |
82 | } | 84 | } |
83 | 85 | ||
86 | static int update(struct hash_desc *desc, | ||
87 | struct scatterlist *sg, unsigned int nbytes) | ||
88 | { | ||
89 | if (WARN_ON_ONCE(in_irq())) | ||
90 | return -EDEADLK; | ||
91 | return update2(desc, sg, nbytes); | ||
92 | } | ||
93 | |||
84 | static int final(struct hash_desc *desc, u8 *out) | 94 | static int final(struct hash_desc *desc, u8 *out) |
85 | { | 95 | { |
86 | struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm); | 96 | 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) | |||
118 | static int digest(struct hash_desc *desc, | 128 | static int digest(struct hash_desc *desc, |
119 | struct scatterlist *sg, unsigned int nbytes, u8 *out) | 129 | struct scatterlist *sg, unsigned int nbytes, u8 *out) |
120 | { | 130 | { |
131 | if (WARN_ON_ONCE(in_irq())) | ||
132 | return -EDEADLK; | ||
133 | |||
121 | init(desc); | 134 | init(desc); |
122 | update(desc, sg, nbytes); | 135 | update2(desc, sg, nbytes); |
123 | return final(desc, out); | 136 | return final(desc, out); |
124 | } | 137 | } |
125 | 138 | ||