* Re: [BUG] More issues with arm/aes-neonbs
2024-08-09 4:40 ` Herbert Xu
@ 2024-08-09 5:19 ` Linus Torvalds
2024-08-09 16:25 ` Linus Torvalds
2024-08-09 7:50 ` Russell King (Oracle)
` (3 subsequent siblings)
4 siblings, 1 reply; 35+ messages in thread
From: Linus Torvalds @ 2024-08-09 5:19 UTC (permalink / raw)
To: Herbert Xu
Cc: Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller, linux-crypto
On Thu, 8 Aug 2024 at 21:40, Herbert Xu <herbert@gondor.apana.org.au> wrote:
>
> The immediate cause of the recursive load is the self-test system
> (if it is not disabled through Kconfig). The algorithm registration
> does not return until after the self-test has successfully executed.
> For the algorithm in question, that involves loading a fallback
> algorithm which is what triggered the recursive module load.
Ahh. I tried to figure out why it would load the same module
recursively, and it was very unclear to me.
> We had an issue when algorithms were built into the kernel, where
> due to the random of registration calls, a self-test may invoke
> an algorithm which is built into the kernel but not yet registered.
> There it was resolved by postponing all self-tests until all
> algorithms had been registered (or when an algorithm was first used,
> which would trigger the self-test for that algorithm there and then).
We don't have any generic module "do this asynchronously after you've
been loaded", but I guess the crypto code itself could just do
something like that when a new crypto algorithm has been registered?
The keyword being that "do this _asynchronouysly_" so that it doesn't
hold up the module init itself..
> Russell, is it OK with you if we only resolve this in the mainline
> kernel or do you want a solution that can be backported as well?
I actually had what I thought was a cunning plan, and thought that I
could fix this by reorganizing the module loading and relying on the
module_mutex itself to avoid the race that happens when you release
waiters early.
But it turns out my cunning plan was just me being stupid, because we
really can't hold the module mutex over the initcall itself, and
that's the part (well, _one_ of the parts) that needs protection.
And in fact, as part of shooting down my not-so-cunning plan I
convinced myself that I don't think this recursive load actually ever
worked at all, and it would always hang on the recursive module load.
But before that commit 9828ed3f695a, that hang was in
module_patient_check_exists(), and it would be interruptible.
So any signal would then cause the nested module loading to break out
with an error, the first module load would finish happilt, and at
least it wouldn't hang forever.
End result: I now have a new plan - I'll make the
wait_for_completion(&idem.complete) be interruptible and return -EINTR
(and I'll have to clean up the wait-queues etc).
That should make all this work the effectively the same way the old
path in module_patient_check_exists() used to work (and still does,
for the non-file-load case).
That should be a distinct improvement, and at least get us back the
old historical behavior. It still doesn't make the recursive module
load _work_, but it won't be the "hung forever" disaster (and
regression) that it is now.
But considering how not-cunning my first plan was, I'll sleep on it
first. I think this plan actually works, but I'm not going to start
implementing it at 10pm.
And then the crypto layer fixing the actual recursion issue will fix
the underlying problem.
Linus
^ permalink raw reply [flat|nested] 35+ messages in thread* Re: [BUG] More issues with arm/aes-neonbs
2024-08-09 5:19 ` Linus Torvalds
@ 2024-08-09 16:25 ` Linus Torvalds
0 siblings, 0 replies; 35+ messages in thread
From: Linus Torvalds @ 2024-08-09 16:25 UTC (permalink / raw)
To: Herbert Xu
Cc: Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller, linux-crypto
On Thu, 8 Aug 2024 at 22:19, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> End result: I now have a new plan - I'll make the
> wait_for_completion(&idem.complete) be interruptible and return -EINTR
> (and I'll have to clean up the wait-queues etc).
.. and that seems to have been pretty straightforward, and creating a
test-module that just recursively does a "request_module()" of itself
shows that it all seems to work.
I've committed it and marked it as
Fixes: 9b9879fc0327 ("modules: catch concurrent module loads, treat
them as idempotent")
but it shouldn't actually matter for any non-buggy module situation.
Linus
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [BUG] More issues with arm/aes-neonbs
2024-08-09 4:40 ` Herbert Xu
2024-08-09 5:19 ` Linus Torvalds
@ 2024-08-09 7:50 ` Russell King (Oracle)
2024-08-10 2:41 ` [PATCH 1/3] crypto: api - Remove instance larval fulfilment Herbert Xu
` (2 subsequent siblings)
4 siblings, 0 replies; 35+ messages in thread
From: Russell King (Oracle) @ 2024-08-09 7:50 UTC (permalink / raw)
To: Herbert Xu
Cc: Linus Torvalds, Horia Geantă, Ard Biesheuvel,
David S. Miller, linux-crypto
On Fri, Aug 09, 2024 at 12:40:39PM +0800, Herbert Xu wrote:
> On Thu, Aug 08, 2024 at 12:54:10PM -0700, Linus Torvalds wrote:
> >
> > I don't know the crypto registration API enough to even guess at what
> > the fix to break the recursion is.
> >
> > Herbert?
>
> Yes my plan is to fix this in the Crypto API and not do any recursive
> loads as we used to do.
>
> The immediate cause of the recursive load is the self-test system
> (if it is not disabled through Kconfig). The algorithm registration
> does not return until after the self-test has successfully executed.
> For the algorithm in question, that involves loading a fallback
> algorithm which is what triggered the recursive module load.
>
> We had an issue when algorithms were built into the kernel, where
> due to the random of registration calls, a self-test may invoke
> an algorithm which is built into the kernel but not yet registered.
> There it was resolved by postponing all self-tests until all
> algorithms had been registered (or when an algorithm was first used,
> which would trigger the self-test for that algorithm there and then).
>
> I will extend this to modules and let the registration return
> as soon as the new algorithm can be looked up. The self-test
> can then complete asynchronously.
>
> Russell, is it OK with you if we only resolve this in the mainline
> kernel or do you want a solution that can be backported as well?
That's fine - I've blacklisted the arm-aes-bs module in modprobe.conf
on the affected machines. Thanks!
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply [flat|nested] 35+ messages in thread* [PATCH 1/3] crypto: api - Remove instance larval fulfilment
2024-08-09 4:40 ` Herbert Xu
2024-08-09 5:19 ` Linus Torvalds
2024-08-09 7:50 ` Russell King (Oracle)
@ 2024-08-10 2:41 ` Herbert Xu
2024-08-16 8:45 ` kernel test robot
2024-08-10 2:42 ` [PATCH 2/3] crypto: api - Do not wait for tests during registration Herbert Xu
2024-08-10 2:43 ` [PATCH " Herbert Xu
4 siblings, 1 reply; 35+ messages in thread
From: Herbert Xu @ 2024-08-10 2:41 UTC (permalink / raw)
To: Linus Torvalds
Cc: Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller, linux-crypto
In order to allow testing to complete asynchronously after the
registration process, instance larvals need to complete prior
to having a test result. Support this by redoing the lookup for
instance larvals after completion. This should locate the pending
test larval and then repeat the wait on that (if it is still pending).
As the lookup is now repeated there is no longer any need to compute
the fulfilment status and all that code can be removed.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/algapi.c | 48 +++---------------------------------------------
crypto/api.c | 23 +++++++++++++++++++----
2 files changed, 22 insertions(+), 49 deletions(-)
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 122cd910c4e1..d2ccc1289f92 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -235,7 +235,6 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
EXPORT_SYMBOL_GPL(crypto_remove_spawns);
static void crypto_alg_finish_registration(struct crypto_alg *alg,
- bool fulfill_requests,
struct list_head *algs_to_put)
{
struct crypto_alg *q;
@@ -247,30 +246,8 @@ static void crypto_alg_finish_registration(struct crypto_alg *alg,
if (crypto_is_moribund(q))
continue;
- if (crypto_is_larval(q)) {
- struct crypto_larval *larval = (void *)q;
-
- /*
- * Check to see if either our generic name or
- * specific name can satisfy the name requested
- * by the larval entry 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 (fulfill_requests && crypto_mod_get(alg))
- larval->adult = alg;
- else
- larval->adult = ERR_PTR(-EAGAIN);
-
+ if (crypto_is_larval(q))
continue;
- }
if (strcmp(alg->cra_name, q->cra_name))
continue;
@@ -359,7 +336,7 @@ __crypto_register_alg(struct crypto_alg *alg, struct list_head *algs_to_put)
list_add(&larval->alg.cra_list, &crypto_alg_list);
} else {
alg->cra_flags |= CRYPTO_ALG_TESTED;
- crypto_alg_finish_registration(alg, true, algs_to_put);
+ crypto_alg_finish_registration(alg, algs_to_put);
}
out:
@@ -376,7 +353,6 @@ 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) {
@@ -408,25 +384,7 @@ void crypto_alg_tested(const char *name, int err)
alg->cra_flags |= CRYPTO_ALG_TESTED;
- /*
- * If a higher-priority implementation of the same algorithm is
- * currently being tested, then don't fulfill request larvals.
- */
- 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;
- }
- }
-
- crypto_alg_finish_registration(alg, best, &list);
+ crypto_alg_finish_registration(alg, &list);
complete:
complete_all(&test->completion);
diff --git a/crypto/api.c b/crypto/api.c
index 22556907b3bc..ffb81aa32725 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -37,6 +37,8 @@ DEFINE_STATIC_KEY_FALSE(__crypto_boot_test_finished);
#endif
static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg);
+static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type,
+ u32 mask);
struct crypto_alg *crypto_mod_get(struct crypto_alg *alg)
{
@@ -201,9 +203,12 @@ static void crypto_start_test(struct crypto_larval *larval)
static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
{
- struct crypto_larval *larval = (void *)alg;
+ struct crypto_larval *larval;
long time_left;
+again:
+ larval = container_of(alg, struct crypto_larval, alg);
+
if (!crypto_boot_test_finished())
crypto_start_test(larval);
@@ -215,9 +220,16 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
alg = ERR_PTR(-EINTR);
else if (!time_left)
alg = ERR_PTR(-ETIMEDOUT);
- else if (!alg)
- alg = ERR_PTR(-ENOENT);
- else if (IS_ERR(alg))
+ else if (!alg) {
+ u32 type;
+ u32 mask;
+
+ alg = &larval->alg;
+ type = alg->cra_flags & ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
+ mask = larval->mask;
+ alg = crypto_alg_lookup(alg->cra_name, type, mask) ?:
+ ERR_PTR(-ENOENT);
+ } else if (IS_ERR(alg))
;
else if (crypto_is_test_larval(larval) &&
!(alg->cra_flags & CRYPTO_ALG_TESTED))
@@ -228,6 +240,9 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
alg = ERR_PTR(-EAGAIN);
crypto_mod_put(&larval->alg);
+ if (!IS_ERR(alg) && crypto_is_larval(alg))
+ goto again;
+
return alg;
}
--
2.39.2
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related [flat|nested] 35+ messages in thread* Re: [PATCH 1/3] crypto: api - Remove instance larval fulfilment
2024-08-10 2:41 ` [PATCH 1/3] crypto: api - Remove instance larval fulfilment Herbert Xu
@ 2024-08-16 8:45 ` kernel test robot
2024-08-17 6:56 ` [v3 PATCH " Herbert Xu
0 siblings, 1 reply; 35+ messages in thread
From: kernel test robot @ 2024-08-16 8:45 UTC (permalink / raw)
To: Herbert Xu
Cc: oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller, oliver.sang
Hello,
kernel test robot noticed "ltp.af_alg03.fail" on:
commit: 103961609b0935ee6ad40b0a9fea2924b1c62c18 ("[PATCH 1/3] crypto: api - Remove instance larval fulfilment")
url: https://github.com/intel-lab-lkp/linux/commits/Herbert-Xu/crypto-api-Do-not-wait-for-tests-during-registration/20240810-160343
base: https://git.kernel.org/cgit/linux/kernel/git/herbert/cryptodev-2.6.git master
patch link: https://lore.kernel.org/all/ZrbTUk6DyktnO7qk@gondor.apana.org.au/
patch subject: [PATCH 1/3] crypto: api - Remove instance larval fulfilment
in testcase: ltp
version: ltp-x86_64-14c1f76-1_20240810
with following parameters:
test: crypto/af_alg03
compiler: gcc-12
test machine: 8 threads 1 sockets Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz (Ivy Bridge) with 16G memory
(please refer to attached dmesg/kmsg for entire log/backtrace)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <oliver.sang@intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202408161634.598311fd-oliver.sang@intel.com
Running tests.......
<<<test_start>>>
tag=af_alg03 stime=1723519123
cmdline="af_alg03"
contacts=""
analysis=exit
<<<test_output>>>
tst_test.c:1807: TINFO: LTP version: 20240524-172-gcc410eaa0
tst_test.c:1651: TINFO: Timeout per run is 0h 00m 30s
Test timeouted, sending SIGKILL!
Test timeouted, sending SIGKILL!
Test timeouted, sending SIGKILL!
Test timeouted, sending SIGKILL!
Test timeouted, sending SIGKILL!
Test timeouted, sending SIGKILL!
Test timeouted, sending SIGKILL!
Test timeouted, sending SIGKILL!
Test timeouted, sending SIGKILL!
Test timeouted, sending SIGKILL!
Test timeouted, sending SIGKILL!
Cannot kill test processes!
Congratulation, likely test hit a kernel bug.
Exiting uncleanly...
incrementing stop
<<<execution_status>>>
initiation_status="ok"
duration=80 termination_type=exited termination_id=1 corefile=no
cutime=0 cstime=0
<<<test_end>>>
INFO: ltp-pan reported some tests FAIL
LTP Version: 20240524-172-gcc410eaa0
###############################################################
Done executing testcases.
LTP Version: 20240524-172-gcc410eaa0
###############################################################
The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20240816/202408161634.598311fd-oliver.sang@intel.com
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 35+ messages in thread* [v3 PATCH 1/3] crypto: api - Remove instance larval fulfilment
2024-08-16 8:45 ` kernel test robot
@ 2024-08-17 6:56 ` Herbert Xu
2024-08-17 6:57 ` [v3 PATCH 2/3] crypto: api - Do not wait for tests during registration Herbert Xu
0 siblings, 1 reply; 35+ messages in thread
From: Herbert Xu @ 2024-08-17 6:56 UTC (permalink / raw)
To: kernel test robot
Cc: oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
On Fri, Aug 16, 2024 at 04:45:59PM +0800, kernel test robot wrote:
>
> kernel test robot noticed "ltp.af_alg03.fail" on:
Thanks for the report. Indeed the first patch is buggy as the
larval isn't marked as dead upon completion which when paired with
the new re-lookup triggers a dead-lock. Fix this by adding a DEAD
marking prior to calling complete_all.
---8<---
In order to allow testing to complete asynchronously after the
registration process, instance larvals need to complete prior
to having a test result. Support this by redoing the lookup for
instance larvals after completion. This should locate the pending
test larval and then repeat the wait on that (if it is still pending).
As the lookup is now repeated there is no longer any need to compute
the fulfilment status and all that code can be removed.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/algapi.c | 48 +++---------------------------------------------
crypto/algboss.c | 1 +
crypto/api.c | 23 +++++++++++++++++++----
3 files changed, 23 insertions(+), 49 deletions(-)
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 122cd910c4e1..d2ccc1289f92 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -235,7 +235,6 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
EXPORT_SYMBOL_GPL(crypto_remove_spawns);
static void crypto_alg_finish_registration(struct crypto_alg *alg,
- bool fulfill_requests,
struct list_head *algs_to_put)
{
struct crypto_alg *q;
@@ -247,30 +246,8 @@ static void crypto_alg_finish_registration(struct crypto_alg *alg,
if (crypto_is_moribund(q))
continue;
- if (crypto_is_larval(q)) {
- struct crypto_larval *larval = (void *)q;
-
- /*
- * Check to see if either our generic name or
- * specific name can satisfy the name requested
- * by the larval entry 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 (fulfill_requests && crypto_mod_get(alg))
- larval->adult = alg;
- else
- larval->adult = ERR_PTR(-EAGAIN);
-
+ if (crypto_is_larval(q))
continue;
- }
if (strcmp(alg->cra_name, q->cra_name))
continue;
@@ -359,7 +336,7 @@ __crypto_register_alg(struct crypto_alg *alg, struct list_head *algs_to_put)
list_add(&larval->alg.cra_list, &crypto_alg_list);
} else {
alg->cra_flags |= CRYPTO_ALG_TESTED;
- crypto_alg_finish_registration(alg, true, algs_to_put);
+ crypto_alg_finish_registration(alg, algs_to_put);
}
out:
@@ -376,7 +353,6 @@ 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) {
@@ -408,25 +384,7 @@ void crypto_alg_tested(const char *name, int err)
alg->cra_flags |= CRYPTO_ALG_TESTED;
- /*
- * If a higher-priority implementation of the same algorithm is
- * currently being tested, then don't fulfill request larvals.
- */
- 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;
- }
- }
-
- crypto_alg_finish_registration(alg, best, &list);
+ crypto_alg_finish_registration(alg, &list);
complete:
complete_all(&test->completion);
diff --git a/crypto/algboss.c b/crypto/algboss.c
index 1aa5f306998a..d05a5aad2176 100644
--- a/crypto/algboss.c
+++ b/crypto/algboss.c
@@ -64,6 +64,7 @@ static int cryptomgr_probe(void *data)
crypto_tmpl_put(tmpl);
out:
+ param->larval->alg.cra_flags |= CRYPTO_ALG_DEAD;
complete_all(¶m->larval->completion);
crypto_alg_put(¶m->larval->alg);
kfree(param);
diff --git a/crypto/api.c b/crypto/api.c
index 22556907b3bc..ffb81aa32725 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -37,6 +37,8 @@ DEFINE_STATIC_KEY_FALSE(__crypto_boot_test_finished);
#endif
static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg);
+static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type,
+ u32 mask);
struct crypto_alg *crypto_mod_get(struct crypto_alg *alg)
{
@@ -201,9 +203,12 @@ static void crypto_start_test(struct crypto_larval *larval)
static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
{
- struct crypto_larval *larval = (void *)alg;
+ struct crypto_larval *larval;
long time_left;
+again:
+ larval = container_of(alg, struct crypto_larval, alg);
+
if (!crypto_boot_test_finished())
crypto_start_test(larval);
@@ -215,9 +220,16 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
alg = ERR_PTR(-EINTR);
else if (!time_left)
alg = ERR_PTR(-ETIMEDOUT);
- else if (!alg)
- alg = ERR_PTR(-ENOENT);
- else if (IS_ERR(alg))
+ else if (!alg) {
+ u32 type;
+ u32 mask;
+
+ alg = &larval->alg;
+ type = alg->cra_flags & ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
+ mask = larval->mask;
+ alg = crypto_alg_lookup(alg->cra_name, type, mask) ?:
+ ERR_PTR(-ENOENT);
+ } else if (IS_ERR(alg))
;
else if (crypto_is_test_larval(larval) &&
!(alg->cra_flags & CRYPTO_ALG_TESTED))
@@ -228,6 +240,9 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
alg = ERR_PTR(-EAGAIN);
crypto_mod_put(&larval->alg);
+ if (!IS_ERR(alg) && crypto_is_larval(alg))
+ goto again;
+
return alg;
}
--
2.39.2
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related [flat|nested] 35+ messages in thread* [v3 PATCH 2/3] crypto: api - Do not wait for tests during registration
2024-08-17 6:56 ` [v3 PATCH " Herbert Xu
@ 2024-08-17 6:57 ` Herbert Xu
2024-08-17 6:58 ` [v3 PATCH 3/3] crypto: simd - Do not call crypto_alloc_tfm " Herbert Xu
0 siblings, 1 reply; 35+ messages in thread
From: Herbert Xu @ 2024-08-17 6:57 UTC (permalink / raw)
To: kernel test robot
Cc: oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
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>
---
crypto/algapi.c | 23 ++++++++++++-----------
crypto/api.c | 41 +++++++++++++++++++++--------------------
crypto/internal.h | 3 +--
3 files changed, 34 insertions(+), 33 deletions(-)
diff --git a/crypto/algapi.c b/crypto/algapi.c
index d2ccc1289f92..74e2261c184c 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -366,7 +366,8 @@ void crypto_alg_tested(const char *name, int err)
}
pr_err("alg: Unexpected test result for %s: %d\n", name, err);
- goto unlock;
+ up_write(&crypto_alg_sem);
+ return;
found:
q->cra_flags |= CRYPTO_ALG_DEAD;
@@ -387,11 +388,12 @@ void crypto_alg_tested(const char *name, int err)
crypto_alg_finish_registration(alg, &list);
complete:
+ list_del_init(&test->alg.cra_list);
complete_all(&test->completion);
-unlock:
up_write(&crypto_alg_sem);
+ crypto_alg_put(&test->alg);
crypto_remove_final(&list);
}
EXPORT_SYMBOL_GPL(crypto_alg_tested);
@@ -412,7 +414,6 @@ int crypto_register_alg(struct crypto_alg *alg)
{
struct crypto_larval *larval;
LIST_HEAD(algs_to_put);
- bool test_started = false;
int err;
alg->cra_flags &= ~CRYPTO_ALG_DEAD;
@@ -423,15 +424,16 @@ int crypto_register_alg(struct crypto_alg *alg)
down_write(&crypto_alg_sem);
larval = __crypto_register_alg(alg, &algs_to_put);
if (!IS_ERR_OR_NULL(larval)) {
- test_started = crypto_boot_test_finished();
+ bool test_started = crypto_boot_test_finished();
+
larval->test_started = test_started;
+ if (test_started)
+ crypto_schedule_test(larval);
}
up_write(&crypto_alg_sem);
if (IS_ERR(larval))
return PTR_ERR(larval);
- if (test_started)
- crypto_wait_for_test(larval);
crypto_remove_final(&algs_to_put);
return 0;
}
@@ -646,8 +648,10 @@ int crypto_register_instance(struct crypto_template *tmpl,
larval = __crypto_register_alg(&inst->alg, &algs_to_put);
if (IS_ERR(larval))
goto unlock;
- else if (larval)
+ else if (larval) {
larval->test_started = true;
+ crypto_schedule_test(larval);
+ }
hlist_add_head(&inst->list, &tmpl->instances);
inst->tmpl = tmpl;
@@ -657,8 +661,6 @@ int crypto_register_instance(struct crypto_template *tmpl,
if (IS_ERR(larval))
return PTR_ERR(larval);
- if (larval)
- crypto_wait_for_test(larval);
crypto_remove_final(&algs_to_put);
return 0;
}
@@ -1042,6 +1044,7 @@ static void __init crypto_start_tests(void)
l->test_started = true;
larval = l;
+ crypto_schedule_test(larval);
break;
}
@@ -1049,8 +1052,6 @@ static void __init crypto_start_tests(void)
if (!larval)
break;
-
- crypto_wait_for_test(larval);
}
set_crypto_boot_test_finished();
diff --git a/crypto/api.c b/crypto/api.c
index ffb81aa32725..bbe29d438815 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -154,32 +154,31 @@ static struct crypto_alg *crypto_larval_add(const char *name, u32 type,
return alg;
}
-void crypto_larval_kill(struct crypto_alg *alg)
+static void crypto_larval_kill(struct crypto_larval *larval)
{
- struct crypto_larval *larval = (void *)alg;
+ bool unlinked;
down_write(&crypto_alg_sem);
- list_del(&alg->cra_list);
+ unlinked = list_empty(&larval->alg.cra_list);
+ if (!unlinked)
+ list_del_init(&larval->alg.cra_list);
up_write(&crypto_alg_sem);
- complete_all(&larval->completion);
- crypto_alg_put(alg);
-}
-EXPORT_SYMBOL_GPL(crypto_larval_kill);
-void crypto_wait_for_test(struct crypto_larval *larval)
+ if (unlinked)
+ return;
+
+ complete_all(&larval->completion);
+ crypto_alg_put(&larval->alg);
+}
+
+void crypto_schedule_test(struct crypto_larval *larval)
{
int err;
err = crypto_probing_notify(CRYPTO_MSG_ALG_REGISTER, larval->adult);
- if (WARN_ON_ONCE(err != NOTIFY_STOP))
- goto out;
-
- err = wait_for_completion_killable(&larval->completion);
- WARN_ON(err);
-out:
- crypto_larval_kill(&larval->alg);
+ WARN_ON_ONCE(err != NOTIFY_STOP);
}
-EXPORT_SYMBOL_GPL(crypto_wait_for_test);
+EXPORT_SYMBOL_GPL(crypto_schedule_test);
static void crypto_start_test(struct crypto_larval *larval)
{
@@ -198,7 +197,7 @@ static void crypto_start_test(struct crypto_larval *larval)
larval->test_started = true;
up_write(&crypto_alg_sem);
- crypto_wait_for_test(larval);
+ crypto_schedule_test(larval);
}
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)
alg = larval->adult;
if (time_left < 0)
alg = ERR_PTR(-EINTR);
- else if (!time_left)
+ else if (!time_left) {
+ if (crypto_is_test_larval(larval))
+ crypto_larval_kill(larval);
alg = ERR_PTR(-ETIMEDOUT);
- else if (!alg) {
+ } else if (!alg) {
u32 type;
u32 mask;
@@ -355,7 +356,7 @@ struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
crypto_mod_put(larval);
alg = ERR_PTR(-ENOENT);
}
- crypto_larval_kill(larval);
+ crypto_larval_kill(container_of(larval, struct crypto_larval, alg));
return alg;
}
EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup);
diff --git a/crypto/internal.h b/crypto/internal.h
index aee31319be2e..711a6a5bfa2b 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -113,8 +113,7 @@ struct crypto_alg *crypto_mod_get(struct crypto_alg *alg);
struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask);
struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask);
-void crypto_larval_kill(struct crypto_alg *alg);
-void crypto_wait_for_test(struct crypto_larval *larval);
+void crypto_schedule_test(struct crypto_larval *larval);
void crypto_alg_tested(const char *name, int err);
void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
--
2.39.2
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related [flat|nested] 35+ messages in thread* [v3 PATCH 3/3] crypto: simd - Do not call crypto_alloc_tfm during registration
2024-08-17 6:57 ` [v3 PATCH 2/3] crypto: api - Do not wait for tests during registration Herbert Xu
@ 2024-08-17 6:58 ` Herbert Xu
2024-08-27 18:48 ` Eric Biggers
0 siblings, 1 reply; 35+ messages in thread
From: Herbert Xu @ 2024-08-17 6:58 UTC (permalink / raw)
To: kernel test robot
Cc: oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
Algorithm registration is usually carried out during module init,
where as little work as possible should be carried out. The SIMD
code violated this rule by allocating a tfm, this then triggers a
full test of the algorithm which may dead-lock in certain cases.
SIMD is only allocating the tfm to get at the alg object, which is
in fact already available as it is what we are registering. Use
that directly and remove the crypto_alloc_tfm call.
Also remove some obsolete and unused SIMD API.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
arch/arm/crypto/aes-ce-glue.c | 2 +-
arch/arm/crypto/aes-neonbs-glue.c | 2 +-
crypto/simd.c | 76 ++++++-------------------------
include/crypto/internal/simd.h | 12 +----
4 files changed, 19 insertions(+), 73 deletions(-)
diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c
index b668c97663ec..f5b66f4cf45d 100644
--- a/arch/arm/crypto/aes-ce-glue.c
+++ b/arch/arm/crypto/aes-ce-glue.c
@@ -711,7 +711,7 @@ static int __init aes_init(void)
algname = aes_algs[i].base.cra_name + 2;
drvname = aes_algs[i].base.cra_driver_name + 2;
basename = aes_algs[i].base.cra_driver_name;
- simd = simd_skcipher_create_compat(algname, drvname, basename);
+ simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename);
err = PTR_ERR(simd);
if (IS_ERR(simd))
goto unregister_simds;
diff --git a/arch/arm/crypto/aes-neonbs-glue.c b/arch/arm/crypto/aes-neonbs-glue.c
index fd04f855b2f5..f6be80b5938b 100644
--- a/arch/arm/crypto/aes-neonbs-glue.c
+++ b/arch/arm/crypto/aes-neonbs-glue.c
@@ -491,7 +491,7 @@ static int __init aes_init(void)
algname = aes_algs[i].base.cra_name + 2;
drvname = aes_algs[i].base.cra_driver_name + 2;
basename = aes_algs[i].base.cra_driver_name;
- simd = simd_skcipher_create_compat(algname, drvname, basename);
+ simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename);
err = PTR_ERR(simd);
if (IS_ERR(simd))
goto unregister_simds;
diff --git a/crypto/simd.c b/crypto/simd.c
index 2aa4f72e224f..b07721d1f3f6 100644
--- a/crypto/simd.c
+++ b/crypto/simd.c
@@ -136,27 +136,19 @@ static int simd_skcipher_init(struct crypto_skcipher *tfm)
return 0;
}
-struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname,
+struct simd_skcipher_alg *simd_skcipher_create_compat(struct skcipher_alg *ialg,
+ const char *algname,
const char *drvname,
const char *basename)
{
struct simd_skcipher_alg *salg;
- struct crypto_skcipher *tfm;
- struct skcipher_alg *ialg;
struct skcipher_alg *alg;
int err;
- tfm = crypto_alloc_skcipher(basename, CRYPTO_ALG_INTERNAL,
- CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm))
- return ERR_CAST(tfm);
-
- ialg = crypto_skcipher_alg(tfm);
-
salg = kzalloc(sizeof(*salg), GFP_KERNEL);
if (!salg) {
salg = ERR_PTR(-ENOMEM);
- goto out_put_tfm;
+ goto out;
}
salg->ialg_name = basename;
@@ -195,30 +187,16 @@ struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname,
if (err)
goto out_free_salg;
-out_put_tfm:
- crypto_free_skcipher(tfm);
+out:
return salg;
out_free_salg:
kfree(salg);
salg = ERR_PTR(err);
- goto out_put_tfm;
+ goto out;
}
EXPORT_SYMBOL_GPL(simd_skcipher_create_compat);
-struct simd_skcipher_alg *simd_skcipher_create(const char *algname,
- const char *basename)
-{
- char drvname[CRYPTO_MAX_ALG_NAME];
-
- if (snprintf(drvname, CRYPTO_MAX_ALG_NAME, "simd-%s", basename) >=
- CRYPTO_MAX_ALG_NAME)
- return ERR_PTR(-ENAMETOOLONG);
-
- return simd_skcipher_create_compat(algname, drvname, basename);
-}
-EXPORT_SYMBOL_GPL(simd_skcipher_create);
-
void simd_skcipher_free(struct simd_skcipher_alg *salg)
{
crypto_unregister_skcipher(&salg->alg);
@@ -246,7 +224,7 @@ int simd_register_skciphers_compat(struct skcipher_alg *algs, int count,
algname = algs[i].base.cra_name + 2;
drvname = algs[i].base.cra_driver_name + 2;
basename = algs[i].base.cra_driver_name;
- simd = simd_skcipher_create_compat(algname, drvname, basename);
+ simd = simd_skcipher_create_compat(algs + i, algname, drvname, basename);
err = PTR_ERR(simd);
if (IS_ERR(simd))
goto err_unregister;
@@ -383,27 +361,19 @@ static int simd_aead_init(struct crypto_aead *tfm)
return 0;
}
-struct simd_aead_alg *simd_aead_create_compat(const char *algname,
- const char *drvname,
- const char *basename)
+static struct simd_aead_alg *simd_aead_create_compat(struct aead_alg *ialg,
+ const char *algname,
+ const char *drvname,
+ const char *basename)
{
struct simd_aead_alg *salg;
- struct crypto_aead *tfm;
- struct aead_alg *ialg;
struct aead_alg *alg;
int err;
- tfm = crypto_alloc_aead(basename, CRYPTO_ALG_INTERNAL,
- CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm))
- return ERR_CAST(tfm);
-
- ialg = crypto_aead_alg(tfm);
-
salg = kzalloc(sizeof(*salg), GFP_KERNEL);
if (!salg) {
salg = ERR_PTR(-ENOMEM);
- goto out_put_tfm;
+ goto out;
}
salg->ialg_name = basename;
@@ -442,36 +412,20 @@ struct simd_aead_alg *simd_aead_create_compat(const char *algname,
if (err)
goto out_free_salg;
-out_put_tfm:
- crypto_free_aead(tfm);
+out:
return salg;
out_free_salg:
kfree(salg);
salg = ERR_PTR(err);
- goto out_put_tfm;
+ goto out;
}
-EXPORT_SYMBOL_GPL(simd_aead_create_compat);
-struct simd_aead_alg *simd_aead_create(const char *algname,
- const char *basename)
-{
- char drvname[CRYPTO_MAX_ALG_NAME];
-
- if (snprintf(drvname, CRYPTO_MAX_ALG_NAME, "simd-%s", basename) >=
- CRYPTO_MAX_ALG_NAME)
- return ERR_PTR(-ENAMETOOLONG);
-
- return simd_aead_create_compat(algname, drvname, basename);
-}
-EXPORT_SYMBOL_GPL(simd_aead_create);
-
-void simd_aead_free(struct simd_aead_alg *salg)
+static void simd_aead_free(struct simd_aead_alg *salg)
{
crypto_unregister_aead(&salg->alg);
kfree(salg);
}
-EXPORT_SYMBOL_GPL(simd_aead_free);
int simd_register_aeads_compat(struct aead_alg *algs, int count,
struct simd_aead_alg **simd_algs)
@@ -493,7 +447,7 @@ int simd_register_aeads_compat(struct aead_alg *algs, int count,
algname = algs[i].base.cra_name + 2;
drvname = algs[i].base.cra_driver_name + 2;
basename = algs[i].base.cra_driver_name;
- simd = simd_aead_create_compat(algname, drvname, basename);
+ simd = simd_aead_create_compat(algs + i, algname, drvname, basename);
err = PTR_ERR(simd);
if (IS_ERR(simd))
goto err_unregister;
diff --git a/include/crypto/internal/simd.h b/include/crypto/internal/simd.h
index d2316242a988..be97b97a75dd 100644
--- a/include/crypto/internal/simd.h
+++ b/include/crypto/internal/simd.h
@@ -14,11 +14,10 @@
struct simd_skcipher_alg;
struct skcipher_alg;
-struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname,
+struct simd_skcipher_alg *simd_skcipher_create_compat(struct skcipher_alg *ialg,
+ const char *algname,
const char *drvname,
const char *basename);
-struct simd_skcipher_alg *simd_skcipher_create(const char *algname,
- const char *basename);
void simd_skcipher_free(struct simd_skcipher_alg *alg);
int simd_register_skciphers_compat(struct skcipher_alg *algs, int count,
@@ -32,13 +31,6 @@ void simd_unregister_skciphers(struct skcipher_alg *algs, int count,
struct simd_aead_alg;
struct aead_alg;
-struct simd_aead_alg *simd_aead_create_compat(const char *algname,
- const char *drvname,
- const char *basename);
-struct simd_aead_alg *simd_aead_create(const char *algname,
- const char *basename);
-void simd_aead_free(struct simd_aead_alg *alg);
-
int simd_register_aeads_compat(struct aead_alg *algs, int count,
struct simd_aead_alg **simd_algs);
--
2.39.2
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related [flat|nested] 35+ messages in thread* Re: [v3 PATCH 3/3] crypto: simd - Do not call crypto_alloc_tfm during registration
2024-08-17 6:58 ` [v3 PATCH 3/3] crypto: simd - Do not call crypto_alloc_tfm " Herbert Xu
@ 2024-08-27 18:48 ` Eric Biggers
2024-08-28 2:59 ` Herbert Xu
0 siblings, 1 reply; 35+ messages in thread
From: Eric Biggers @ 2024-08-27 18:48 UTC (permalink / raw)
To: Herbert Xu
Cc: kernel test robot, oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
On Sat, Aug 17, 2024 at 02:58:35PM +0800, Herbert Xu wrote:
> Algorithm registration is usually carried out during module init,
> where as little work as possible should be carried out. The SIMD
> code violated this rule by allocating a tfm, this then triggers a
> full test of the algorithm which may dead-lock in certain cases.
>
> SIMD is only allocating the tfm to get at the alg object, which is
> in fact already available as it is what we are registering. Use
> that directly and remove the crypto_alloc_tfm call.
>
> Also remove some obsolete and unused SIMD API.
>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
> ---
> arch/arm/crypto/aes-ce-glue.c | 2 +-
> arch/arm/crypto/aes-neonbs-glue.c | 2 +-
> crypto/simd.c | 76 ++++++-------------------------
> include/crypto/internal/simd.h | 12 +----
> 4 files changed, 19 insertions(+), 73 deletions(-)
>
I'm getting a test failure with this series applied:
[ 0.383128] alg: aead: failed to allocate transform for gcm_base(ctr(aes-generic),ghash-generic): -2
[ 0.383500] alg: self-tests for gcm(aes) using gcm_base(ctr(aes-generic),ghash-generic) failed (rc=-2)
This is on x86_64 with CONFIG_CRYPTO_MANAGER_EXTRA_TESTS=y.
- Eric
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [v3 PATCH 3/3] crypto: simd - Do not call crypto_alloc_tfm during registration
2024-08-27 18:48 ` Eric Biggers
@ 2024-08-28 2:59 ` Herbert Xu
2024-08-30 17:51 ` Eric Biggers
0 siblings, 1 reply; 35+ messages in thread
From: Herbert Xu @ 2024-08-28 2:59 UTC (permalink / raw)
To: Eric Biggers
Cc: kernel test robot, oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
On Tue, Aug 27, 2024 at 11:48:39AM -0700, Eric Biggers wrote:
> On Sat, Aug 17, 2024 at 02:58:35PM +0800, Herbert Xu wrote:
> > Algorithm registration is usually carried out during module init,
> > where as little work as possible should be carried out. The SIMD
> > code violated this rule by allocating a tfm, this then triggers a
> > full test of the algorithm which may dead-lock in certain cases.
> >
> > SIMD is only allocating the tfm to get at the alg object, which is
> > in fact already available as it is what we are registering. Use
> > that directly and remove the crypto_alloc_tfm call.
> >
> > Also remove some obsolete and unused SIMD API.
> >
> > Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
> > ---
> > arch/arm/crypto/aes-ce-glue.c | 2 +-
> > arch/arm/crypto/aes-neonbs-glue.c | 2 +-
> > crypto/simd.c | 76 ++++++-------------------------
> > include/crypto/internal/simd.h | 12 +----
> > 4 files changed, 19 insertions(+), 73 deletions(-)
> >
>
> I'm getting a test failure with this series applied:
>
> [ 0.383128] alg: aead: failed to allocate transform for gcm_base(ctr(aes-generic),ghash-generic): -2
> [ 0.383500] alg: self-tests for gcm(aes) using gcm_base(ctr(aes-generic),ghash-generic) failed (rc=-2)
>
> This is on x86_64 with CONFIG_CRYPTO_MANAGER_EXTRA_TESTS=y.
Could you please send me your config file?
Thanks,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [v3 PATCH 3/3] crypto: simd - Do not call crypto_alloc_tfm during registration
2024-08-28 2:59 ` Herbert Xu
@ 2024-08-30 17:51 ` Eric Biggers
2024-09-01 8:05 ` [PATCH] crypto: api - Fix generic algorithm self-test races Herbert Xu
0 siblings, 1 reply; 35+ messages in thread
From: Eric Biggers @ 2024-08-30 17:51 UTC (permalink / raw)
To: Herbert Xu
Cc: kernel test robot, oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
On Wed, Aug 28, 2024 at 10:59:20AM +0800, Herbert Xu wrote:
> On Tue, Aug 27, 2024 at 11:48:39AM -0700, Eric Biggers wrote:
> > On Sat, Aug 17, 2024 at 02:58:35PM +0800, Herbert Xu wrote:
> > > Algorithm registration is usually carried out during module init,
> > > where as little work as possible should be carried out. The SIMD
> > > code violated this rule by allocating a tfm, this then triggers a
> > > full test of the algorithm which may dead-lock in certain cases.
> > >
> > > SIMD is only allocating the tfm to get at the alg object, which is
> > > in fact already available as it is what we are registering. Use
> > > that directly and remove the crypto_alloc_tfm call.
> > >
> > > Also remove some obsolete and unused SIMD API.
> > >
> > > Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
> > > ---
> > > arch/arm/crypto/aes-ce-glue.c | 2 +-
> > > arch/arm/crypto/aes-neonbs-glue.c | 2 +-
> > > crypto/simd.c | 76 ++++++-------------------------
> > > include/crypto/internal/simd.h | 12 +----
> > > 4 files changed, 19 insertions(+), 73 deletions(-)
> > >
> >
> > I'm getting a test failure with this series applied:
> >
> > [ 0.383128] alg: aead: failed to allocate transform for gcm_base(ctr(aes-generic),ghash-generic): -2
> > [ 0.383500] alg: self-tests for gcm(aes) using gcm_base(ctr(aes-generic),ghash-generic) failed (rc=-2)
> >
> > This is on x86_64 with CONFIG_CRYPTO_MANAGER_EXTRA_TESTS=y.
>
> Could you please send me your config file?
>
> Thanks,
Given below in defconfig form, use 'make olddefconfig' to apply. The failures
are nondeterministic and sometimes there are different ones, for example:
[ 0.358017] alg: skcipher: failed to allocate transform for cbc(twofish-generic): -2
[ 0.358365] alg: self-tests for cbc(twofish) using cbc(twofish-generic) failed (rc=-2)
[ 0.358535] alg: skcipher: failed to allocate transform for cbc(camellia-generic): -2
[ 0.358918] alg: self-tests for cbc(camellia) using cbc(camellia-generic) failed (rc=-2)
[ 0.371533] alg: skcipher: failed to allocate transform for xts(ecb(aes-generic)): -2
[ 0.371922] alg: self-tests for xts(aes) using xts(ecb(aes-generic)) failed (rc=-2)
Modules are not enabled, maybe that matters (I haven't checked yet).
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CGROUPS=y
CONFIG_USER_NS=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_SMP=y
CONFIG_X86_X2APIC=y
CONFIG_HYPERVISOR_GUEST=y
CONFIG_PARAVIRT=y
CONFIG_MCORE2=y
CONFIG_NR_CPUS=48
CONFIG_NUMA=y
CONFIG_HZ_300=y
# CONFIG_RANDOMIZE_BASE is not set
CONFIG_IA32_EMULATION=y
CONFIG_JUMP_LABEL=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=y
CONFIG_UNIX=y
CONFIG_UNIX_DIAG=y
CONFIG_INET=y
CONFIG_PCI=y
CONFIG_PCI_MSI=y
CONFIG_DEVTMPFS=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_VIRTIO_BLK=y
CONFIG_NETDEVICES=y
CONFIG_VIRTIO_NET=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=32
CONFIG_SERIAL_8250_RUNTIME_UARTS=32
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_VIRT_DRIVERS=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_MMIO=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_AUTOFS_FS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_CRYPTO_USER=y
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
CONFIG_CRYPTO_MANAGER_EXTRA_TESTS=y
CONFIG_CRYPTO_PCRYPT=y
CONFIG_CRYPTO_DH_RFC7919_GROUPS=y
CONFIG_CRYPTO_ECDH=y
CONFIG_CRYPTO_ECDSA=y
CONFIG_CRYPTO_ECRDSA=y
CONFIG_CRYPTO_CURVE25519=y
CONFIG_CRYPTO_AES_TI=y
CONFIG_CRYPTO_ANUBIS=y
CONFIG_CRYPTO_BLOWFISH=y
CONFIG_CRYPTO_CAMELLIA=y
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_FCRYPT=y
CONFIG_CRYPTO_KHAZAD=y
CONFIG_CRYPTO_SEED=y
CONFIG_CRYPTO_TEA=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_ADIANTUM=y
CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_HCTR2=y
CONFIG_CRYPTO_KEYWRAP=y
CONFIG_CRYPTO_LRW=y
CONFIG_CRYPTO_PCBC=y
CONFIG_CRYPTO_AEGIS128=y
CONFIG_CRYPTO_SEQIV=y
CONFIG_CRYPTO_ECHAINIV=y
CONFIG_CRYPTO_ESSIV=y
CONFIG_CRYPTO_BLAKE2B=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_RMD160=y
CONFIG_CRYPTO_SM3_GENERIC=y
CONFIG_CRYPTO_VMAC=y
CONFIG_CRYPTO_WP512=y
CONFIG_CRYPTO_XXHASH=y
CONFIG_CRYPTO_CRC32=y
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_842=y
CONFIG_CRYPTO_LZ4=y
CONFIG_CRYPTO_LZ4HC=y
CONFIG_CRYPTO_ZSTD=y
CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_USER_API_SKCIPHER=y
CONFIG_CRYPTO_USER_API_RNG=y
CONFIG_CRYPTO_USER_API_RNG_CAVP=y
CONFIG_CRYPTO_USER_API_AEAD=y
CONFIG_CRYPTO_CURVE25519_X86=y
CONFIG_CRYPTO_AES_NI_INTEL=y
CONFIG_CRYPTO_BLOWFISH_X86_64=y
CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=y
CONFIG_CRYPTO_CAST5_AVX_X86_64=y
CONFIG_CRYPTO_CAST6_AVX_X86_64=y
CONFIG_CRYPTO_DES3_EDE_X86_64=y
CONFIG_CRYPTO_SERPENT_SSE2_X86_64=y
CONFIG_CRYPTO_SERPENT_AVX2_X86_64=y
CONFIG_CRYPTO_SM4_AESNI_AVX2_X86_64=y
CONFIG_CRYPTO_TWOFISH_AVX_X86_64=y
CONFIG_CRYPTO_ARIA_GFNI_AVX512_X86_64=y
CONFIG_CRYPTO_CHACHA20_X86_64=y
CONFIG_CRYPTO_AEGIS128_AESNI_SSE2=y
CONFIG_CRYPTO_NHPOLY1305_SSE2=y
CONFIG_CRYPTO_NHPOLY1305_AVX2=y
CONFIG_CRYPTO_BLAKE2S_X86=y
CONFIG_CRYPTO_POLYVAL_CLMUL_NI=y
CONFIG_CRYPTO_POLY1305_X86_64=y
CONFIG_CRYPTO_SHA1_SSSE3=y
CONFIG_CRYPTO_SHA256_SSSE3=y
CONFIG_CRYPTO_SHA512_SSSE3=y
CONFIG_CRYPTO_SM3_AVX_X86_64=y
CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=y
CONFIG_CRYPTO_CRC32C_INTEL=y
CONFIG_CRYPTO_CRC32_PCLMUL=y
CONFIG_CRYPTO_CRCT10DIF_PCLMUL=y
CONFIG_CRYPTO_DEV_PADLOCK=y
CONFIG_CRYPTO_DEV_PADLOCK_AES=y
CONFIG_CRYPTO_DEV_PADLOCK_SHA=y
CONFIG_CRYPTO_DEV_CCP=y
CONFIG_CRYPTO_DEV_NITROX_CNN55XX=y
CONFIG_CRYPTO_DEV_QAT_DH895xCC=y
CONFIG_CRYPTO_DEV_QAT_C3XXX=y
CONFIG_CRYPTO_DEV_QAT_C62X=y
CONFIG_CRYPTO_DEV_QAT_4XXX=y
CONFIG_CRYPTO_DEV_QAT_DH895xCCVF=y
CONFIG_CRYPTO_DEV_QAT_C3XXXVF=y
CONFIG_CRYPTO_DEV_QAT_C62XVF=y
CONFIG_CRYPTO_DEV_VIRTIO=y
CONFIG_CRYPTO_DEV_SAFEXCEL=y
CONFIG_CRYPTO_DEV_AMLOGIC_GXL=y
CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG=y
CONFIG_CRYPTO_LIB_CURVE25519=y
CONFIG_CRYPTO_LIB_CHACHA20POLY1305=y
CONFIG_CRC_CCITT=y
CONFIG_CRC_T10DIF=y
CONFIG_CRC64_ROCKSOFT=y
CONFIG_CRC_ITU_T=y
CONFIG_CRC32_SELFTEST=y
CONFIG_CRC32_SLICEBY4=y
CONFIG_CRC4=y
CONFIG_CRC7=y
CONFIG_LIBCRC32C=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_FS=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_UNWINDER_FRAME_POINTER=y
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH] crypto: api - Fix generic algorithm self-test races
2024-08-30 17:51 ` Eric Biggers
@ 2024-09-01 8:05 ` Herbert Xu
2024-09-02 17:05 ` Eric Biggers
0 siblings, 1 reply; 35+ messages in thread
From: Herbert Xu @ 2024-09-01 8:05 UTC (permalink / raw)
To: Eric Biggers
Cc: kernel test robot, oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
On Fri, Aug 30, 2024 at 10:51:54AM -0700, Eric Biggers wrote:
>
> Given below in defconfig form, use 'make olddefconfig' to apply. The failures
> are nondeterministic and sometimes there are different ones, for example:
>
> [ 0.358017] alg: skcipher: failed to allocate transform for cbc(twofish-generic): -2
> [ 0.358365] alg: self-tests for cbc(twofish) using cbc(twofish-generic) failed (rc=-2)
> [ 0.358535] alg: skcipher: failed to allocate transform for cbc(camellia-generic): -2
> [ 0.358918] alg: self-tests for cbc(camellia) using cbc(camellia-generic) failed (rc=-2)
> [ 0.371533] alg: skcipher: failed to allocate transform for xts(ecb(aes-generic)): -2
> [ 0.371922] alg: self-tests for xts(aes) using xts(ecb(aes-generic)) failed (rc=-2)
>
> Modules are not enabled, maybe that matters (I haven't checked yet).
Yes I think that was the key. This triggers a massive self-test
run which executes in parallel and reveals a few race conditions
in the system. I think it boils down to the following scenario:
Base algorithm X-generic, X-optimised
Template Y
Optimised algorithm Y-X-optimised
Everything gets registered, and then the self-tests are started.
When Y-X-optimised gets tested, it requests the creation of the
generic Y(X-generic). Which then itself undergoes testing.
The race is that after Y(X-generic) gets registered, but just
before it gets tested, X-optimised finally finishes self-testing
which then causes all spawns of X-generic to be destroyed. So
by the time the self-test for Y(X-generic) comes along, it can
no longer find the algorithm. This error then bubbles up all
the way up to the self-test of Y-X-optimised which then fails.
Note that there is some complexity that I've omitted here because
when the generic self-test fails to find Y(X-generic) it actually
triggers the construction of it again which then fails for various
other reasons (these are not important because the construction
should *not* be triggered at this point).
So in a way the error is expected, and we should probably remove
the pr_err for the case where ENOENT is returned for the algorithm
that we're currently testing.
The solution is two-fold. First when an algorithm undergoes
self-testing it should not trigger its construction. Secondly
if an instance larval fails to materialise due to it being destroyed
by a more optimised algorithm coming along, it should obviously
retry the construction.
Remove the check in __crypto_alg_lookup that stops a larval from
matching new requests based on differences in the mask. It is better
to block new requests even if it is wrong and then simply retry the
lookup. If this ends up being the wrong larval it will sort iself
out during the retry.
Reduce the CRYPTO_ALG_TYPE_MASK bits in type during larval creation
as otherwise LSKCIPHER algorithms may not match SKCIPHER larvals.
Also block the instance creation during self-testing in the function
crypto_larval_lookup by checking for CRYPTO_ALG_TESTED in the mask
field.
Finally change the return value when crypto_alg_lookup fails in
crypto_larval_wait to EAGAIN to redo the lookup.
Fixes: 37da5d0ffa7b ("crypto: api - Do not wait for tests during registration")
Reported-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff --git a/crypto/api.c b/crypto/api.c
index bbe29d438815..bfd177a4313a 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -70,11 +70,6 @@ static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type,
if ((q->cra_flags ^ type) & mask)
continue;
- if (crypto_is_larval(q) &&
- !crypto_is_test_larval((struct crypto_larval *)q) &&
- ((struct crypto_larval *)q)->mask != mask)
- continue;
-
exact = !strcmp(q->cra_driver_name, name);
fuzzy = !strcmp(q->cra_name, name);
if (!exact && !(fuzzy && q->cra_priority > best))
@@ -113,6 +108,8 @@ struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask)
if (!larval)
return ERR_PTR(-ENOMEM);
+ type &= ~CRYPTO_ALG_TYPE_MASK | (mask ?: CRYPTO_ALG_TYPE_MASK);
+
larval->mask = mask;
larval->alg.cra_flags = CRYPTO_ALG_LARVAL | type;
larval->alg.cra_priority = -1;
@@ -229,7 +226,7 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
type = alg->cra_flags & ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
mask = larval->mask;
alg = crypto_alg_lookup(alg->cra_name, type, mask) ?:
- ERR_PTR(-ENOENT);
+ ERR_PTR(-EAGAIN);
} else if (IS_ERR(alg))
;
else if (crypto_is_test_larval(larval) &&
@@ -308,8 +305,12 @@ static struct crypto_alg *crypto_larval_lookup(const char *name, u32 type,
if (!IS_ERR_OR_NULL(alg) && crypto_is_larval(alg))
alg = crypto_larval_wait(alg);
- else if (!alg)
+ else if (alg)
+ ;
+ else if (!(mask & CRYPTO_ALG_TESTED))
alg = crypto_larval_add(name, type, mask);
+ else
+ alg = ERR_PTR(-ENOENT);
return alg;
}
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related [flat|nested] 35+ messages in thread* Re: [PATCH] crypto: api - Fix generic algorithm self-test races
2024-09-01 8:05 ` [PATCH] crypto: api - Fix generic algorithm self-test races Herbert Xu
@ 2024-09-02 17:05 ` Eric Biggers
2024-09-02 23:07 ` Herbert Xu
0 siblings, 1 reply; 35+ messages in thread
From: Eric Biggers @ 2024-09-02 17:05 UTC (permalink / raw)
To: Herbert Xu
Cc: kernel test robot, oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
On Sun, Sep 01, 2024 at 04:05:40PM +0800, Herbert Xu wrote:
> On Fri, Aug 30, 2024 at 10:51:54AM -0700, Eric Biggers wrote:
> >
> > Given below in defconfig form, use 'make olddefconfig' to apply. The failures
> > are nondeterministic and sometimes there are different ones, for example:
> >
> > [ 0.358017] alg: skcipher: failed to allocate transform for cbc(twofish-generic): -2
> > [ 0.358365] alg: self-tests for cbc(twofish) using cbc(twofish-generic) failed (rc=-2)
> > [ 0.358535] alg: skcipher: failed to allocate transform for cbc(camellia-generic): -2
> > [ 0.358918] alg: self-tests for cbc(camellia) using cbc(camellia-generic) failed (rc=-2)
> > [ 0.371533] alg: skcipher: failed to allocate transform for xts(ecb(aes-generic)): -2
> > [ 0.371922] alg: self-tests for xts(aes) using xts(ecb(aes-generic)) failed (rc=-2)
> >
> > Modules are not enabled, maybe that matters (I haven't checked yet).
>
> Yes I think that was the key. This triggers a massive self-test
> run which executes in parallel and reveals a few race conditions
> in the system. I think it boils down to the following scenario:
>
> Base algorithm X-generic, X-optimised
> Template Y
> Optimised algorithm Y-X-optimised
>
> Everything gets registered, and then the self-tests are started.
> When Y-X-optimised gets tested, it requests the creation of the
> generic Y(X-generic). Which then itself undergoes testing.
>
> The race is that after Y(X-generic) gets registered, but just
> before it gets tested, X-optimised finally finishes self-testing
> which then causes all spawns of X-generic to be destroyed. So
> by the time the self-test for Y(X-generic) comes along, it can
> no longer find the algorithm. This error then bubbles up all
> the way up to the self-test of Y-X-optimised which then fails.
>
> Note that there is some complexity that I've omitted here because
> when the generic self-test fails to find Y(X-generic) it actually
> triggers the construction of it again which then fails for various
> other reasons (these are not important because the construction
> should *not* be triggered at this point).
>
> So in a way the error is expected, and we should probably remove
> the pr_err for the case where ENOENT is returned for the algorithm
> that we're currently testing.
>
> The solution is two-fold. First when an algorithm undergoes
> self-testing it should not trigger its construction. Secondly
> if an instance larval fails to materialise due to it being destroyed
> by a more optimised algorithm coming along, it should obviously
> retry the construction.
>
> Remove the check in __crypto_alg_lookup that stops a larval from
> matching new requests based on differences in the mask. It is better
> to block new requests even if it is wrong and then simply retry the
> lookup. If this ends up being the wrong larval it will sort iself
> out during the retry.
>
> Reduce the CRYPTO_ALG_TYPE_MASK bits in type during larval creation
> as otherwise LSKCIPHER algorithms may not match SKCIPHER larvals.
>
> Also block the instance creation during self-testing in the function
> crypto_larval_lookup by checking for CRYPTO_ALG_TESTED in the mask
> field.
>
> Finally change the return value when crypto_alg_lookup fails in
> crypto_larval_wait to EAGAIN to redo the lookup.
>
> Fixes: 37da5d0ffa7b ("crypto: api - Do not wait for tests during registration")
> Reported-by: Eric Biggers <ebiggers@kernel.org>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
>
> diff --git a/crypto/api.c b/crypto/api.c
> index bbe29d438815..bfd177a4313a 100644
> --- a/crypto/api.c
> +++ b/crypto/api.c
> @@ -70,11 +70,6 @@ static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type,
> if ((q->cra_flags ^ type) & mask)
> continue;
>
> - if (crypto_is_larval(q) &&
> - !crypto_is_test_larval((struct crypto_larval *)q) &&
> - ((struct crypto_larval *)q)->mask != mask)
> - continue;
> -
> exact = !strcmp(q->cra_driver_name, name);
> fuzzy = !strcmp(q->cra_name, name);
> if (!exact && !(fuzzy && q->cra_priority > best))
> @@ -113,6 +108,8 @@ struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask)
> if (!larval)
> return ERR_PTR(-ENOMEM);
>
> + type &= ~CRYPTO_ALG_TYPE_MASK | (mask ?: CRYPTO_ALG_TYPE_MASK);
> +
> larval->mask = mask;
> larval->alg.cra_flags = CRYPTO_ALG_LARVAL | type;
> larval->alg.cra_priority = -1;
> @@ -229,7 +226,7 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
> type = alg->cra_flags & ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
> mask = larval->mask;
> alg = crypto_alg_lookup(alg->cra_name, type, mask) ?:
> - ERR_PTR(-ENOENT);
> + ERR_PTR(-EAGAIN);
> } else if (IS_ERR(alg))
> ;
> else if (crypto_is_test_larval(larval) &&
> @@ -308,8 +305,12 @@ static struct crypto_alg *crypto_larval_lookup(const char *name, u32 type,
>
> if (!IS_ERR_OR_NULL(alg) && crypto_is_larval(alg))
> alg = crypto_larval_wait(alg);
> - else if (!alg)
> + else if (alg)
> + ;
> + else if (!(mask & CRYPTO_ALG_TESTED))
> alg = crypto_larval_add(name, type, mask);
> + else
> + alg = ERR_PTR(-ENOENT);
>
> return alg;
> }
With both this patch "crypto: api - Fix generic algorithm self-test races" and
your other patch "crypto: algboss - Pass instance creation error up" applied,
I'm still getting errors occasionally, e.g.:
[ 5.155587] alg: skcipher: failed to allocate transform for cbc(sm4-generic): -2
[ 5.155954] alg: self-tests for cbc(sm4) using cbc(sm4-generic) failed (rc=-2)
[ 5.372511] alg: aead: failed to allocate transform for gcm_base(ctr(aes-generic),ghash-generic): -2
[ 5.372861] alg: self-tests for gcm(aes) using gcm_base(ctr(aes-generic),ghash-generic) failed (rc=-2)
I can't follow your explanation of what is going on here and what the fix is.
Would it make any sense to just revert the commits that introduced this problem?
- Eric
^ permalink raw reply [flat|nested] 35+ messages in thread* Re: [PATCH] crypto: api - Fix generic algorithm self-test races
2024-09-02 17:05 ` Eric Biggers
@ 2024-09-02 23:07 ` Herbert Xu
2024-10-05 22:24 ` Eric Biggers
0 siblings, 1 reply; 35+ messages in thread
From: Herbert Xu @ 2024-09-02 23:07 UTC (permalink / raw)
To: Eric Biggers
Cc: kernel test robot, oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
On Mon, Sep 02, 2024 at 10:05:54AM -0700, Eric Biggers wrote:
>
> With both this patch "crypto: api - Fix generic algorithm self-test races" and
> your other patch "crypto: algboss - Pass instance creation error up" applied,
> I'm still getting errors occasionally, e.g.:
>
> [ 5.155587] alg: skcipher: failed to allocate transform for cbc(sm4-generic): -2
> [ 5.155954] alg: self-tests for cbc(sm4) using cbc(sm4-generic) failed (rc=-2)
> [ 5.372511] alg: aead: failed to allocate transform for gcm_base(ctr(aes-generic),ghash-generic): -2
> [ 5.372861] alg: self-tests for gcm(aes) using gcm_base(ctr(aes-generic),ghash-generic) failed (rc=-2)
>
> I can't follow your explanation of what is going on here and what the fix is.
> Would it make any sense to just revert the commits that introduced this problem?
As I said earlier, these errors are expected. What's happening
is this:
__ecb-sm4-aesni-avx gets registered (but not tested)
cbc(sm4-generic) gets registered (but not tested)
__ecb-sm4-aesni-avx finishes testing
with lskcipher this is equivalent to crypto_cipher sm4
so it triggers the destruction of all instances of sm4
cbc(sm4-generic) gets marked as dead
cbc(sm4-generic) fails self-test because it's already dead (ENOENT)
It's harmless because whatever that is asking for cbc(sm4-generic)
(in this case it's the extra-test mechanism) will simply retry the
allocation which will then succeed.
I will send a patch to disable the warning when allocating X returns
ENOENT while we're testing X itself. This can always happen if X
gets killed for the reason mentioned above and it's perfectly harmless.
It's just that the race window was tiny previously because testing
occurred immediately after registration. But now we've magnified
that window many times with asynchronous testing.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] crypto: api - Fix generic algorithm self-test races
2024-09-02 23:07 ` Herbert Xu
@ 2024-10-05 22:24 ` Eric Biggers
2024-10-06 0:53 ` Herbert Xu
0 siblings, 1 reply; 35+ messages in thread
From: Eric Biggers @ 2024-10-05 22:24 UTC (permalink / raw)
To: Herbert Xu
Cc: kernel test robot, oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
On Tue, Sep 03, 2024 at 07:07:38AM +0800, Herbert Xu wrote:
> On Mon, Sep 02, 2024 at 10:05:54AM -0700, Eric Biggers wrote:
> >
> > With both this patch "crypto: api - Fix generic algorithm self-test races" and
> > your other patch "crypto: algboss - Pass instance creation error up" applied,
> > I'm still getting errors occasionally, e.g.:
> >
> > [ 5.155587] alg: skcipher: failed to allocate transform for cbc(sm4-generic): -2
> > [ 5.155954] alg: self-tests for cbc(sm4) using cbc(sm4-generic) failed (rc=-2)
> > [ 5.372511] alg: aead: failed to allocate transform for gcm_base(ctr(aes-generic),ghash-generic): -2
> > [ 5.372861] alg: self-tests for gcm(aes) using gcm_base(ctr(aes-generic),ghash-generic) failed (rc=-2)
> >
> > I can't follow your explanation of what is going on here and what the fix is.
> > Would it make any sense to just revert the commits that introduced this problem?
>
> As I said earlier, these errors are expected. What's happening
> is this:
>
> __ecb-sm4-aesni-avx gets registered (but not tested)
>
> cbc(sm4-generic) gets registered (but not tested)
>
> __ecb-sm4-aesni-avx finishes testing
> with lskcipher this is equivalent to crypto_cipher sm4
> so it triggers the destruction of all instances of sm4
>
> cbc(sm4-generic) gets marked as dead
>
> cbc(sm4-generic) fails self-test because it's already dead (ENOENT)
>
> It's harmless because whatever that is asking for cbc(sm4-generic)
> (in this case it's the extra-test mechanism) will simply retry the
> allocation which will then succeed.
>
> I will send a patch to disable the warning when allocating X returns
> ENOENT while we're testing X itself. This can always happen if X
> gets killed for the reason mentioned above and it's perfectly harmless.
>
> It's just that the race window was tiny previously because testing
> occurred immediately after registration. But now we've magnified
> that window many times with asynchronous testing.
>
The tests are still failing on upstream:
[ 0.343845] alg: self-tests for rfc4106(gcm(aes)) using rfc4106(gcm_base(ctr(aes-generic),ghash-generic)) failed (rc=-2)
To me it still seems like commit 37da5d0ffa7b ("crypto: api - Do not wait for
tests during registration") is just broken and should be reverted.
Besides the test failures, it looks like there's no longer any guarantee that
algorithms are actually available now that their module is loaded.
E.g. consider if someone does 'modprobe aesni-intel' and then immediately
creates a dm-crypt device. Now it sounds like the AES-NI algorithms might not
have finished being tested yet and the generic algorithms can be used instead,
resulting in a performance regression.
I understand that you want to try to fix the edge cases in "fallback" ciphers.
But "fallback" ciphers have always seemed like a bad design due to how they use
the crypto API recursively. I think the algorithms that use them should
generally be migrated off of them, e.g. as I did in commit f235bc11cc95
("crypto: arm/aes-neonbs - go back to using aes-arm directly"). That fixed the
problem in aes-neonbs that seems to have triggered this work in the first place.
- Eric
^ permalink raw reply [flat|nested] 35+ messages in thread* Re: [PATCH] crypto: api - Fix generic algorithm self-test races
2024-10-05 22:24 ` Eric Biggers
@ 2024-10-06 0:53 ` Herbert Xu
2024-10-06 3:06 ` Eric Biggers
0 siblings, 1 reply; 35+ messages in thread
From: Herbert Xu @ 2024-10-06 0:53 UTC (permalink / raw)
To: Eric Biggers
Cc: kernel test robot, oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
On Sat, Oct 05, 2024 at 03:24:48PM -0700, Eric Biggers wrote:
>
> The tests are still failing on upstream:
>
> [ 0.343845] alg: self-tests for rfc4106(gcm(aes)) using rfc4106(gcm_base(ctr(aes-generic),ghash-generic)) failed (rc=-2)
You're right. I only disabled the warnings at the point of
allocation, the overall self-test warning is still there. Let
me get rid of them too.
> Besides the test failures, it looks like there's no longer any guarantee that
> algorithms are actually available now that their module is loaded.
That would indeed be a bug. But I haven't seen it in practice.
Although the s390 folks were reporting some weird errors with
dm-crypt, they have recently disappeared.
If you do see an actual failure please report it and then I'll
consider reverting it until it's fixed.
> E.g. consider if someone does 'modprobe aesni-intel' and then immediately
> creates a dm-crypt device. Now it sounds like the AES-NI algorithms might not
> have finished being tested yet and the generic algorithms can be used instead,
> resulting in a performance regression.
That is not the case. After modprobe returns, the algorithm is
guaranteed to have been registered. Yes it is untested, but that
should not be a problem because a test larval will have been created
and all users looking for that algorithm will be waiting on that
test larval.
> I understand that you want to try to fix the edge cases in "fallback" ciphers.
> But "fallback" ciphers have always seemed like a bad design due to how they use
> the crypto API recursively. I think the algorithms that use them should
> generally be migrated off of them, e.g. as I did in commit f235bc11cc95
> ("crypto: arm/aes-neonbs - go back to using aes-arm directly"). That fixed the
> problem in aes-neonbs that seems to have triggered this work in the first place.
Yes getting rid of fallbacks is nice, but this it not the reason why
we're making self-test asynchronous. The primary issue with synchronous
self-tests is the modprobe dead-lock.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 35+ messages in thread* Re: [PATCH] crypto: api - Fix generic algorithm self-test races
2024-10-06 0:53 ` Herbert Xu
@ 2024-10-06 3:06 ` Eric Biggers
2024-10-07 4:32 ` Herbert Xu
0 siblings, 1 reply; 35+ messages in thread
From: Eric Biggers @ 2024-10-06 3:06 UTC (permalink / raw)
To: Herbert Xu
Cc: kernel test robot, oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
On Sun, Oct 06, 2024 at 08:53:28AM +0800, Herbert Xu wrote:
> On Sat, Oct 05, 2024 at 03:24:48PM -0700, Eric Biggers wrote:
> >
> > The tests are still failing on upstream:
> >
> > [ 0.343845] alg: self-tests for rfc4106(gcm(aes)) using rfc4106(gcm_base(ctr(aes-generic),ghash-generic)) failed (rc=-2)
>
> You're right. I only disabled the warnings at the point of
> allocation, the overall self-test warning is still there. Let
> me get rid of them too.
>
> > Besides the test failures, it looks like there's no longer any guarantee that
> > algorithms are actually available now that their module is loaded.
>
> That would indeed be a bug. But I haven't seen it in practice.
> Although the s390 folks were reporting some weird errors with
> dm-crypt, they have recently disappeared.
>
> If you do see an actual failure please report it and then I'll
> consider reverting it until it's fixed.
>
> > E.g. consider if someone does 'modprobe aesni-intel' and then immediately
> > creates a dm-crypt device. Now it sounds like the AES-NI algorithms might not
> > have finished being tested yet and the generic algorithms can be used instead,
> > resulting in a performance regression.
>
> That is not the case. After modprobe returns, the algorithm is
> guaranteed to have been registered. Yes it is untested, but that
> should not be a problem because a test larval will have been created
> and all users looking for that algorithm will be waiting on that
> test larval.
I'm not sure about that, since the code that looks up algorithms only looks for
algorithms that already have the CRYPTO_ALG_TESTED flag.
> > I understand that you want to try to fix the edge cases in "fallback" ciphers.
> > But "fallback" ciphers have always seemed like a bad design due to how they use
> > the crypto API recursively. I think the algorithms that use them should
> > generally be migrated off of them, e.g. as I did in commit f235bc11cc95
> > ("crypto: arm/aes-neonbs - go back to using aes-arm directly"). That fixed the
> > problem in aes-neonbs that seems to have triggered this work in the first place.
>
> Yes getting rid of fallbacks is nice, but this it not the reason why
> we're making self-test asynchronous. The primary issue with synchronous
> self-tests is the modprobe dead-lock.
That problem is caused by the use of fallback ciphers, though.
- Eric
^ permalink raw reply [flat|nested] 35+ messages in thread* Re: [PATCH] crypto: api - Fix generic algorithm self-test races
2024-10-06 3:06 ` Eric Biggers
@ 2024-10-07 4:32 ` Herbert Xu
2024-10-07 7:58 ` Herbert Xu
2024-10-07 8:31 ` Herbert Xu
0 siblings, 2 replies; 35+ messages in thread
From: Herbert Xu @ 2024-10-07 4:32 UTC (permalink / raw)
To: Eric Biggers
Cc: kernel test robot, oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
On Sat, Oct 05, 2024 at 08:06:18PM -0700, Eric Biggers wrote:
>
> I'm not sure about that, since the code that looks up algorithms only looks for
> algorithms that already have the CRYPTO_ALG_TESTED flag.
For normal lookups (one without CRYPTO_ALG_TESTED set in the mask
field), the core API will first look for a tested algorithm, and
if that fails then it will look for an untested algorithm. The
second step should find the larval and then sleep on that until it's
done.
> That problem is caused by the use of fallback ciphers, though.
Sure that particular deadlock may have been due to a fallback,
but such dependencies exist outside of fallbacks too. Especially
now that we have the fuzz testing which will dynamically load the
generic algorithms, it's easy to envisage a scenario where one
module registers an algorithm, which then triggers modprobe's on the
generic implementation of the same algorithm that then dead-locks.
PS it looks like there is an actual report of things breaking with
async testing in mv_cesa so I might revert/disable the async testing
after all.
Thanks,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] crypto: api - Fix generic algorithm self-test races
2024-10-07 4:32 ` Herbert Xu
@ 2024-10-07 7:58 ` Herbert Xu
2024-10-07 8:31 ` Herbert Xu
1 sibling, 0 replies; 35+ messages in thread
From: Herbert Xu @ 2024-10-07 7:58 UTC (permalink / raw)
To: Eric Biggers
Cc: kernel test robot, oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
On Mon, Oct 07, 2024 at 12:32:22PM +0800, Herbert Xu wrote:
>
> For normal lookups (one without CRYPTO_ALG_TESTED set in the mask
> field), the core API will first look for a tested algorithm, and
> if that fails then it will look for an untested algorithm. The
> second step should find the larval and then sleep on that until it's
> done.
Actually that's not quite right. The test larval is registered
with TESTED set so normal lookups will latch onto that and then
wait.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] crypto: api - Fix generic algorithm self-test races
2024-10-07 4:32 ` Herbert Xu
2024-10-07 7:58 ` Herbert Xu
@ 2024-10-07 8:31 ` Herbert Xu
1 sibling, 0 replies; 35+ messages in thread
From: Herbert Xu @ 2024-10-07 8:31 UTC (permalink / raw)
To: Eric Biggers
Cc: kernel test robot, oe-lkp, lkp, linux-crypto, ltp, Linus Torvalds,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller
On Mon, Oct 07, 2024 at 12:32:22PM +0800, Herbert Xu wrote:
>
> PS it looks like there is an actual report of things breaking with
> async testing in mv_cesa so I might revert/disable the async testing
> after all.
It looks like it wasn't a bug in the async self-test.
Instead this appears to be a real bug that was discovered by the
async testing (because we now run all the tests at the same time,
thus testing the whether the driver deals with parallel requests
or not).
This is a bit accidental, because the driver in question registered
multiple hash algorithms. Had it only registered one, then nothing
would have changed.
Is this something that we could improve in testmgr? Perhaps we can
add a bit of parallelism ourselves to cover the case where a driver
only registers one hash algorithm.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 2/3] crypto: api - Do not wait for tests during registration
2024-08-09 4:40 ` Herbert Xu
` (2 preceding siblings ...)
2024-08-10 2:41 ` [PATCH 1/3] crypto: api - Remove instance larval fulfilment Herbert Xu
@ 2024-08-10 2:42 ` Herbert Xu
2024-08-11 13:30 ` Dan Carpenter
2024-08-10 2:43 ` [PATCH " Herbert Xu
4 siblings, 1 reply; 35+ messages in thread
From: Herbert Xu @ 2024-08-10 2:42 UTC (permalink / raw)
To: Linus Torvalds
Cc: Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller, linux-crypto
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>
---
crypto/algapi.c | 19 ++++++++++---------
crypto/api.c | 41 +++++++++++++++++++++--------------------
crypto/internal.h | 3 +--
3 files changed, 32 insertions(+), 31 deletions(-)
diff --git a/crypto/algapi.c b/crypto/algapi.c
index d2ccc1289f92..2a2a7b6a00d0 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -387,11 +387,13 @@ void crypto_alg_tested(const char *name, int err)
crypto_alg_finish_registration(alg, &list);
complete:
+ list_del_init(&test->alg.cra_list);
complete_all(&test->completion);
unlock:
up_write(&crypto_alg_sem);
+ crypto_alg_put(&test->alg);
crypto_remove_final(&list);
}
EXPORT_SYMBOL_GPL(crypto_alg_tested);
@@ -412,7 +414,6 @@ int crypto_register_alg(struct crypto_alg *alg)
{
struct crypto_larval *larval;
LIST_HEAD(algs_to_put);
- bool test_started = false;
int err;
alg->cra_flags &= ~CRYPTO_ALG_DEAD;
@@ -423,15 +424,16 @@ int crypto_register_alg(struct crypto_alg *alg)
down_write(&crypto_alg_sem);
larval = __crypto_register_alg(alg, &algs_to_put);
if (!IS_ERR_OR_NULL(larval)) {
- test_started = crypto_boot_test_finished();
+ bool test_started = crypto_boot_test_finished();
+
larval->test_started = test_started;
+ if (test_started)
+ crypto_schedule_test(larval);
}
up_write(&crypto_alg_sem);
if (IS_ERR(larval))
return PTR_ERR(larval);
- if (test_started)
- crypto_wait_for_test(larval);
crypto_remove_final(&algs_to_put);
return 0;
}
@@ -646,8 +648,10 @@ int crypto_register_instance(struct crypto_template *tmpl,
larval = __crypto_register_alg(&inst->alg, &algs_to_put);
if (IS_ERR(larval))
goto unlock;
- else if (larval)
+ else if (larval) {
larval->test_started = true;
+ crypto_schedule_test(larval);
+ }
hlist_add_head(&inst->list, &tmpl->instances);
inst->tmpl = tmpl;
@@ -657,8 +661,6 @@ int crypto_register_instance(struct crypto_template *tmpl,
if (IS_ERR(larval))
return PTR_ERR(larval);
- if (larval)
- crypto_wait_for_test(larval);
crypto_remove_final(&algs_to_put);
return 0;
}
@@ -1042,6 +1044,7 @@ static void __init crypto_start_tests(void)
l->test_started = true;
larval = l;
+ crypto_schedule_test(larval);
break;
}
@@ -1049,8 +1052,6 @@ static void __init crypto_start_tests(void)
if (!larval)
break;
-
- crypto_wait_for_test(larval);
}
set_crypto_boot_test_finished();
diff --git a/crypto/api.c b/crypto/api.c
index ffb81aa32725..bbe29d438815 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -154,32 +154,31 @@ static struct crypto_alg *crypto_larval_add(const char *name, u32 type,
return alg;
}
-void crypto_larval_kill(struct crypto_alg *alg)
+static void crypto_larval_kill(struct crypto_larval *larval)
{
- struct crypto_larval *larval = (void *)alg;
+ bool unlinked;
down_write(&crypto_alg_sem);
- list_del(&alg->cra_list);
+ unlinked = list_empty(&larval->alg.cra_list);
+ if (!unlinked)
+ list_del_init(&larval->alg.cra_list);
up_write(&crypto_alg_sem);
- complete_all(&larval->completion);
- crypto_alg_put(alg);
-}
-EXPORT_SYMBOL_GPL(crypto_larval_kill);
-void crypto_wait_for_test(struct crypto_larval *larval)
+ if (unlinked)
+ return;
+
+ complete_all(&larval->completion);
+ crypto_alg_put(&larval->alg);
+}
+
+void crypto_schedule_test(struct crypto_larval *larval)
{
int err;
err = crypto_probing_notify(CRYPTO_MSG_ALG_REGISTER, larval->adult);
- if (WARN_ON_ONCE(err != NOTIFY_STOP))
- goto out;
-
- err = wait_for_completion_killable(&larval->completion);
- WARN_ON(err);
-out:
- crypto_larval_kill(&larval->alg);
+ WARN_ON_ONCE(err != NOTIFY_STOP);
}
-EXPORT_SYMBOL_GPL(crypto_wait_for_test);
+EXPORT_SYMBOL_GPL(crypto_schedule_test);
static void crypto_start_test(struct crypto_larval *larval)
{
@@ -198,7 +197,7 @@ static void crypto_start_test(struct crypto_larval *larval)
larval->test_started = true;
up_write(&crypto_alg_sem);
- crypto_wait_for_test(larval);
+ crypto_schedule_test(larval);
}
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)
alg = larval->adult;
if (time_left < 0)
alg = ERR_PTR(-EINTR);
- else if (!time_left)
+ else if (!time_left) {
+ if (crypto_is_test_larval(larval))
+ crypto_larval_kill(larval);
alg = ERR_PTR(-ETIMEDOUT);
- else if (!alg) {
+ } else if (!alg) {
u32 type;
u32 mask;
@@ -355,7 +356,7 @@ struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
crypto_mod_put(larval);
alg = ERR_PTR(-ENOENT);
}
- crypto_larval_kill(larval);
+ crypto_larval_kill(container_of(larval, struct crypto_larval, alg));
return alg;
}
EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup);
diff --git a/crypto/internal.h b/crypto/internal.h
index aee31319be2e..711a6a5bfa2b 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -113,8 +113,7 @@ struct crypto_alg *crypto_mod_get(struct crypto_alg *alg);
struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask);
struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask);
-void crypto_larval_kill(struct crypto_alg *alg);
-void crypto_wait_for_test(struct crypto_larval *larval);
+void crypto_schedule_test(struct crypto_larval *larval);
void crypto_alg_tested(const char *name, int err);
void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
--
2.39.2
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related [flat|nested] 35+ messages in thread* Re: [PATCH 2/3] crypto: api - Do not wait for tests during registration
2024-08-10 2:42 ` [PATCH 2/3] crypto: api - Do not wait for tests during registration Herbert Xu
@ 2024-08-11 13:30 ` Dan Carpenter
2024-08-12 10:33 ` Herbert Xu
0 siblings, 1 reply; 35+ messages in thread
From: Dan Carpenter @ 2024-08-11 13:30 UTC (permalink / raw)
To: oe-kbuild, Herbert Xu, Linus Torvalds
Cc: lkp, oe-kbuild-all, LKML, Russell King (Oracle),
Horia Geantă, Ard Biesheuvel, linux-crypto
Hi Herbert,
kernel test robot noticed the following build warnings:
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Herbert-Xu/crypto-api-Do-not-wait-for-tests-during-registration/20240810-160343
base: https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master
patch link: https://lore.kernel.org/r/ZrbTfOViUr3S4V7X%40gondor.apana.org.au
patch subject: [PATCH 2/3] crypto: api - Do not wait for tests during registration
config: x86_64-randconfig-161-20240811 (https://download.01.org/0day-ci/archive/20240811/202408110413.vKk2q3qN-lkp@intel.com/config)
compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
| Closes: https://lore.kernel.org/r/202408110413.vKk2q3qN-lkp@intel.com/
smatch warnings:
crypto/algapi.c:396 crypto_alg_tested() error: uninitialized symbol 'test'.
vim +/test +396 crypto/algapi.c
73d3864a4823ab Herbert Xu 2008-08-03 350 void crypto_alg_tested(const char *name, int err)
73d3864a4823ab Herbert Xu 2008-08-03 351 {
73d3864a4823ab Herbert Xu 2008-08-03 352 struct crypto_larval *test;
73d3864a4823ab Herbert Xu 2008-08-03 353 struct crypto_alg *alg;
73d3864a4823ab Herbert Xu 2008-08-03 354 struct crypto_alg *q;
73d3864a4823ab Herbert Xu 2008-08-03 355 LIST_HEAD(list);
73d3864a4823ab Herbert Xu 2008-08-03 356
73d3864a4823ab Herbert Xu 2008-08-03 357 down_write(&crypto_alg_sem);
73d3864a4823ab Herbert Xu 2008-08-03 358 list_for_each_entry(q, &crypto_alg_list, cra_list) {
b8e15992b420d0 Herbert Xu 2009-01-28 359 if (crypto_is_moribund(q) || !crypto_is_larval(q))
73d3864a4823ab Herbert Xu 2008-08-03 360 continue;
Is it possible for everything to be moribund or larval?
73d3864a4823ab Herbert Xu 2008-08-03 361
73d3864a4823ab Herbert Xu 2008-08-03 362 test = (struct crypto_larval *)q;
73d3864a4823ab Herbert Xu 2008-08-03 363
73d3864a4823ab Herbert Xu 2008-08-03 364 if (!strcmp(q->cra_driver_name, name))
73d3864a4823ab Herbert Xu 2008-08-03 365 goto found;
73d3864a4823ab Herbert Xu 2008-08-03 366 }
73d3864a4823ab Herbert Xu 2008-08-03 367
c72358571aaadf Karim Eshapa 2017-05-13 368 pr_err("alg: Unexpected test result for %s: %d\n", name, err);
73d3864a4823ab Herbert Xu 2008-08-03 369 goto unlock;
This calling crypto_alg_put() on the last item in the list seems wrong either
way.
73d3864a4823ab Herbert Xu 2008-08-03 370
73d3864a4823ab Herbert Xu 2008-08-03 371 found:
b8e15992b420d0 Herbert Xu 2009-01-28 372 q->cra_flags |= CRYPTO_ALG_DEAD;
73d3864a4823ab Herbert Xu 2008-08-03 373 alg = test->adult;
d6097b8d5d55f2 Nicolai Stange 2022-02-21 374
d6097b8d5d55f2 Nicolai Stange 2022-02-21 375 if (list_empty(&alg->cra_list))
73d3864a4823ab Herbert Xu 2008-08-03 376 goto complete;
73d3864a4823ab Herbert Xu 2008-08-03 377
d6097b8d5d55f2 Nicolai Stange 2022-02-21 378 if (err == -ECANCELED)
d6097b8d5d55f2 Nicolai Stange 2022-02-21 379 alg->cra_flags |= CRYPTO_ALG_FIPS_INTERNAL;
d6097b8d5d55f2 Nicolai Stange 2022-02-21 380 else if (err)
73d3864a4823ab Herbert Xu 2008-08-03 381 goto complete;
d6097b8d5d55f2 Nicolai Stange 2022-02-21 382 else
d6097b8d5d55f2 Nicolai Stange 2022-02-21 383 alg->cra_flags &= ~CRYPTO_ALG_FIPS_INTERNAL;
73d3864a4823ab Herbert Xu 2008-08-03 384
73d3864a4823ab Herbert Xu 2008-08-03 385 alg->cra_flags |= CRYPTO_ALG_TESTED;
73d3864a4823ab Herbert Xu 2008-08-03 386
103961609b0935 Herbert Xu 2024-08-10 387 crypto_alg_finish_registration(alg, &list);
cce9e06d100df1 Herbert Xu 2006-08-21 388
73d3864a4823ab Herbert Xu 2008-08-03 389 complete:
862e4618d9321e Herbert Xu 2024-08-10 390 list_del_init(&test->alg.cra_list);
73d3864a4823ab Herbert Xu 2008-08-03 391 complete_all(&test->completion);
2825982d9d66eb Herbert Xu 2006-08-06 392
73d3864a4823ab Herbert Xu 2008-08-03 393 unlock:
73d3864a4823ab Herbert Xu 2008-08-03 394 up_write(&crypto_alg_sem);
2825982d9d66eb Herbert Xu 2006-08-06 395
862e4618d9321e Herbert Xu 2024-08-10 @396 crypto_alg_put(&test->alg);
^^^^
73d3864a4823ab Herbert Xu 2008-08-03 397 crypto_remove_final(&list);
cce9e06d100df1 Herbert Xu 2006-08-21 398 }
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 35+ messages in thread* Re: [PATCH 2/3] crypto: api - Do not wait for tests during registration
2024-08-11 13:30 ` Dan Carpenter
@ 2024-08-12 10:33 ` Herbert Xu
2024-08-12 10:34 ` [v2 PATCH 1/3] crypto: api - Remove instance larval fulfilment Herbert Xu
0 siblings, 1 reply; 35+ messages in thread
From: Herbert Xu @ 2024-08-12 10:33 UTC (permalink / raw)
To: Dan Carpenter
Cc: oe-kbuild, Linus Torvalds, lkp, oe-kbuild-all, LKML,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
linux-crypto
On Sun, Aug 11, 2024 at 04:30:10PM +0300, Dan Carpenter wrote:
>
> c72358571aaadf Karim Eshapa 2017-05-13 368 pr_err("alg: Unexpected test result for %s: %d\n", name, err);
> 73d3864a4823ab Herbert Xu 2008-08-03 369 goto unlock;
>
> This calling crypto_alg_put() on the last item in the list seems wrong either
> way.
Indeed. This should just return.
Thanks,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 35+ messages in thread* [v2 PATCH 1/3] crypto: api - Remove instance larval fulfilment
2024-08-12 10:33 ` Herbert Xu
@ 2024-08-12 10:34 ` Herbert Xu
2024-08-12 10:35 ` [v2 PATCH 2/3] crypto: api - Do not wait for tests during registration Herbert Xu
0 siblings, 1 reply; 35+ messages in thread
From: Herbert Xu @ 2024-08-12 10:34 UTC (permalink / raw)
To: Dan Carpenter
Cc: oe-kbuild, Linus Torvalds, lkp, oe-kbuild-all, LKML,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
linux-crypto
In order to allow testing to complete asynchronously after the
registration process, instance larvals need to complete prior
to having a test result. Support this by redoing the lookup for
instance larvals after completion. This should locate the pending
test larval and then repeat the wait on that (if it is still pending).
As the lookup is now repeated there is no longer any need to compute
the fulfilment status and all that code can be removed.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/algapi.c | 48 +++---------------------------------------------
crypto/api.c | 23 +++++++++++++++++++----
2 files changed, 22 insertions(+), 49 deletions(-)
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 122cd910c4e1..d2ccc1289f92 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -235,7 +235,6 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
EXPORT_SYMBOL_GPL(crypto_remove_spawns);
static void crypto_alg_finish_registration(struct crypto_alg *alg,
- bool fulfill_requests,
struct list_head *algs_to_put)
{
struct crypto_alg *q;
@@ -247,30 +246,8 @@ static void crypto_alg_finish_registration(struct crypto_alg *alg,
if (crypto_is_moribund(q))
continue;
- if (crypto_is_larval(q)) {
- struct crypto_larval *larval = (void *)q;
-
- /*
- * Check to see if either our generic name or
- * specific name can satisfy the name requested
- * by the larval entry 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 (fulfill_requests && crypto_mod_get(alg))
- larval->adult = alg;
- else
- larval->adult = ERR_PTR(-EAGAIN);
-
+ if (crypto_is_larval(q))
continue;
- }
if (strcmp(alg->cra_name, q->cra_name))
continue;
@@ -359,7 +336,7 @@ __crypto_register_alg(struct crypto_alg *alg, struct list_head *algs_to_put)
list_add(&larval->alg.cra_list, &crypto_alg_list);
} else {
alg->cra_flags |= CRYPTO_ALG_TESTED;
- crypto_alg_finish_registration(alg, true, algs_to_put);
+ crypto_alg_finish_registration(alg, algs_to_put);
}
out:
@@ -376,7 +353,6 @@ 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) {
@@ -408,25 +384,7 @@ void crypto_alg_tested(const char *name, int err)
alg->cra_flags |= CRYPTO_ALG_TESTED;
- /*
- * If a higher-priority implementation of the same algorithm is
- * currently being tested, then don't fulfill request larvals.
- */
- 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;
- }
- }
-
- crypto_alg_finish_registration(alg, best, &list);
+ crypto_alg_finish_registration(alg, &list);
complete:
complete_all(&test->completion);
diff --git a/crypto/api.c b/crypto/api.c
index 22556907b3bc..ffb81aa32725 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -37,6 +37,8 @@ DEFINE_STATIC_KEY_FALSE(__crypto_boot_test_finished);
#endif
static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg);
+static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type,
+ u32 mask);
struct crypto_alg *crypto_mod_get(struct crypto_alg *alg)
{
@@ -201,9 +203,12 @@ static void crypto_start_test(struct crypto_larval *larval)
static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
{
- struct crypto_larval *larval = (void *)alg;
+ struct crypto_larval *larval;
long time_left;
+again:
+ larval = container_of(alg, struct crypto_larval, alg);
+
if (!crypto_boot_test_finished())
crypto_start_test(larval);
@@ -215,9 +220,16 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
alg = ERR_PTR(-EINTR);
else if (!time_left)
alg = ERR_PTR(-ETIMEDOUT);
- else if (!alg)
- alg = ERR_PTR(-ENOENT);
- else if (IS_ERR(alg))
+ else if (!alg) {
+ u32 type;
+ u32 mask;
+
+ alg = &larval->alg;
+ type = alg->cra_flags & ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
+ mask = larval->mask;
+ alg = crypto_alg_lookup(alg->cra_name, type, mask) ?:
+ ERR_PTR(-ENOENT);
+ } else if (IS_ERR(alg))
;
else if (crypto_is_test_larval(larval) &&
!(alg->cra_flags & CRYPTO_ALG_TESTED))
@@ -228,6 +240,9 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
alg = ERR_PTR(-EAGAIN);
crypto_mod_put(&larval->alg);
+ if (!IS_ERR(alg) && crypto_is_larval(alg))
+ goto again;
+
return alg;
}
--
2.39.2
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related [flat|nested] 35+ messages in thread* [v2 PATCH 2/3] crypto: api - Do not wait for tests during registration
2024-08-12 10:34 ` [v2 PATCH 1/3] crypto: api - Remove instance larval fulfilment Herbert Xu
@ 2024-08-12 10:35 ` Herbert Xu
2024-08-12 10:36 ` [v2 PATCH 3/3] crypto: simd - Do not call crypto_alloc_tfm " Herbert Xu
0 siblings, 1 reply; 35+ messages in thread
From: Herbert Xu @ 2024-08-12 10:35 UTC (permalink / raw)
To: Dan Carpenter
Cc: oe-kbuild, Linus Torvalds, lkp, oe-kbuild-all, LKML,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
linux-crypto
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>
---
crypto/algapi.c | 23 ++++++++++++-----------
crypto/api.c | 41 +++++++++++++++++++++--------------------
crypto/internal.h | 3 +--
3 files changed, 34 insertions(+), 33 deletions(-)
diff --git a/crypto/algapi.c b/crypto/algapi.c
index d2ccc1289f92..74e2261c184c 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -366,7 +366,8 @@ void crypto_alg_tested(const char *name, int err)
}
pr_err("alg: Unexpected test result for %s: %d\n", name, err);
- goto unlock;
+ up_write(&crypto_alg_sem);
+ return;
found:
q->cra_flags |= CRYPTO_ALG_DEAD;
@@ -387,11 +388,12 @@ void crypto_alg_tested(const char *name, int err)
crypto_alg_finish_registration(alg, &list);
complete:
+ list_del_init(&test->alg.cra_list);
complete_all(&test->completion);
-unlock:
up_write(&crypto_alg_sem);
+ crypto_alg_put(&test->alg);
crypto_remove_final(&list);
}
EXPORT_SYMBOL_GPL(crypto_alg_tested);
@@ -412,7 +414,6 @@ int crypto_register_alg(struct crypto_alg *alg)
{
struct crypto_larval *larval;
LIST_HEAD(algs_to_put);
- bool test_started = false;
int err;
alg->cra_flags &= ~CRYPTO_ALG_DEAD;
@@ -423,15 +424,16 @@ int crypto_register_alg(struct crypto_alg *alg)
down_write(&crypto_alg_sem);
larval = __crypto_register_alg(alg, &algs_to_put);
if (!IS_ERR_OR_NULL(larval)) {
- test_started = crypto_boot_test_finished();
+ bool test_started = crypto_boot_test_finished();
+
larval->test_started = test_started;
+ if (test_started)
+ crypto_schedule_test(larval);
}
up_write(&crypto_alg_sem);
if (IS_ERR(larval))
return PTR_ERR(larval);
- if (test_started)
- crypto_wait_for_test(larval);
crypto_remove_final(&algs_to_put);
return 0;
}
@@ -646,8 +648,10 @@ int crypto_register_instance(struct crypto_template *tmpl,
larval = __crypto_register_alg(&inst->alg, &algs_to_put);
if (IS_ERR(larval))
goto unlock;
- else if (larval)
+ else if (larval) {
larval->test_started = true;
+ crypto_schedule_test(larval);
+ }
hlist_add_head(&inst->list, &tmpl->instances);
inst->tmpl = tmpl;
@@ -657,8 +661,6 @@ int crypto_register_instance(struct crypto_template *tmpl,
if (IS_ERR(larval))
return PTR_ERR(larval);
- if (larval)
- crypto_wait_for_test(larval);
crypto_remove_final(&algs_to_put);
return 0;
}
@@ -1042,6 +1044,7 @@ static void __init crypto_start_tests(void)
l->test_started = true;
larval = l;
+ crypto_schedule_test(larval);
break;
}
@@ -1049,8 +1052,6 @@ static void __init crypto_start_tests(void)
if (!larval)
break;
-
- crypto_wait_for_test(larval);
}
set_crypto_boot_test_finished();
diff --git a/crypto/api.c b/crypto/api.c
index ffb81aa32725..bbe29d438815 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -154,32 +154,31 @@ static struct crypto_alg *crypto_larval_add(const char *name, u32 type,
return alg;
}
-void crypto_larval_kill(struct crypto_alg *alg)
+static void crypto_larval_kill(struct crypto_larval *larval)
{
- struct crypto_larval *larval = (void *)alg;
+ bool unlinked;
down_write(&crypto_alg_sem);
- list_del(&alg->cra_list);
+ unlinked = list_empty(&larval->alg.cra_list);
+ if (!unlinked)
+ list_del_init(&larval->alg.cra_list);
up_write(&crypto_alg_sem);
- complete_all(&larval->completion);
- crypto_alg_put(alg);
-}
-EXPORT_SYMBOL_GPL(crypto_larval_kill);
-void crypto_wait_for_test(struct crypto_larval *larval)
+ if (unlinked)
+ return;
+
+ complete_all(&larval->completion);
+ crypto_alg_put(&larval->alg);
+}
+
+void crypto_schedule_test(struct crypto_larval *larval)
{
int err;
err = crypto_probing_notify(CRYPTO_MSG_ALG_REGISTER, larval->adult);
- if (WARN_ON_ONCE(err != NOTIFY_STOP))
- goto out;
-
- err = wait_for_completion_killable(&larval->completion);
- WARN_ON(err);
-out:
- crypto_larval_kill(&larval->alg);
+ WARN_ON_ONCE(err != NOTIFY_STOP);
}
-EXPORT_SYMBOL_GPL(crypto_wait_for_test);
+EXPORT_SYMBOL_GPL(crypto_schedule_test);
static void crypto_start_test(struct crypto_larval *larval)
{
@@ -198,7 +197,7 @@ static void crypto_start_test(struct crypto_larval *larval)
larval->test_started = true;
up_write(&crypto_alg_sem);
- crypto_wait_for_test(larval);
+ crypto_schedule_test(larval);
}
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)
alg = larval->adult;
if (time_left < 0)
alg = ERR_PTR(-EINTR);
- else if (!time_left)
+ else if (!time_left) {
+ if (crypto_is_test_larval(larval))
+ crypto_larval_kill(larval);
alg = ERR_PTR(-ETIMEDOUT);
- else if (!alg) {
+ } else if (!alg) {
u32 type;
u32 mask;
@@ -355,7 +356,7 @@ struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
crypto_mod_put(larval);
alg = ERR_PTR(-ENOENT);
}
- crypto_larval_kill(larval);
+ crypto_larval_kill(container_of(larval, struct crypto_larval, alg));
return alg;
}
EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup);
diff --git a/crypto/internal.h b/crypto/internal.h
index aee31319be2e..711a6a5bfa2b 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -113,8 +113,7 @@ struct crypto_alg *crypto_mod_get(struct crypto_alg *alg);
struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask);
struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask);
-void crypto_larval_kill(struct crypto_alg *alg);
-void crypto_wait_for_test(struct crypto_larval *larval);
+void crypto_schedule_test(struct crypto_larval *larval);
void crypto_alg_tested(const char *name, int err);
void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
--
2.39.2
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related [flat|nested] 35+ messages in thread* [v2 PATCH 3/3] crypto: simd - Do not call crypto_alloc_tfm during registration
2024-08-12 10:35 ` [v2 PATCH 2/3] crypto: api - Do not wait for tests during registration Herbert Xu
@ 2024-08-12 10:36 ` Herbert Xu
0 siblings, 0 replies; 35+ messages in thread
From: Herbert Xu @ 2024-08-12 10:36 UTC (permalink / raw)
To: Dan Carpenter
Cc: oe-kbuild, Linus Torvalds, lkp, oe-kbuild-all, LKML,
Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
linux-crypto
Algorithm registration is usually carried out during module init,
where as little work as possible should be carried out. The SIMD
code violated this rule by allocating a tfm, this then triggers a
full test of the algorithm which may dead-lock in certain cases.
SIMD is only allocating the tfm to get at the alg object, which is
in fact already available as it is what we are registering. Use
that directly and remove the crypto_alloc_tfm call.
Also remove some obsolete and unused SIMD API.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
arch/arm/crypto/aes-ce-glue.c | 2 +-
arch/arm/crypto/aes-neonbs-glue.c | 2 +-
crypto/simd.c | 76 ++++++-------------------------
include/crypto/internal/simd.h | 12 +----
4 files changed, 19 insertions(+), 73 deletions(-)
diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c
index b668c97663ec..f5b66f4cf45d 100644
--- a/arch/arm/crypto/aes-ce-glue.c
+++ b/arch/arm/crypto/aes-ce-glue.c
@@ -711,7 +711,7 @@ static int __init aes_init(void)
algname = aes_algs[i].base.cra_name + 2;
drvname = aes_algs[i].base.cra_driver_name + 2;
basename = aes_algs[i].base.cra_driver_name;
- simd = simd_skcipher_create_compat(algname, drvname, basename);
+ simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename);
err = PTR_ERR(simd);
if (IS_ERR(simd))
goto unregister_simds;
diff --git a/arch/arm/crypto/aes-neonbs-glue.c b/arch/arm/crypto/aes-neonbs-glue.c
index 201eb35dde37..735a2441ad48 100644
--- a/arch/arm/crypto/aes-neonbs-glue.c
+++ b/arch/arm/crypto/aes-neonbs-glue.c
@@ -540,7 +540,7 @@ static int __init aes_init(void)
algname = aes_algs[i].base.cra_name + 2;
drvname = aes_algs[i].base.cra_driver_name + 2;
basename = aes_algs[i].base.cra_driver_name;
- simd = simd_skcipher_create_compat(algname, drvname, basename);
+ simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename);
err = PTR_ERR(simd);
if (IS_ERR(simd))
goto unregister_simds;
diff --git a/crypto/simd.c b/crypto/simd.c
index 2aa4f72e224f..b07721d1f3f6 100644
--- a/crypto/simd.c
+++ b/crypto/simd.c
@@ -136,27 +136,19 @@ static int simd_skcipher_init(struct crypto_skcipher *tfm)
return 0;
}
-struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname,
+struct simd_skcipher_alg *simd_skcipher_create_compat(struct skcipher_alg *ialg,
+ const char *algname,
const char *drvname,
const char *basename)
{
struct simd_skcipher_alg *salg;
- struct crypto_skcipher *tfm;
- struct skcipher_alg *ialg;
struct skcipher_alg *alg;
int err;
- tfm = crypto_alloc_skcipher(basename, CRYPTO_ALG_INTERNAL,
- CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm))
- return ERR_CAST(tfm);
-
- ialg = crypto_skcipher_alg(tfm);
-
salg = kzalloc(sizeof(*salg), GFP_KERNEL);
if (!salg) {
salg = ERR_PTR(-ENOMEM);
- goto out_put_tfm;
+ goto out;
}
salg->ialg_name = basename;
@@ -195,30 +187,16 @@ struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname,
if (err)
goto out_free_salg;
-out_put_tfm:
- crypto_free_skcipher(tfm);
+out:
return salg;
out_free_salg:
kfree(salg);
salg = ERR_PTR(err);
- goto out_put_tfm;
+ goto out;
}
EXPORT_SYMBOL_GPL(simd_skcipher_create_compat);
-struct simd_skcipher_alg *simd_skcipher_create(const char *algname,
- const char *basename)
-{
- char drvname[CRYPTO_MAX_ALG_NAME];
-
- if (snprintf(drvname, CRYPTO_MAX_ALG_NAME, "simd-%s", basename) >=
- CRYPTO_MAX_ALG_NAME)
- return ERR_PTR(-ENAMETOOLONG);
-
- return simd_skcipher_create_compat(algname, drvname, basename);
-}
-EXPORT_SYMBOL_GPL(simd_skcipher_create);
-
void simd_skcipher_free(struct simd_skcipher_alg *salg)
{
crypto_unregister_skcipher(&salg->alg);
@@ -246,7 +224,7 @@ int simd_register_skciphers_compat(struct skcipher_alg *algs, int count,
algname = algs[i].base.cra_name + 2;
drvname = algs[i].base.cra_driver_name + 2;
basename = algs[i].base.cra_driver_name;
- simd = simd_skcipher_create_compat(algname, drvname, basename);
+ simd = simd_skcipher_create_compat(algs + i, algname, drvname, basename);
err = PTR_ERR(simd);
if (IS_ERR(simd))
goto err_unregister;
@@ -383,27 +361,19 @@ static int simd_aead_init(struct crypto_aead *tfm)
return 0;
}
-struct simd_aead_alg *simd_aead_create_compat(const char *algname,
- const char *drvname,
- const char *basename)
+static struct simd_aead_alg *simd_aead_create_compat(struct aead_alg *ialg,
+ const char *algname,
+ const char *drvname,
+ const char *basename)
{
struct simd_aead_alg *salg;
- struct crypto_aead *tfm;
- struct aead_alg *ialg;
struct aead_alg *alg;
int err;
- tfm = crypto_alloc_aead(basename, CRYPTO_ALG_INTERNAL,
- CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm))
- return ERR_CAST(tfm);
-
- ialg = crypto_aead_alg(tfm);
-
salg = kzalloc(sizeof(*salg), GFP_KERNEL);
if (!salg) {
salg = ERR_PTR(-ENOMEM);
- goto out_put_tfm;
+ goto out;
}
salg->ialg_name = basename;
@@ -442,36 +412,20 @@ struct simd_aead_alg *simd_aead_create_compat(const char *algname,
if (err)
goto out_free_salg;
-out_put_tfm:
- crypto_free_aead(tfm);
+out:
return salg;
out_free_salg:
kfree(salg);
salg = ERR_PTR(err);
- goto out_put_tfm;
+ goto out;
}
-EXPORT_SYMBOL_GPL(simd_aead_create_compat);
-struct simd_aead_alg *simd_aead_create(const char *algname,
- const char *basename)
-{
- char drvname[CRYPTO_MAX_ALG_NAME];
-
- if (snprintf(drvname, CRYPTO_MAX_ALG_NAME, "simd-%s", basename) >=
- CRYPTO_MAX_ALG_NAME)
- return ERR_PTR(-ENAMETOOLONG);
-
- return simd_aead_create_compat(algname, drvname, basename);
-}
-EXPORT_SYMBOL_GPL(simd_aead_create);
-
-void simd_aead_free(struct simd_aead_alg *salg)
+static void simd_aead_free(struct simd_aead_alg *salg)
{
crypto_unregister_aead(&salg->alg);
kfree(salg);
}
-EXPORT_SYMBOL_GPL(simd_aead_free);
int simd_register_aeads_compat(struct aead_alg *algs, int count,
struct simd_aead_alg **simd_algs)
@@ -493,7 +447,7 @@ int simd_register_aeads_compat(struct aead_alg *algs, int count,
algname = algs[i].base.cra_name + 2;
drvname = algs[i].base.cra_driver_name + 2;
basename = algs[i].base.cra_driver_name;
- simd = simd_aead_create_compat(algname, drvname, basename);
+ simd = simd_aead_create_compat(algs + i, algname, drvname, basename);
err = PTR_ERR(simd);
if (IS_ERR(simd))
goto err_unregister;
diff --git a/include/crypto/internal/simd.h b/include/crypto/internal/simd.h
index d2316242a988..be97b97a75dd 100644
--- a/include/crypto/internal/simd.h
+++ b/include/crypto/internal/simd.h
@@ -14,11 +14,10 @@
struct simd_skcipher_alg;
struct skcipher_alg;
-struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname,
+struct simd_skcipher_alg *simd_skcipher_create_compat(struct skcipher_alg *ialg,
+ const char *algname,
const char *drvname,
const char *basename);
-struct simd_skcipher_alg *simd_skcipher_create(const char *algname,
- const char *basename);
void simd_skcipher_free(struct simd_skcipher_alg *alg);
int simd_register_skciphers_compat(struct skcipher_alg *algs, int count,
@@ -32,13 +31,6 @@ void simd_unregister_skciphers(struct skcipher_alg *algs, int count,
struct simd_aead_alg;
struct aead_alg;
-struct simd_aead_alg *simd_aead_create_compat(const char *algname,
- const char *drvname,
- const char *basename);
-struct simd_aead_alg *simd_aead_create(const char *algname,
- const char *basename);
-void simd_aead_free(struct simd_aead_alg *alg);
-
int simd_register_aeads_compat(struct aead_alg *algs, int count,
struct simd_aead_alg **simd_algs);
--
2.39.2
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 3/3] crypto: simd - Do not call crypto_alloc_tfm during registration
2024-08-09 4:40 ` Herbert Xu
` (3 preceding siblings ...)
2024-08-10 2:42 ` [PATCH 2/3] crypto: api - Do not wait for tests during registration Herbert Xu
@ 2024-08-10 2:43 ` Herbert Xu
4 siblings, 0 replies; 35+ messages in thread
From: Herbert Xu @ 2024-08-10 2:43 UTC (permalink / raw)
To: Linus Torvalds
Cc: Russell King (Oracle), Horia Geantă, Ard Biesheuvel,
David S. Miller, linux-crypto
Algorithm registration is usually carried out during module init,
where as little work as possible should be carried out. The SIMD
code violated this rule by allocating a tfm, this then triggers a
full test of the algorithm which may dead-lock in certain cases.
SIMD is only allocating the tfm to get at the alg object, which is
in fact already available as it is what we are registering. Use
that directly and remove the crypto_alloc_tfm call.
Also remove some obsolete and unused SIMD API.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
arch/arm/crypto/aes-ce-glue.c | 2 +-
arch/arm/crypto/aes-neonbs-glue.c | 2 +-
crypto/simd.c | 76 ++++++-------------------------
include/crypto/internal/simd.h | 12 +----
4 files changed, 19 insertions(+), 73 deletions(-)
diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c
index b668c97663ec..f5b66f4cf45d 100644
--- a/arch/arm/crypto/aes-ce-glue.c
+++ b/arch/arm/crypto/aes-ce-glue.c
@@ -711,7 +711,7 @@ static int __init aes_init(void)
algname = aes_algs[i].base.cra_name + 2;
drvname = aes_algs[i].base.cra_driver_name + 2;
basename = aes_algs[i].base.cra_driver_name;
- simd = simd_skcipher_create_compat(algname, drvname, basename);
+ simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename);
err = PTR_ERR(simd);
if (IS_ERR(simd))
goto unregister_simds;
diff --git a/arch/arm/crypto/aes-neonbs-glue.c b/arch/arm/crypto/aes-neonbs-glue.c
index 201eb35dde37..735a2441ad48 100644
--- a/arch/arm/crypto/aes-neonbs-glue.c
+++ b/arch/arm/crypto/aes-neonbs-glue.c
@@ -540,7 +540,7 @@ static int __init aes_init(void)
algname = aes_algs[i].base.cra_name + 2;
drvname = aes_algs[i].base.cra_driver_name + 2;
basename = aes_algs[i].base.cra_driver_name;
- simd = simd_skcipher_create_compat(algname, drvname, basename);
+ simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename);
err = PTR_ERR(simd);
if (IS_ERR(simd))
goto unregister_simds;
diff --git a/crypto/simd.c b/crypto/simd.c
index 2aa4f72e224f..b07721d1f3f6 100644
--- a/crypto/simd.c
+++ b/crypto/simd.c
@@ -136,27 +136,19 @@ static int simd_skcipher_init(struct crypto_skcipher *tfm)
return 0;
}
-struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname,
+struct simd_skcipher_alg *simd_skcipher_create_compat(struct skcipher_alg *ialg,
+ const char *algname,
const char *drvname,
const char *basename)
{
struct simd_skcipher_alg *salg;
- struct crypto_skcipher *tfm;
- struct skcipher_alg *ialg;
struct skcipher_alg *alg;
int err;
- tfm = crypto_alloc_skcipher(basename, CRYPTO_ALG_INTERNAL,
- CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm))
- return ERR_CAST(tfm);
-
- ialg = crypto_skcipher_alg(tfm);
-
salg = kzalloc(sizeof(*salg), GFP_KERNEL);
if (!salg) {
salg = ERR_PTR(-ENOMEM);
- goto out_put_tfm;
+ goto out;
}
salg->ialg_name = basename;
@@ -195,30 +187,16 @@ struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname,
if (err)
goto out_free_salg;
-out_put_tfm:
- crypto_free_skcipher(tfm);
+out:
return salg;
out_free_salg:
kfree(salg);
salg = ERR_PTR(err);
- goto out_put_tfm;
+ goto out;
}
EXPORT_SYMBOL_GPL(simd_skcipher_create_compat);
-struct simd_skcipher_alg *simd_skcipher_create(const char *algname,
- const char *basename)
-{
- char drvname[CRYPTO_MAX_ALG_NAME];
-
- if (snprintf(drvname, CRYPTO_MAX_ALG_NAME, "simd-%s", basename) >=
- CRYPTO_MAX_ALG_NAME)
- return ERR_PTR(-ENAMETOOLONG);
-
- return simd_skcipher_create_compat(algname, drvname, basename);
-}
-EXPORT_SYMBOL_GPL(simd_skcipher_create);
-
void simd_skcipher_free(struct simd_skcipher_alg *salg)
{
crypto_unregister_skcipher(&salg->alg);
@@ -246,7 +224,7 @@ int simd_register_skciphers_compat(struct skcipher_alg *algs, int count,
algname = algs[i].base.cra_name + 2;
drvname = algs[i].base.cra_driver_name + 2;
basename = algs[i].base.cra_driver_name;
- simd = simd_skcipher_create_compat(algname, drvname, basename);
+ simd = simd_skcipher_create_compat(algs + i, algname, drvname, basename);
err = PTR_ERR(simd);
if (IS_ERR(simd))
goto err_unregister;
@@ -383,27 +361,19 @@ static int simd_aead_init(struct crypto_aead *tfm)
return 0;
}
-struct simd_aead_alg *simd_aead_create_compat(const char *algname,
- const char *drvname,
- const char *basename)
+static struct simd_aead_alg *simd_aead_create_compat(struct aead_alg *ialg,
+ const char *algname,
+ const char *drvname,
+ const char *basename)
{
struct simd_aead_alg *salg;
- struct crypto_aead *tfm;
- struct aead_alg *ialg;
struct aead_alg *alg;
int err;
- tfm = crypto_alloc_aead(basename, CRYPTO_ALG_INTERNAL,
- CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm))
- return ERR_CAST(tfm);
-
- ialg = crypto_aead_alg(tfm);
-
salg = kzalloc(sizeof(*salg), GFP_KERNEL);
if (!salg) {
salg = ERR_PTR(-ENOMEM);
- goto out_put_tfm;
+ goto out;
}
salg->ialg_name = basename;
@@ -442,36 +412,20 @@ struct simd_aead_alg *simd_aead_create_compat(const char *algname,
if (err)
goto out_free_salg;
-out_put_tfm:
- crypto_free_aead(tfm);
+out:
return salg;
out_free_salg:
kfree(salg);
salg = ERR_PTR(err);
- goto out_put_tfm;
+ goto out;
}
-EXPORT_SYMBOL_GPL(simd_aead_create_compat);
-struct simd_aead_alg *simd_aead_create(const char *algname,
- const char *basename)
-{
- char drvname[CRYPTO_MAX_ALG_NAME];
-
- if (snprintf(drvname, CRYPTO_MAX_ALG_NAME, "simd-%s", basename) >=
- CRYPTO_MAX_ALG_NAME)
- return ERR_PTR(-ENAMETOOLONG);
-
- return simd_aead_create_compat(algname, drvname, basename);
-}
-EXPORT_SYMBOL_GPL(simd_aead_create);
-
-void simd_aead_free(struct simd_aead_alg *salg)
+static void simd_aead_free(struct simd_aead_alg *salg)
{
crypto_unregister_aead(&salg->alg);
kfree(salg);
}
-EXPORT_SYMBOL_GPL(simd_aead_free);
int simd_register_aeads_compat(struct aead_alg *algs, int count,
struct simd_aead_alg **simd_algs)
@@ -493,7 +447,7 @@ int simd_register_aeads_compat(struct aead_alg *algs, int count,
algname = algs[i].base.cra_name + 2;
drvname = algs[i].base.cra_driver_name + 2;
basename = algs[i].base.cra_driver_name;
- simd = simd_aead_create_compat(algname, drvname, basename);
+ simd = simd_aead_create_compat(algs + i, algname, drvname, basename);
err = PTR_ERR(simd);
if (IS_ERR(simd))
goto err_unregister;
diff --git a/include/crypto/internal/simd.h b/include/crypto/internal/simd.h
index d2316242a988..be97b97a75dd 100644
--- a/include/crypto/internal/simd.h
+++ b/include/crypto/internal/simd.h
@@ -14,11 +14,10 @@
struct simd_skcipher_alg;
struct skcipher_alg;
-struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname,
+struct simd_skcipher_alg *simd_skcipher_create_compat(struct skcipher_alg *ialg,
+ const char *algname,
const char *drvname,
const char *basename);
-struct simd_skcipher_alg *simd_skcipher_create(const char *algname,
- const char *basename);
void simd_skcipher_free(struct simd_skcipher_alg *alg);
int simd_register_skciphers_compat(struct skcipher_alg *algs, int count,
@@ -32,13 +31,6 @@ void simd_unregister_skciphers(struct skcipher_alg *algs, int count,
struct simd_aead_alg;
struct aead_alg;
-struct simd_aead_alg *simd_aead_create_compat(const char *algname,
- const char *drvname,
- const char *basename);
-struct simd_aead_alg *simd_aead_create(const char *algname,
- const char *basename);
-void simd_aead_free(struct simd_aead_alg *alg);
-
int simd_register_aeads_compat(struct aead_alg *algs, int count,
struct simd_aead_alg **simd_algs);
--
2.39.2
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related [flat|nested] 35+ messages in thread