Skip to content

Commit 37da5d0

Browse files
committed
crypto: api - Do not wait for tests during registration
As registration is usually carried out during module init, this is a context where as little work as possible should be carried out. Testing may trigger module loads of underlying components, which could even lead back to the module that is registering at the moment. This may lead to dead-locks outside of the Crypto API. Avoid this by not waiting for the tests to complete. They will be scheduled but completion will be asynchronous. Any users will still wait for completion. Reported-by: Russell King <linux@armlinux.org.uk> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent 96ad595 commit 37da5d0

File tree

3 files changed

+32
-31
lines changed

3 files changed

+32
-31
lines changed

crypto/algapi.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ void crypto_alg_tested(const char *name, int err)
366366
}
367367

368368
pr_err("alg: Unexpected test result for %s: %d\n", name, err);
369-
goto unlock;
369+
up_write(&crypto_alg_sem);
370+
return;
370371

371372
found:
372373
q->cra_flags |= CRYPTO_ALG_DEAD;
@@ -387,11 +388,12 @@ void crypto_alg_tested(const char *name, int err)
387388
crypto_alg_finish_registration(alg, &list);
388389

389390
complete:
391+
list_del_init(&test->alg.cra_list);
390392
complete_all(&test->completion);
391393

392-
unlock:
393394
up_write(&crypto_alg_sem);
394395

396+
crypto_alg_put(&test->alg);
395397
crypto_remove_final(&list);
396398
}
397399
EXPORT_SYMBOL_GPL(crypto_alg_tested);
@@ -412,7 +414,6 @@ int crypto_register_alg(struct crypto_alg *alg)
412414
{
413415
struct crypto_larval *larval;
414416
LIST_HEAD(algs_to_put);
415-
bool test_started = false;
416417
int err;
417418

418419
alg->cra_flags &= ~CRYPTO_ALG_DEAD;
@@ -423,15 +424,16 @@ int crypto_register_alg(struct crypto_alg *alg)
423424
down_write(&crypto_alg_sem);
424425
larval = __crypto_register_alg(alg, &algs_to_put);
425426
if (!IS_ERR_OR_NULL(larval)) {
426-
test_started = crypto_boot_test_finished();
427+
bool test_started = crypto_boot_test_finished();
428+
427429
larval->test_started = test_started;
430+
if (test_started)
431+
crypto_schedule_test(larval);
428432
}
429433
up_write(&crypto_alg_sem);
430434

431435
if (IS_ERR(larval))
432436
return PTR_ERR(larval);
433-
if (test_started)
434-
crypto_wait_for_test(larval);
435437
crypto_remove_final(&algs_to_put);
436438
return 0;
437439
}
@@ -646,8 +648,10 @@ int crypto_register_instance(struct crypto_template *tmpl,
646648
larval = __crypto_register_alg(&inst->alg, &algs_to_put);
647649
if (IS_ERR(larval))
648650
goto unlock;
649-
else if (larval)
651+
else if (larval) {
650652
larval->test_started = true;
653+
crypto_schedule_test(larval);
654+
}
651655

652656
hlist_add_head(&inst->list, &tmpl->instances);
653657
inst->tmpl = tmpl;
@@ -657,8 +661,6 @@ int crypto_register_instance(struct crypto_template *tmpl,
657661

658662
if (IS_ERR(larval))
659663
return PTR_ERR(larval);
660-
if (larval)
661-
crypto_wait_for_test(larval);
662664
crypto_remove_final(&algs_to_put);
663665
return 0;
664666
}
@@ -1042,15 +1044,14 @@ static void __init crypto_start_tests(void)
10421044

10431045
l->test_started = true;
10441046
larval = l;
1047+
crypto_schedule_test(larval);
10451048
break;
10461049
}
10471050

10481051
up_write(&crypto_alg_sem);
10491052

10501053
if (!larval)
10511054
break;
1052-
1053-
crypto_wait_for_test(larval);
10541055
}
10551056

10561057
set_crypto_boot_test_finished();

crypto/api.c

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -154,32 +154,31 @@ static struct crypto_alg *crypto_larval_add(const char *name, u32 type,
154154
return alg;
155155
}
156156

157-
void crypto_larval_kill(struct crypto_alg *alg)
157+
static void crypto_larval_kill(struct crypto_larval *larval)
158158
{
159-
struct crypto_larval *larval = (void *)alg;
159+
bool unlinked;
160160

161161
down_write(&crypto_alg_sem);
162-
list_del(&alg->cra_list);
162+
unlinked = list_empty(&larval->alg.cra_list);
163+
if (!unlinked)
164+
list_del_init(&larval->alg.cra_list);
163165
up_write(&crypto_alg_sem);
166+
167+
if (unlinked)
168+
return;
169+
164170
complete_all(&larval->completion);
165-
crypto_alg_put(alg);
171+
crypto_alg_put(&larval->alg);
166172
}
167-
EXPORT_SYMBOL_GPL(crypto_larval_kill);
168173

169-
void crypto_wait_for_test(struct crypto_larval *larval)
174+
void crypto_schedule_test(struct crypto_larval *larval)
170175
{
171176
int err;
172177

173178
err = crypto_probing_notify(CRYPTO_MSG_ALG_REGISTER, larval->adult);
174-
if (WARN_ON_ONCE(err != NOTIFY_STOP))
175-
goto out;
176-
177-
err = wait_for_completion_killable(&larval->completion);
178-
WARN_ON(err);
179-
out:
180-
crypto_larval_kill(&larval->alg);
179+
WARN_ON_ONCE(err != NOTIFY_STOP);
181180
}
182-
EXPORT_SYMBOL_GPL(crypto_wait_for_test);
181+
EXPORT_SYMBOL_GPL(crypto_schedule_test);
183182

184183
static void crypto_start_test(struct crypto_larval *larval)
185184
{
@@ -198,7 +197,7 @@ static void crypto_start_test(struct crypto_larval *larval)
198197
larval->test_started = true;
199198
up_write(&crypto_alg_sem);
200199

201-
crypto_wait_for_test(larval);
200+
crypto_schedule_test(larval);
202201
}
203202

204203
static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
@@ -218,9 +217,11 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
218217
alg = larval->adult;
219218
if (time_left < 0)
220219
alg = ERR_PTR(-EINTR);
221-
else if (!time_left)
220+
else if (!time_left) {
221+
if (crypto_is_test_larval(larval))
222+
crypto_larval_kill(larval);
222223
alg = ERR_PTR(-ETIMEDOUT);
223-
else if (!alg) {
224+
} else if (!alg) {
224225
u32 type;
225226
u32 mask;
226227

@@ -355,7 +356,7 @@ struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
355356
crypto_mod_put(larval);
356357
alg = ERR_PTR(-ENOENT);
357358
}
358-
crypto_larval_kill(larval);
359+
crypto_larval_kill(container_of(larval, struct crypto_larval, alg));
359360
return alg;
360361
}
361362
EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup);

crypto/internal.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,7 @@ struct crypto_alg *crypto_mod_get(struct crypto_alg *alg);
113113
struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask);
114114

115115
struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask);
116-
void crypto_larval_kill(struct crypto_alg *alg);
117-
void crypto_wait_for_test(struct crypto_larval *larval);
116+
void crypto_schedule_test(struct crypto_larval *larval);
118117
void crypto_alg_tested(const char *name, int err);
119118

120119
void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,

0 commit comments

Comments
 (0)