aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-12-09 18:45:28 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2007-02-06 17:20:58 -0500
commitfb469840b8c34b2f95b40a64b271f245cc1075b7 (patch)
tree8013f8beb39c83b80be0e40195005b0482cea69b
parent62d0cfcb27cf755cebdc93ca95dabc83608007cd (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>
-rw-r--r--crypto/blkcipher.c4
-rw-r--r--crypto/digest.c19
-rw-r--r--crypto/xcbc.c21
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 @@
16 16
17#include <linux/crypto.h> 17#include <linux/crypto.h>
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/hardirq.h>
19#include <linux/kernel.h> 20#include <linux/kernel.h>
20#include <linux/module.h> 21#include <linux/module.h>
21#include <linux/scatterlist.h> 22#include <linux/scatterlist.h>
@@ -313,6 +314,9 @@ static int blkcipher_walk_first(struct blkcipher_desc *desc,
313 struct crypto_blkcipher *tfm = desc->tfm; 314 struct crypto_blkcipher *tfm = desc->tfm;
314 unsigned int alignmask = crypto_blkcipher_alignmask(tfm); 315 unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
315 316
317 if (WARN_ON_ONCE(in_irq()))
318 return -EDEADLK;
319
316 walk->nbytes = walk->total; 320 walk->nbytes = walk->total;
317 if (unlikely(!walk->total)) 321 if (unlikely(!walk->total))
318 return 0; 322 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 @@
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
32static int update(struct hash_desc *desc, 34static 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
86static 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
84static int final(struct hash_desc *desc, u8 *out) 94static 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)
118static int digest(struct hash_desc *desc, 128static 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
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 @@
21 21
22#include <linux/crypto.h> 22#include <linux/crypto.h>
23#include <linux/err.h> 23#include <linux/err.h>
24#include <linux/hardirq.h>
24#include <linux/kernel.h> 25#include <linux/kernel.h>
25#include <linux/mm.h> 26#include <linux/mm.h>
26#include <linux/rtnetlink.h> 27#include <linux/rtnetlink.h>
@@ -108,9 +109,9 @@ static int crypto_xcbc_digest_init(struct hash_desc *pdesc)
108 return 0; 109 return 0;
109} 110}
110 111
111static int crypto_xcbc_digest_update(struct hash_desc *pdesc, 112static int crypto_xcbc_digest_update2(struct hash_desc *pdesc,
112 struct scatterlist *sg, 113 struct scatterlist *sg,
113 unsigned int nbytes) 114 unsigned int nbytes)
114{ 115{
115 struct crypto_hash *parent = pdesc->tfm; 116 struct crypto_hash *parent = pdesc->tfm;
116 struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent); 117 struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
@@ -183,6 +184,15 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
183 return 0; 184 return 0;
184} 185}
185 186
187static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
188 struct scatterlist *sg,
189 unsigned int nbytes)
190{
191 if (WARN_ON_ONCE(in_irq()))
192 return -EDEADLK;
193 return crypto_xcbc_digest_update2(pdesc, sg, nbytes);
194}
195
186static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out) 196static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
187{ 197{
188 struct crypto_hash *parent = pdesc->tfm; 198 struct crypto_hash *parent = pdesc->tfm;
@@ -234,8 +244,11 @@ static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
234static int crypto_xcbc_digest(struct hash_desc *pdesc, 244static int crypto_xcbc_digest(struct hash_desc *pdesc,
235 struct scatterlist *sg, unsigned int nbytes, u8 *out) 245 struct scatterlist *sg, unsigned int nbytes, u8 *out)
236{ 246{
247 if (WARN_ON_ONCE(in_irq()))
248 return -EDEADLK;
249
237 crypto_xcbc_digest_init(pdesc); 250 crypto_xcbc_digest_init(pdesc);
238 crypto_xcbc_digest_update(pdesc, sg, nbytes); 251 crypto_xcbc_digest_update2(pdesc, sg, nbytes);
239 return crypto_xcbc_digest_final(pdesc, out); 252 return crypto_xcbc_digest_final(pdesc, out);
240} 253}
241 254