summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2009-02-26 14:06:31 +0800
committerHerbert Xu <herbert@gondor.apana.org.au>2009-02-26 14:06:31 +0800
commit89dd1d477cb68a6fb936b97560e1f85191b50d39 (patch)
treeb3117a0cb33e649278d9bf552bf33a40e273f0f0
parent5d4ead5666179d2464e8f7d9a88eefdcb3179683 (diff)
downloadlinux-crypto-89dd1d477cb68a6fb936b97560e1f85191b50d39.tar.gz
linux-crypto-89dd1d477cb68a6fb936b97560e1f85191b50d39.zip
crypto: api - Fix module load deadlock with fallback algorithms
With the mandatory algorithm testing at registration, we have now created a deadlock with algorithms requiring fallbacks. This can happen if the module containing the algorithm requiring fallback is loaded first, without the fallback module being loaded first. The system will then try to test the new algorithm, find that it needs to load a fallback, and then try to load that. As both algorithms share the same module alias, it can attempt to load the original algorithm again and block indefinitely. As algorithms requiring fallbacks are a special case, we can fix this by giving them a different module alias than the rest. Then it's just a matter of using the right aliases according to what algorithms we're trying to find. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/api.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/crypto/api.c b/crypto/api.c
index efe77df6..38a2bc02 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -215,8 +215,19 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
type &= mask;
- alg = try_then_request_module(crypto_alg_lookup(name, type, mask),
- name);
+ alg = crypto_alg_lookup(name, type, mask);
+ if (!alg) {
+ char tmp[CRYPTO_MAX_ALG_NAME];
+
+ request_module(name);
+
+ if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask) &&
+ snprintf(tmp, sizeof(tmp), "%s-all", name) < sizeof(tmp))
+ request_module(tmp);
+
+ alg = crypto_alg_lookup(name, type, mask);
+ }
+
if (alg)
return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg;