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

Reply via email to