From: Jarod Wilson <jarod@redhat.com> Date: Thu, 23 Apr 2009 14:37:47 -0400 Subject: [crypto] fix rfc4309 deadlocks Message-id: 49F0B57B.90606@redhat.com O-Subject: [RHEL5.4 PATCH 1/3 v2] crypto: fix rfc4309 deadlocks Bugzilla: 472386 RH-Acked-by: Neil Horman <nhorman@redhat.com> Bugzilla #472386: fips crypto: self-test needed for rfc4309(ccm(aes)) https://bugzilla.redhat.com/show_bug.cgi?id=472386 Part 1 of 3 Backport fixes from cryptodev-2.6 tree to remedy rfc4309(ccm(aes)) deadlocks. Roll-up of: crypto: api - Fix algorithm test race that broke aead initialisation: http://git.kernel.org/?p=linux/kernel/git/herbert/cryptodev-2.6.git;a=commitdiff;h=b8e15992b420d09dae831125a623c474c8637cee crypto: api - crypto_alg_mod_lookup either tested or untested: http://git.kernel.org/?p=linux/kernel/git/herbert/cryptodev-2.6.git;a=commitdiff;h=ff753308d2f70f210ba468492cd9a01274d9d7ce crypto: testmgr - Test skciphers with no IVs: http://git.kernel.org/?p=linux/kernel/git/herbert/cryptodev-2.6.git;a=commitdiff;h=6fe4a28d8855e072036f36ee22f0a8f43f44918f diff --git a/crypto/algapi.c b/crypto/algapi.c index 23b5bc8..82e86c7 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -151,6 +151,9 @@ static struct crypto_larval *__crypto_register_alg(struct ncrypto_alg *alg) if (q == alg) goto err; + if (crypto_is_moribund(q)) + continue; + if (crypto_is_larval(q)) { if (!strcmp(alg->cra_driver_name, q->cra_driver_name)) goto err; @@ -199,7 +202,7 @@ void crypto_alg_tested(const char *name, int err) down_write(&ncrypto_alg_sem); list_for_each_entry(q, &ncrypto_alg_list, cra_list) { - if (!crypto_is_larval(q)) + if (crypto_is_moribund(q) || !crypto_is_larval(q)) continue; test = (struct crypto_larval *)q; @@ -212,6 +215,7 @@ void crypto_alg_tested(const char *name, int err) goto unlock; found: + q->cra_flags |= NCRYPTO_ALG_DEAD; alg = test->adult; if (err || list_empty(&alg->cra_list)) goto complete; diff --git a/crypto/crypto_api.c b/crypto/crypto_api.c index 1f9a034..c789ea3 100644 --- a/crypto/crypto_api.c +++ b/crypto/crypto_api.c @@ -247,7 +247,7 @@ struct ncrypto_alg *ncrypto_alg_mod_lookup(const char *name, u32 type, u32 mask) struct ncrypto_alg *larval; int ok; - if (!(mask & NCRYPTO_ALG_TESTED)) { + if (!((type | mask) & NCRYPTO_ALG_TESTED)) { type |= NCRYPTO_ALG_TESTED; mask |= NCRYPTO_ALG_TESTED; } diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 2393aaf..bf3afa3 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -24,6 +24,7 @@ #include <linux/scatterlist.h> #include <linux/slab.h> #include <linux/string.h> +#include <crypto/internal/aead.h> #include "ninternal.h" #include "testmgr.h" @@ -1357,8 +1358,7 @@ static int cryptomgr_test(void *data) u32 type = param->type; int err = 0; - if (!((type ^ NCRYPTO_ALG_TYPE_BLKCIPHER) & - NCRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & NCRYPTO_ALG_GENIV)) + if (type & NCRYPTO_ALG_TESTED) goto skiptest; err = alg_test(param->driver, param->alg, type, NCRYPTO_ALG_TESTED); @@ -1374,6 +1374,7 @@ static int cryptomgr_schedule_test(struct ncrypto_alg *alg) { struct task_struct *thread; struct crypto_test_param *param; + u32 type; if (!try_module_get(THIS_MODULE)) goto err; @@ -1384,7 +1385,20 @@ static int cryptomgr_schedule_test(struct ncrypto_alg *alg) memcpy(param->driver, alg->cra_driver_name, sizeof(param->driver)); memcpy(param->alg, alg->cra_name, sizeof(param->alg)); - param->type = alg->cra_flags; + type = alg->cra_flags; + + /* This piece of crap needs to disappear into per-type test hooks. */ + if ((!((type ^ NCRYPTO_ALG_TYPE_BLKCIPHER) & + NCRYPTO_ALG_TYPE_BLKCIPHER_MASK) && + !(type & NCRYPTO_ALG_GENIV) && + ((alg->cra_flags & NCRYPTO_ALG_TYPE_MASK) == + NCRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize : + alg->cra_ablkcipher.ivsize)) || + (!((type ^ NCRYPTO_ALG_TYPE_AEAD) & NCRYPTO_ALG_TYPE_MASK) && + alg->cra_type == &crypto_nivaead_type && alg->cra_aead.ivsize)) + type |= NCRYPTO_ALG_TESTED; + + param->type = type; thread = kthread_run(cryptomgr_test, param, "cryptomgr_test"); if (IS_ERR(thread))