Re: crypto: api - Fix use-after-free and race in crypto_spawn_alg

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Apr 10, 2020 at 04:09:42PM +1000, Herbert Xu wrote:
> There are two problems in crypto_spawn_alg.  First of all it may
> return spawn->alg even if spawn->dead is set.  This results in a
> double-free as detected by syzbot.
> 
> Secondly the setting of the DYING flag is racy because we hold
> the read-lock instead of the write-lock.  We should instead call
> crypto_shoot_alg in a safe manner by gaining a refcount, dropping
> the lock, and then releasing the refcount.
> 
> This patch fixes both problems.
> 
> Reported-by: syzbot+fc0674cde00b66844470@xxxxxxxxxxxxxxxxxxxxxxxxx
> Fixes: 4f87ee118d16 ("crypto: api - Do not zap spawn->alg")
> Fixes: 73669cc55646 ("crypto: api - Fix race condition in...")
> Cc: <stable@xxxxxxxxxxxxxxx>
> Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
> 
> diff --git a/crypto/algapi.c b/crypto/algapi.c
> index 69605e21af92..f8b4dc161c02 100644
> --- a/crypto/algapi.c
> +++ b/crypto/algapi.c
> @@ -716,17 +716,27 @@ EXPORT_SYMBOL_GPL(crypto_drop_spawn);
>  
>  static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn)
>  {
> -	struct crypto_alg *alg;
> +	struct crypto_alg *alg = ERR_PTR(-EAGAIN);
> +	struct crypto_alg *target;
> +	bool shoot = false;
>  
>  	down_read(&crypto_alg_sem);
> -	alg = spawn->alg;
> -	if (!spawn->dead && !crypto_mod_get(alg)) {
> -		alg->cra_flags |= CRYPTO_ALG_DYING;
> -		alg = NULL;
> +	if (!spawn->dead) {
> +		alg = spawn->alg;
> +		if (!crypto_mod_get(alg)) {
> +			target = crypto_alg_get(alg);
> +			shoot = true;
> +			alg = ERR_PTR(-EAGAIN);
> +		}
>  	}
>  	up_read(&crypto_alg_sem);
>  
> -	return alg ?: ERR_PTR(-EAGAIN);
> +	if (shoot) {
> +		crypto_shoot_alg(target);
> +		crypto_alg_put(target);
> +	}
> +
> +	return alg;
>  }

Wouldn't it be a bit simpler to set 'target = NULL', remove 'shoot',
and use 'if (target)' instead of 'if (shoot)'?

- Eric



[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux