Skip to content

Commit

Permalink
[CRYPTO] all: Check for usage in hard IRQ context
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
herbertx committed Feb 6, 2007
1 parent 62d0cfc commit fb46984
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 7 deletions.
4 changes: 4 additions & 0 deletions crypto/blkcipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand Down
19 changes: 16 additions & 3 deletions crypto/digest.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down
21 changes: 17 additions & 4 deletions crypto/xcbc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down

0 comments on commit fb46984

Please sign in to comment.