linux-crypto.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eric Biggers <ebiggers@kernel.org>
To: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Linux Crypto Mailing List <linux-crypto@vger.kernel.org>
Subject: Re: [PATCH 2/2] crypto: api - Do not zap spawn->alg
Date: Fri, 6 Dec 2019 14:50:21 -0800	[thread overview]
Message-ID: <20191206225021.GF246840@gmail.com> (raw)
In-Reply-To: <E1idElt-0001VY-O3@gondobar>

On Fri, Dec 06, 2019 at 10:39:53PM +0800, Herbert Xu wrote:
> Currently when a spawn is removed we will zap its alg field.
> This is racy because the spawn could belong to an unregistered
> instance which may dereference the spawn->alg field.
> 
> This patch fixes this by keeping spawn->alg constant and instead
> adding a new spawn->dead field to indicate that a spawn is going
> away.
> 
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
> ---
> 
>  crypto/algapi.c         |   21 +++++++++++----------
>  include/crypto/algapi.h |    1 +
>  2 files changed, 12 insertions(+), 10 deletions(-)
> 
> diff --git a/crypto/algapi.c b/crypto/algapi.c
> index cc55301beef4..2d0697c4f69c 100644
> --- a/crypto/algapi.c
> +++ b/crypto/algapi.c
> @@ -93,15 +93,16 @@ static struct list_head *crypto_more_spawns(struct crypto_alg *alg,
>  	if (!spawn)
>  		return NULL;
>  
> -	n = list_next_entry(spawn, list);
> +	list_move(&spawn->list, secondary_spawns);
>  
> -	if (spawn->alg && &n->list != stack && !n->alg)
> -		n->alg = (n->list.next == stack) ? alg :
> -			 &list_next_entry(n, list)->inst->alg;
> +	if (list_is_last(&spawn->list, stack))
> +		return top;
>  
> -	list_move(&spawn->list, secondary_spawns);
> +	n = list_next_entry(spawn, list);
> +	if (!spawn->dead)
> +		n->dead = false;
>  
> -	return &n->list == stack ? top : &n->inst->alg.cra_users;
> +	return &n->inst->alg.cra_users;
>  }
>  
>  static void crypto_remove_instance(struct crypto_instance *inst,
> @@ -160,7 +161,7 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
>  			if (&inst->alg == nalg)
>  				break;
>  
> -			spawn->alg = NULL;
> +			spawn->dead = true;
>  			spawns = &inst->alg.cra_users;
>  
>  			/*
> @@ -179,7 +180,7 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
>  					      &secondary_spawns)));
>  
>  	list_for_each_entry_safe(spawn, n, &secondary_spawns, list) {
> -		if (spawn->alg)
> +		if (!spawn->dead)
>  			list_move(&spawn->list, &spawn->alg->cra_users);
>  		else
>  			crypto_remove_instance(spawn->inst, list);
> @@ -669,7 +670,7 @@ EXPORT_SYMBOL_GPL(crypto_grab_spawn);
>  void crypto_drop_spawn(struct crypto_spawn *spawn)
>  {
>  	down_write(&crypto_alg_sem);
> -	if (spawn->alg)
> +	if (!spawn->dead)
>  		list_del(&spawn->list);
>  	up_write(&crypto_alg_sem);
>  }
> @@ -681,7 +682,7 @@ static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn)
>  
>  	down_read(&crypto_alg_sem);
>  	alg = spawn->alg;
> -	if (alg && !crypto_mod_get(alg)) {
> +	if (!spawn->dead && !crypto_mod_get(alg)) {
>  		alg->cra_flags |= CRYPTO_ALG_DYING;
>  		alg = NULL;
>  	}
> diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
> index 5cd846defdd6..771a295ac755 100644
> --- a/include/crypto/algapi.h
> +++ b/include/crypto/algapi.h
> @@ -70,6 +70,7 @@ struct crypto_spawn {
>  	struct crypto_instance *inst;
>  	const struct crypto_type *frontend;
>  	u32 mask;
> +	bool dead;
>  };
>  

This patch causes the below crash.

Also, some comments (e.g. for struct crypto_spawn and crypto_remove_spawns())
would be really helpful to understand what's going on here.

==================================================================
BUG: KASAN: stack-out-of-bounds in crypto_more_spawns crypto/algapi.c:105 [inline]
BUG: KASAN: stack-out-of-bounds in crypto_remove_spawns+0x9cd/0xc30 crypto/algapi.c:179
Read of size 8 at addr ffff88806a1f7d58 by task cryptomgr_test/430

CPU: 2 PID: 430 Comm: cryptomgr_test Not tainted 5.4.0-07583-g2c69d0491b7e2 #5
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0xa0/0xea lib/dump_stack.c:118
 print_address_description.constprop.4+0x21/0x2c0 mm/kasan/report.c:374
 __kasan_report.cold.8+0x7a/0xb5 mm/kasan/report.c:506
 kasan_report+0x12/0x20 mm/kasan/common.c:638
 __asan_report_load8_noabort+0x14/0x20 mm/kasan/generic_report.c:135
 crypto_more_spawns crypto/algapi.c:105 [inline]
 crypto_remove_spawns+0x9cd/0xc30 crypto/algapi.c:179
 crypto_alg_tested+0x493/0x5b0 crypto/algapi.c:357
 cryptomgr_test+0x60/0x80 crypto/algboss.c:225
 kthread+0x331/0x3f0 kernel/kthread.c:255
 ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352

The buggy address belongs to the page:
page:ffffea0001736e08 refcount:0 mapcount:0 mapping:0000000000000000 index:0x0
raw: 0100000000000000 ffffea0001736e10 ffffea0001736e10 0000000000000000
raw: 0000000000000000 0000000000000000 00000000ffffffff
page dumped because: kasan: bad access detected

addr ffff88806a1f7d58 is located in stack of task cryptomgr_test/430 at offset 56 in frame:
 crypto_remove_spawns+0x0/0xc30 crypto/algapi.c:956

this frame has 3 objects:
 [32, 48) 'secondary_spawns'
 [96, 112) 'stack'
 [160, 176) 'top'

Memory state around the buggy address:
 ffff88806a1f7c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ffff88806a1f7c80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff88806a1f7d00: 00 00 00 00 f1 f1 f1 f1 00 00 f2 f2 f2 f2 f2 f2
                                                    ^
 ffff88806a1f7d80: 00 00 f2 f2 f2 f2 f2 f2 00 00 f2 f2 00 00 00 00
 ffff88806a1f7e00: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
==================================================================
Disabling lock debugging due to kernel taint
kasan: CONFIG_KASAN_INLINE enabled
kasan: GPF could be caused by NULL-ptr deref or user memory access
general protection fault: 0000 [#1] SMP KASAN
CPU: 2 PID: 430 Comm: cryptomgr_test Tainted: G    B             5.4.0-07583-g2c69d0491b7e2 #5
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
RIP: 0010:crypto_remove_spawns+0x359/0xc30 crypto/algapi.c:155
Code: 39 c4 0f 84 71 01 00 00 4c 89 e0 48 c1 e8 03 42 80 3c 38 00 0f 85 a7 05 00 00 4d 8b 24 24 49 8d 7c 24 18 48 89 f8 48 c1 e8 03 <42> 80 3c 38 00 0f 85 6b 05 00 0f
RSP: 0000:ffff88806a1f7cc8 EFLAGS: 00010206
RAX: 0000000000000003 RBX: ffff88806a1f7e00 RCX: ffffffff81339704
RDX: 0000000000000000 RSI: 0000000000000004 RDI: 0000000000000018
RBP: ffff88806a1f7e28 R08: fffffbfff06973a5 R09: fffffbfff06973a5
R10: fffffbfff06973a4 R11: ffffffff834b9d23 R12: 0000000000000000
R13: ffff88806a1f7d80 R14: ffff88806a1f7d40 R15: dffffc0000000000
FS:  0000000000000000(0000) GS:ffff88806d900000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000ffffffff CR3: 0000000003213001 CR4: 0000000000760ee0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
PKRU: 55555554
Call Trace:
 crypto_alg_tested+0x493/0x5b0 crypto/algapi.c:357
 cryptomgr_test+0x60/0x80 crypto/algboss.c:225
 kthread+0x331/0x3f0 kernel/kthread.c:255
 ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352
Modules linked in:
---[ end trace e42d20303e3e7399 ]---
RIP: 0010:crypto_remove_spawns+0x359/0xc30 crypto/algapi.c:155
Code: 39 c4 0f 84 71 01 00 00 4c 89 e0 48 c1 e8 03 42 80 3c 38 00 0f 85 a7 05 00 00 4d 8b 24 24 49 8d 7c 24 18 48 89 f8 48 c1 e8 03 <42> 80 3c 38 00 0f 85 6b 05 00 0f
RSP: 0000:ffff88806a1f7cc8 EFLAGS: 00010206
RAX: 0000000000000003 RBX: ffff88806a1f7e00 RCX: ffffffff81339704
RDX: 0000000000000000 RSI: 0000000000000004 RDI: 0000000000000018
RBP: ffff88806a1f7e28 R08: fffffbfff06973a5 R09: fffffbfff06973a5
R10: fffffbfff06973a4 R11: ffffffff834b9d23 R12: 0000000000000000
R13: ffff88806a1f7d80 R14: ffff88806a1f7d40 R15: dffffc0000000000
FS:  0000000000000000(0000) GS:ffff88806d900000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000ffffffff CR3: 0000000003213001 CR4: 0000000000760ee0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
PKRU: 55555554


  reply	other threads:[~2019-12-06 22:50 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-06 14:39 [PATCH 0/2] crypto: api - Fix spawn races Herbert Xu
2019-12-06 14:39 ` [PATCH 1/2] crypto: api - Fix race condition in crypto_spawn_alg Herbert Xu
2019-12-06 14:39 ` [PATCH 2/2] crypto: api - Do not zap spawn->alg Herbert Xu
2019-12-06 22:50   ` Eric Biggers [this message]
2019-12-07  3:40     ` Herbert Xu
2019-12-07 14:33       ` [PATCH] crypto: api - Add more comments to crypto_remove_spawns Herbert Xu
2019-12-07 14:15 ` [v2 PATCH 0/2] crypto: api - Fix spawn races Herbert Xu
2019-12-07 14:15   ` [PATCH 1/2] crypto: api - Fix race condition in crypto_spawn_alg Herbert Xu
2019-12-11  3:38     ` Eric Biggers
2019-12-11  5:41       ` Herbert Xu
2019-12-07 14:15   ` [PATCH 2/2] crypto: api - Do not zap spawn->alg Herbert Xu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191206225021.GF246840@gmail.com \
    --to=ebiggers@kernel.org \
    --cc=herbert@gondor.apana.org.au \
    --cc=linux-crypto@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).