All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nicolas Ferre <nicolas.ferre@atmel.com>
To: Peter Korsgaard <jacmet@sunsite.dk>, <herbert@gondor.hengli.com.au>
Cc: <jamie@jamieiles.com>, <linux-kernel@vger.kernel.org>,
	<GPontis@z9.com>, <stable@vger.kernel.org>
Subject: Re: [PATCH] hw_random: atmel-rng: fix race condition leading to repeated bits
Date: Fri, 25 May 2012 12:04:06 +0200	[thread overview]
Message-ID: <4FBF5916.4070705@atmel.com> (raw)
In-Reply-To: <1337937158-9710-1-git-send-email-jacmet@sunsite.dk>

On 05/25/2012 11:12 AM, Peter Korsgaard :
> Data valid gets cleared by reading the ISR (status register) and NOT from
> reading ODATA (data register). A new data word can become available between
> checking ISR and reading ODATA, causing us to reuse the same data word next
> time atmel_trng_read() gets called, if that happens before the following
> data word is ready.

Hi Peter, thanks for finding this...

> With this fixed, rngtest no longer complains of 'Continous run' errors.
> Before:
> 
> rngtest -c 1000 < /dev/hwrng
> rngtest 3
> Copyright (c) 2004 by Henrique de Moraes Holschuh
> This is free software; see the source for copying conditions.  There is NO warr.
> 
> rngtest: starting FIPS tests...
> rngtest: bits received from input: 20000032
> rngtest: FIPS 140-2 successes: 923
> rngtest: FIPS 140-2 failures: 77
> rngtest: FIPS 140-2(2001-10-10) Monobit: 0
> rngtest: FIPS 140-2(2001-10-10) Poker: 0
> rngtest: FIPS 140-2(2001-10-10) Runs: 1
> rngtest: FIPS 140-2(2001-10-10) Long run: 0
> rngtest: FIPS 140-2(2001-10-10) Continuous run: 76
> rngtest: input channel speed: (min=721.402; avg=46003.510; max=49321.338)Kibitss
> rngtest: FIPS tests speed: (min=11.442; avg=12.714; max=12.801)Mibits/s
> rngtest: Program run time: 1931860 microseconds
> 
> After:
> 
> rngtest -c 1000 < /dev/hwrng
> rngtest 3
> Copyright (c) 2004 by Henrique de Moraes Holschuh
> This is free software; see the source for copying conditions.  There is NO warr.
> 
> rngtest: starting FIPS tests...
> rngtest: bits received from input: 20000032
> rngtest: FIPS 140-2 successes: 1000
> rngtest: FIPS 140-2 failures: 0
> rngtest: FIPS 140-2(2001-10-10) Monobit: 0
> rngtest: FIPS 140-2(2001-10-10) Poker: 0
> rngtest: FIPS 140-2(2001-10-10) Runs: 0
> rngtest: FIPS 140-2(2001-10-10) Long run: 0
> rngtest: FIPS 140-2(2001-10-10) Continuous run: 0
> rngtest: input channel speed: (min=777.518; avg=36988.482; max=43115.342)Kibitss
> rngtest: FIPS tests speed: (min=11.951; avg=12.715; max=12.887)Mibits/s
> rngtest: Program run time: 2035543 microseconds
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
> Reported-by: George Pontis <GPontis@z9.com>
> ---
>  drivers/char/hw_random/atmel-rng.c |    7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
> index d7ab920..731c904 100644
> --- a/drivers/char/hw_random/atmel-rng.c
> +++ b/drivers/char/hw_random/atmel-rng.c
> @@ -36,6 +36,13 @@ static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max,
>  	/* data ready? */
>  	if (readl(trng->base + TRNG_ISR) & 1) {
>  		*data = readl(trng->base + TRNG_ODATA);
> +		/*
> +		  ensure data ready is only set again AFTER the next data
> +		  word is ready in case it got set between checking ISR
> +		  and reading ODATA, so we don't risk re-reading the
> +		  same word
> +		*/
> +		readl(trng->base + TRNG_ISR);
>  		return 4;
>  	} else
>  		return 0;

What about a single read to ISR like this:

tmp = readl(trng->base + TRNG_ODATA);
if (readl(trng->base + TRNG_ISR) & 1) {
	*data = tmp;
	return 4;
} else {
  	return 0;
}

But it is true that there is always 2 reads in case of data not
available, instead of just one: I cannot figure out which solution is
the fastest: your thoughts?

Bye,
-- 
Nicolas Ferre

WARNING: multiple messages have this Message-ID (diff)
From: Nicolas Ferre <nicolas.ferre@atmel.com>
To: Peter Korsgaard <jacmet@sunsite.dk>, <herbert@gondor.apana.org.au>
Cc: <jamie@jamieiles.com>, <linux-kernel@vger.kernel.org>,
	<GPontis@z9.com>, <stable@vger.kernel.org>
Subject: Re: [PATCH] hw_random: atmel-rng: fix race condition leading to repeated bits
Date: Fri, 25 May 2012 12:04:06 +0200	[thread overview]
Message-ID: <4FBF5916.4070705@atmel.com> (raw)
In-Reply-To: <1337937158-9710-1-git-send-email-jacmet@sunsite.dk>

On 05/25/2012 11:12 AM, Peter Korsgaard :
> Data valid gets cleared by reading the ISR (status register) and NOT from
> reading ODATA (data register). A new data word can become available between
> checking ISR and reading ODATA, causing us to reuse the same data word next
> time atmel_trng_read() gets called, if that happens before the following
> data word is ready.

Hi Peter, thanks for finding this...

> With this fixed, rngtest no longer complains of 'Continous run' errors.
> Before:
> 
> rngtest -c 1000 < /dev/hwrng
> rngtest 3
> Copyright (c) 2004 by Henrique de Moraes Holschuh
> This is free software; see the source for copying conditions.  There is NO warr.
> 
> rngtest: starting FIPS tests...
> rngtest: bits received from input: 20000032
> rngtest: FIPS 140-2 successes: 923
> rngtest: FIPS 140-2 failures: 77
> rngtest: FIPS 140-2(2001-10-10) Monobit: 0
> rngtest: FIPS 140-2(2001-10-10) Poker: 0
> rngtest: FIPS 140-2(2001-10-10) Runs: 1
> rngtest: FIPS 140-2(2001-10-10) Long run: 0
> rngtest: FIPS 140-2(2001-10-10) Continuous run: 76
> rngtest: input channel speed: (min=721.402; avg=46003.510; max=49321.338)Kibitss
> rngtest: FIPS tests speed: (min=11.442; avg=12.714; max=12.801)Mibits/s
> rngtest: Program run time: 1931860 microseconds
> 
> After:
> 
> rngtest -c 1000 < /dev/hwrng
> rngtest 3
> Copyright (c) 2004 by Henrique de Moraes Holschuh
> This is free software; see the source for copying conditions.  There is NO warr.
> 
> rngtest: starting FIPS tests...
> rngtest: bits received from input: 20000032
> rngtest: FIPS 140-2 successes: 1000
> rngtest: FIPS 140-2 failures: 0
> rngtest: FIPS 140-2(2001-10-10) Monobit: 0
> rngtest: FIPS 140-2(2001-10-10) Poker: 0
> rngtest: FIPS 140-2(2001-10-10) Runs: 0
> rngtest: FIPS 140-2(2001-10-10) Long run: 0
> rngtest: FIPS 140-2(2001-10-10) Continuous run: 0
> rngtest: input channel speed: (min=777.518; avg=36988.482; max=43115.342)Kibitss
> rngtest: FIPS tests speed: (min=11.951; avg=12.715; max=12.887)Mibits/s
> rngtest: Program run time: 2035543 microseconds
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
> Reported-by: George Pontis <GPontis@z9.com>
> ---
>  drivers/char/hw_random/atmel-rng.c |    7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
> index d7ab920..731c904 100644
> --- a/drivers/char/hw_random/atmel-rng.c
> +++ b/drivers/char/hw_random/atmel-rng.c
> @@ -36,6 +36,13 @@ static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max,
>  	/* data ready? */
>  	if (readl(trng->base + TRNG_ISR) & 1) {
>  		*data = readl(trng->base + TRNG_ODATA);
> +		/*
> +		  ensure data ready is only set again AFTER the next data
> +		  word is ready in case it got set between checking ISR
> +		  and reading ODATA, so we don't risk re-reading the
> +		  same word
> +		*/
> +		readl(trng->base + TRNG_ISR);
>  		return 4;
>  	} else
>  		return 0;

What about a single read to ISR like this:

tmp = readl(trng->base + TRNG_ODATA);
if (readl(trng->base + TRNG_ISR) & 1) {
	*data = tmp;
	return 4;
} else {
  	return 0;
}

But it is true that there is always 2 reads in case of data not
available, instead of just one: I cannot figure out which solution is
the fastest: your thoughts?

Bye,
-- 
Nicolas Ferre

  reply	other threads:[~2012-05-25 10:04 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-25  9:12 [PATCH] hw_random: atmel-rng: fix race condition leading to repeated bits Peter Korsgaard
2012-05-25  9:12 ` Peter Korsgaard
2012-05-25 10:04 ` Nicolas Ferre [this message]
2012-05-25 10:04   ` Nicolas Ferre
2012-05-25 10:10   ` Peter Korsgaard
2012-05-25 10:10     ` Peter Korsgaard
2012-05-27 11:49     ` Nicolas Ferre
2012-05-27 11:49       ` Nicolas Ferre
2012-05-27 11:51 ` Nicolas Ferre
2012-05-27 11:51   ` Nicolas Ferre
2012-05-31 10:54 ` Herbert Xu
2012-05-31 10:54   ` 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=4FBF5916.4070705@atmel.com \
    --to=nicolas.ferre@atmel.com \
    --cc=GPontis@z9.com \
    --cc=herbert@gondor.hengli.com.au \
    --cc=jacmet@sunsite.dk \
    --cc=jamie@jamieiles.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.