From: Eric Biggers <ebiggers@kernel.org>
To: Herbert Xu <herbert@gondor.apana.org.au>
Cc: linux-crypto@vger.kernel.org, pvanleeuwen@verimatrix.com
Subject: Re: [v4 PATCH] crypto: api - fix unexpectedly getting generic implementation
Date: Tue, 10 Dec 2019 18:26:13 -0800 [thread overview]
Message-ID: <20191211022613.GA732@sol.localdomain> (raw)
In-Reply-To: <20191205045545.qernhqet4dx3b47b@gondor.apana.org.au>
On Thu, Dec 05, 2019 at 12:55:45PM +0800, Herbert Xu wrote:
> On Wed, Dec 04, 2019 at 07:43:01PM -0800, Eric Biggers wrote:
> >
> > No, the problem I'm talking about is different and is new to your patch. If
> > tmpl(X-accelerated) is registered while someone is doing crypto_alg_mod_lookup()
> > that triggered instantiation of tmpl(X-generic), then crypto_alg_mod_lookup()
> > could fail with ENOENT, instead of returning tmpl(X-generic) as it does
> > currently. This is because the proposed new logic will not fulfill the request
> > larval if a better implementation of tmpl(X) is still being tested. But there's
> > no guarantee that tmpl(X) will finish being tested by the time cryptomgr_probe()
> > thinks it is done and complete()s the request larval with 'adult' still NULL.
> >
> > (I think; I haven't actually tested this, this analysis is just based on my
> > reading of the code...)
>
> Right. This is indeed a regression. How about this patch then?
> We can simply punt and retry the lookup if we encounter a better
> larval.
>
> ---8<---
> When CONFIG_CRYPTO_MANAGER_EXTRA_TESTS=y, the first lookup of an
> algorithm that needs to be instantiated using a template will always get
> the generic implementation, even when an accelerated one is available.
>
> This happens because the extra self-tests for the accelerated
> implementation allocate the generic implementation for comparison
> purposes, and then crypto_alg_tested() for the generic implementation
> "fulfills" the original request (i.e. sets crypto_larval::adult).
>
> This patch fixes this by only fulfilling the original request if
> we are currently the best outstanding larval as judged by the
> priority. If we're not the best then we will ask all waiters on
> that larval request to retry the lookup.
>
> Note that this patch introduces a behaviour change when the module
> providing the new algorithm is unregistered during the process.
> Previously we would have failed with ENOENT, after the patch we
> will instead redo the lookup.
>
> Fixes: 9a8a6b3f0950 ("crypto: testmgr - fuzz hashes against...")
> Fixes: d435e10e67be ("crypto: testmgr - fuzz skciphers against...")
> Fixes: 40153b10d91c ("crypto: testmgr - fuzz AEADs against...")
> Reported-by: Eric Biggers <ebiggers@google.com>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
>
> diff --git a/crypto/algapi.c b/crypto/algapi.c
> index b052f38edba6..c7527ac614af 100644
> --- a/crypto/algapi.c
> +++ b/crypto/algapi.c
> @@ -257,6 +257,7 @@ void crypto_alg_tested(const char *name, int err)
> struct crypto_alg *alg;
> struct crypto_alg *q;
> LIST_HEAD(list);
> + bool best;
>
> down_write(&crypto_alg_sem);
> list_for_each_entry(q, &crypto_alg_list, cra_list) {
> @@ -280,6 +281,21 @@ void crypto_alg_tested(const char *name, int err)
>
> alg->cra_flags |= CRYPTO_ALG_TESTED;
>
> + /* Only satisfy larval waiters if we are the best. */
> + best = true;
> + list_for_each_entry(q, &crypto_alg_list, cra_list) {
> + if (crypto_is_moribund(q) || !crypto_is_larval(q))
> + continue;
> +
> + if (strcmp(alg->cra_name, q->cra_name))
> + continue;
> +
> + if (q->cra_priority > alg->cra_priority) {
> + best = false;
> + break;
> + }
> + }
> +
> list_for_each_entry(q, &crypto_alg_list, cra_list) {
> if (q == alg)
> continue;
> @@ -289,6 +305,7 @@ void crypto_alg_tested(const char *name, int err)
>
> if (crypto_is_larval(q)) {
> struct crypto_larval *larval = (void *)q;
> + struct crypto_alg *r;
>
> /*
> * Check to see if either our generic name or
> @@ -303,8 +320,10 @@ void crypto_alg_tested(const char *name, int err)
> continue;
> if ((q->cra_flags ^ alg->cra_flags) & larval->mask)
> continue;
> - if (!crypto_mod_get(alg))
> - continue;
> +
> + r = ERR_PTR(-EAGAIN);
> + if (best && crypto_mod_get(alg))
> + r = alg;
>
> larval->adult = alg;
> continue;
> diff --git a/crypto/api.c b/crypto/api.c
> index 55bca28df92d..b5ad4cc1198a 100644
> --- a/crypto/api.c
> +++ b/crypto/api.c
> @@ -97,7 +97,7 @@ static void crypto_larval_destroy(struct crypto_alg *alg)
> struct crypto_larval *larval = (void *)alg;
>
> BUG_ON(!crypto_is_larval(alg));
> - if (larval->adult)
> + if (!IS_ERR_OR_NULL(larval->adult))
> crypto_mod_put(larval->adult);
> kfree(larval);
> }
> @@ -178,6 +178,8 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
> alg = ERR_PTR(-ETIMEDOUT);
> else if (!alg)
> alg = ERR_PTR(-ENOENT);
> + else if (IS_ERR(alg))
> + ;
> else if (crypto_is_test_larval(larval) &&
> !(alg->cra_flags & CRYPTO_ALG_TESTED))
> alg = ERR_PTR(-EAGAIN);
Sorry, I didn't notice you had already sent another patch for this. I think
this patch is okay, except that it's broken because it doesn't actually do
anything with the 'r' variable in crypto_alg_tested(). I suggest just removing
that variable and doing:
if (best && crypto_mod_get(alg))
larval->adult = alg;
else
larval->adult = ERR_PTR(-EAGAIN);
Also, it would be nice to also add a function comment for crypto_alg_tested(),
like I had in my original patch. It's hard to understand this code.
- Eric
next prev parent reply other threads:[~2019-12-11 2:26 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-02 22:13 [PATCH] crypto: api - fix unexpectedly getting generic implementation Eric Biggers
2019-12-03 11:44 ` Ard Biesheuvel
2019-12-04 9:19 ` [v2 PATCH] " Herbert Xu
2019-12-04 17:22 ` Eric Biggers
2019-12-05 1:58 ` [v3 " Herbert Xu
2019-12-05 3:43 ` Eric Biggers
2019-12-05 4:55 ` [v4 " Herbert Xu
2019-12-11 2:26 ` Eric Biggers [this message]
2019-12-11 2:50 ` [v5 " Herbert Xu
2019-12-11 3:15 ` Eric Biggers
2019-12-05 4:04 ` [v3 " Eric Biggers
2019-12-05 4:23 ` Herbert Xu
2019-12-05 4:27 ` Herbert Xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191211022613.GA732@sol.localdomain \
--to=ebiggers@kernel.org \
--cc=herbert@gondor.apana.org.au \
--cc=linux-crypto@vger.kernel.org \
--cc=pvanleeuwen@verimatrix.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox