Hi Michal: On Mon, Jul 10, 2006 at 05:54:43AM +1000, herbert wrote: > > > Test 2: Now some cryptomgr complaints (should go to its own thread but > > /me is too lazy). > > > > modprobe sha1 and the above setkey. lsmod shows 1 user of sha1. flushed > > SA and modprobed padlock-sha. setkey that AH SA again - lsmod again > > shows 1 user of sha1 and no users for padlock-sha! Strange... > > > > It turns out that cryptomgr created hmac(sha1) from sha1-generic and > > doesn't update list (or create another higher-prio entry) after > > padlock-sha was inserted. > > > > Another bug? > > This is a valid complaint. I'll need to think about this.
OK, this patch should fix that problem. I'll commit it if it looks OK to you. [CRYPTO] api: Remove spawns of eclipsed algorithms When registering a new algorithm it may eclipse existing ones in the sense that if anyone looks up the new algorithm's cra_name they will (or may) get it instead of the existing algorithm. Technically, that they have the same cra_name but the new algorithm has a higher or equal priority. In this case, we should remove all spawns of the eclipsed algorithms so that the new algorithm gets a chance to be spawned in place of the existing one. This may not always happen due to type/mask restrictions. However, in that case deleting the existing spawn will simply result in the existing algorithm being spawned again which is harmless. Signed-off-by: Herbert Xu <[EMAIL PROTECTED]> Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <[EMAIL PROTECTED]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- 6850dd9d07002640bf688558dc4ed6e22b9ba0e8 diff --git a/crypto/api.c b/crypto/api.c index 6bca194..fe15f5c 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -37,6 +37,9 @@ DECLARE_RWSEM(crypto_alg_sem); static BLOCKING_NOTIFIER_HEAD(crypto_chain); +static void crypto_destroy_instance(struct crypto_alg *alg); +static void crypto_remove_final(struct list_head *list); + static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg) { atomic_inc(&alg->cra_refcnt); @@ -469,7 +472,35 @@ static int crypto_check_alg(struct crypt return crypto_set_driver_name(alg); } -static int __crypto_register_alg(struct crypto_alg *alg) +static void crypto_remove_spawns(struct list_head *spawns, + struct list_head *list) +{ + struct crypto_spawn *spawn, *n; + + list_for_each_entry_safe(spawn, n, spawns, list) { + struct crypto_instance *inst = spawn->inst; + struct crypto_template *tmpl = inst->tmpl; + + list_del_init(&spawn->list); + spawn->alg = NULL; + + if (crypto_is_dead(&inst->alg)) + continue; + + inst->alg.cra_flags |= CRYPTO_ALG_DEAD; + if (!tmpl || !crypto_tmpl_get(tmpl)) + continue; + + crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg); + list_move(&inst->alg.cra_list, list); + hlist_del(&inst->list); + list_splice(&inst->alg.cra_users, spawns->prev); + inst->alg.cra_destroy = crypto_destroy_instance; + } +} + +static int __crypto_register_alg(struct crypto_alg *alg, + struct list_head *list) { struct crypto_alg *q; int ret = -EAGAIN; @@ -484,20 +515,37 @@ static int __crypto_register_alg(struct list_for_each_entry(q, &crypto_alg_list, cra_list) { if (q == alg) goto out; - if (crypto_is_larval(q) && - (!strcmp(alg->cra_name, q->cra_name) || - !strcmp(alg->cra_driver_name, q->cra_name))) { + + if (crypto_is_moribund(q)) + continue; + + if (crypto_is_larval(q)) { struct crypto_larval *larval = (void *)q; + if (strcmp(alg->cra_name, q->cra_name) && + strcmp(alg->cra_driver_name, q->cra_name)) + continue; + if (larval->adult) continue; if ((q->cra_flags ^ alg->cra_flags) & larval->mask) continue; if (!crypto_mod_get(alg)) continue; + larval->adult = alg; complete(&larval->completion); + continue; } + + if (strcmp(alg->cra_name, q->cra_name)) + continue; + + if (strcmp(alg->cra_driver_name, q->cra_driver_name) && + q->cra_priority > alg->cra_priority) + continue; + + crypto_remove_spawns(&q->cra_users, list); } list_add(&alg->cra_list, &crypto_alg_list); @@ -511,6 +559,7 @@ out: int crypto_register_alg(struct crypto_alg *alg) { + LIST_HEAD(list); int err; err = crypto_check_alg(alg); @@ -518,9 +567,10 @@ int crypto_register_alg(struct crypto_al return err; down_write(&crypto_alg_sem); - err = __crypto_register_alg(alg); + err = __crypto_register_alg(alg, &list); up_write(&crypto_alg_sem); + crypto_remove_final(&list); return err; } @@ -535,9 +585,6 @@ static void crypto_destroy_instance(stru static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list) { - struct crypto_spawn *spawn, *n; - LIST_HEAD(spawns); - if (unlikely(list_empty(&alg->cra_list))) return -ENOENT; @@ -545,28 +592,7 @@ static int crypto_remove_alg(struct cryp crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg); list_del_init(&alg->cra_list); - list_splice(&alg->cra_users, &spawns); - - list_for_each_entry_safe(spawn, n, &spawns, list) { - struct crypto_instance *inst = spawn->inst; - struct crypto_template *tmpl = inst->tmpl; - - list_del_init(&spawn->list); - spawn->alg = NULL; - - if (crypto_is_dead(&inst->alg)) - continue; - - inst->alg.cra_flags |= CRYPTO_ALG_DEAD; - if (!tmpl || !crypto_tmpl_get(tmpl)) - continue; - - crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg); - list_move(&inst->alg.cra_list, list); - hlist_del(&inst->list); - list_splice(&inst->alg.cra_users, spawns.prev); - inst->alg.cra_destroy = crypto_destroy_instance; - } + crypto_remove_spawns(&alg->cra_users, list); return 0; } @@ -681,6 +707,7 @@ EXPORT_SYMBOL_GPL(crypto_lookup_template int crypto_register_instance(struct crypto_template *tmpl, struct crypto_instance *inst) { + LIST_HEAD(list); int err = -EINVAL; if (inst->alg.cra_destroy) @@ -694,7 +721,7 @@ int crypto_register_instance(struct cryp down_write(&crypto_alg_sem); - err = __crypto_register_alg(&inst->alg); + err = __crypto_register_alg(&inst->alg, &list); if (err) goto unlock; @@ -704,6 +731,8 @@ int crypto_register_instance(struct cryp unlock: up_write(&crypto_alg_sem); + crypto_remove_final(&list); + err: return err; } - To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html