Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+34 -33
+12 -11
crypto/algapi.c
··· 366 366 } 367 367 368 368 pr_err("alg: Unexpected test result for %s: %d\n", name, err); 369 - goto unlock; 369 + up_write(&crypto_alg_sem); 370 + return; 370 371 371 372 found: 372 373 q->cra_flags |= CRYPTO_ALG_DEAD; ··· 388 387 crypto_alg_finish_registration(alg, &list); 389 388 390 389 complete: 390 + list_del_init(&test->alg.cra_list); 391 391 complete_all(&test->completion); 392 392 393 - unlock: 394 393 up_write(&crypto_alg_sem); 395 394 395 + crypto_alg_put(&test->alg); 396 396 crypto_remove_final(&list); 397 397 } 398 398 EXPORT_SYMBOL_GPL(crypto_alg_tested); ··· 414 412 { 415 413 struct crypto_larval *larval; 416 414 LIST_HEAD(algs_to_put); 417 - bool test_started = false; 418 415 int err; 419 416 420 417 alg->cra_flags &= ~CRYPTO_ALG_DEAD; ··· 424 423 down_write(&crypto_alg_sem); 425 424 larval = __crypto_register_alg(alg, &algs_to_put); 426 425 if (!IS_ERR_OR_NULL(larval)) { 427 - test_started = crypto_boot_test_finished(); 426 + bool test_started = crypto_boot_test_finished(); 427 + 428 428 larval->test_started = test_started; 429 + if (test_started) 430 + crypto_schedule_test(larval); 429 431 } 430 432 up_write(&crypto_alg_sem); 431 433 432 434 if (IS_ERR(larval)) 433 435 return PTR_ERR(larval); 434 - if (test_started) 435 - crypto_wait_for_test(larval); 436 436 crypto_remove_final(&algs_to_put); 437 437 return 0; 438 438 } ··· 648 646 larval = __crypto_register_alg(&inst->alg, &algs_to_put); 649 647 if (IS_ERR(larval)) 650 648 goto unlock; 651 - else if (larval) 649 + else if (larval) { 652 650 larval->test_started = true; 651 + crypto_schedule_test(larval); 652 + } 653 653 654 654 hlist_add_head(&inst->list, &tmpl->instances); 655 655 inst->tmpl = tmpl; ··· 661 657 662 658 if (IS_ERR(larval)) 663 659 return PTR_ERR(larval); 664 - if (larval) 665 - crypto_wait_for_test(larval); 666 660 crypto_remove_final(&algs_to_put); 667 661 return 0; 668 662 } ··· 1044 1042 1045 1043 l->test_started = true; 1046 1044 larval = l; 1045 + crypto_schedule_test(larval); 1047 1046 break; 1048 1047 } 1049 1048 ··· 1052 1049 1053 1050 if (!larval) 1054 1051 break; 1055 - 1056 - crypto_wait_for_test(larval); 1057 1052 } 1058 1053 1059 1054 set_crypto_boot_test_finished();
+21 -20
crypto/api.c
··· 154 154 return alg; 155 155 } 156 156 157 - void crypto_larval_kill(struct crypto_alg *alg) 157 + static void crypto_larval_kill(struct crypto_larval *larval) 158 158 { 159 - struct crypto_larval *larval = (void *)alg; 159 + bool unlinked; 160 160 161 161 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); 163 165 up_write(&crypto_alg_sem); 164 - complete_all(&larval->completion); 165 - crypto_alg_put(alg); 166 - } 167 - EXPORT_SYMBOL_GPL(crypto_larval_kill); 168 166 169 - void crypto_wait_for_test(struct crypto_larval *larval) 167 + if (unlinked) 168 + return; 169 + 170 + complete_all(&larval->completion); 171 + crypto_alg_put(&larval->alg); 172 + } 173 + 174 + void crypto_schedule_test(struct crypto_larval *larval) 170 175 { 171 176 int err; 172 177 173 178 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); 181 180 } 182 - EXPORT_SYMBOL_GPL(crypto_wait_for_test); 181 + EXPORT_SYMBOL_GPL(crypto_schedule_test); 183 182 184 183 static void crypto_start_test(struct crypto_larval *larval) 185 184 { ··· 197 198 larval->test_started = true; 198 199 up_write(&crypto_alg_sem); 199 200 200 - crypto_wait_for_test(larval); 201 + crypto_schedule_test(larval); 201 202 } 202 203 203 204 static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) ··· 217 218 alg = larval->adult; 218 219 if (time_left < 0) 219 220 alg = ERR_PTR(-EINTR); 220 - else if (!time_left) 221 + else if (!time_left) { 222 + if (crypto_is_test_larval(larval)) 223 + crypto_larval_kill(larval); 221 224 alg = ERR_PTR(-ETIMEDOUT); 222 - else if (!alg) { 225 + } else if (!alg) { 223 226 u32 type; 224 227 u32 mask; 225 228 ··· 356 355 crypto_mod_put(larval); 357 356 alg = ERR_PTR(-ENOENT); 358 357 } 359 - crypto_larval_kill(larval); 358 + crypto_larval_kill(container_of(larval, struct crypto_larval, alg)); 360 359 return alg; 361 360 } 362 361 EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup);
+1 -2
crypto/internal.h
··· 113 113 struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask); 114 114 115 115 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); 118 117 void crypto_alg_tested(const char *name, int err); 119 118 120 119 void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,