Re: [patch 2/2] random: fix accounting race condition with lockless irq entropy_count update

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

 



On Tue, 7 May 2013, akpm@xxxxxxxxxxxxxxxxxxxx wrote:

> From: Jiri Kosina <jkosina@xxxxxxx>
> Subject: random: fix accounting race condition with lockless irq entropy_count update
> 
> Commit 902c098a3663 ("random: use lockless techniques in the interrupt
> path") turned IRQ path from being spinlock protected into lockless
> cmpxchg-retry update.
> 
> That commit removed r->lock serialization between crediting entropy bits
> from IRQ context and accounting when extracting entropy on userspace read
> path, but didn't turn the r->entropy_count reads/updates in account() to
> use cmpxchg as well.
> 
> It has been observed, that under certain circumstances this leads to
> read() on /dev/urandom to return 0 (EOF), as r->entropy_count gets
> corrupted and becomes negative, which in turn results in propagating 0 all
> the way from account() to the actual read() call.
> 
> Convert the accounting code to be the proper lockless counterpart of what
> has been partially done by 902c098a3663.
> 
> Signed-off-by: Jiri Kosina <jkosina@xxxxxxx>
> Cc: Theodore Ts'o <tytso@xxxxxxx>
> Cc: Greg KH <greg@xxxxxxxxx>
> Cc: <stable@xxxxxxxxxxxxxxx>
> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>

I don't think this patch has been acted upon, has it?

Ted, please?

Thanks.

> ---
> 
>  drivers/char/random.c |   22 +++++++++++++++-------
>  1 file changed, 15 insertions(+), 7 deletions(-)
> 
> diff -puN drivers/char/random.c~random-fix-accounting-race-condition-with-lockless-irq-entropy_count-update drivers/char/random.c
> --- a/drivers/char/random.c~random-fix-accounting-race-condition-with-lockless-irq-entropy_count-update
> +++ a/drivers/char/random.c
> @@ -865,16 +865,24 @@ static size_t account(struct entropy_sto
>  	if (r->entropy_count / 8 < min + reserved) {
>  		nbytes = 0;
>  	} else {
> +		int entropy_count, orig;
> +retry:
> +		entropy_count = orig = ACCESS_ONCE(r->entropy_count);
>  		/* If limited, never pull more than available */
> -		if (r->limit && nbytes + reserved >= r->entropy_count / 8)
> -			nbytes = r->entropy_count/8 - reserved;
> +		if (r->limit && nbytes + reserved >= entropy_count / 8)
> +			nbytes = entropy_count/8 - reserved;
>  
> -		if (r->entropy_count / 8 >= nbytes + reserved)
> -			r->entropy_count -= nbytes*8;
> -		else
> -			r->entropy_count = reserved;
> +		if (entropy_count / 8 >= nbytes + reserved) {
> +			entropy_count -= nbytes*8;
> +			if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
> +				goto retry;
> +		} else {
> +			entropy_count = reserved;
> +			if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
> +				goto retry;
> +		}
>  
> -		if (r->entropy_count < random_write_wakeup_thresh)
> +		if (entropy_count < random_write_wakeup_thresh)
>  			wakeup_write = 1;
>  	}
>  
> _
> 

-- 
Jiri Kosina
SUSE Labs
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]