From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933420Ab3GCS47 (ORCPT ); Wed, 3 Jul 2013 14:56:59 -0400 Received: from hrndva-omtalb.mail.rr.com ([71.74.56.122]:4440 "EHLO hrndva-omtalb.mail.rr.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933197Ab3GCSkx (ORCPT ); Wed, 3 Jul 2013 14:40:53 -0400 X-Authority-Analysis: v=2.0 cv=Du3UCRD+ c=1 sm=0 a=Sro2XwOs0tJUSHxCKfOySw==:17 a=Drc5e87SC40A:10 a=Ciwy3NGCPMMA:10 a=0Yyf6_LS1vQA:10 a=5SG0PmZfjMsA:10 a=bbbx4UPp9XUA:10 a=meVymXHHAAAA:8 a=KGjhK52YXX0A:10 a=sxlsJjnNaUIA:10 a=2C6YHBdLAAAA:8 a=VwQbUJbxAAAA:8 a=Z4Rwk6OoAAAA:8 a=mzh53m0_jfWhFDBG4rEA:9 a=mJMriH8CDpcA:10 a=jbrJJM5MRmoA:10 a=jeBq3FmKZ4MA:10 a=Sro2XwOs0tJUSHxCKfOySw==:117 X-Cloudmark-Score: 0 X-Authenticated-User: X-Originating-IP: 67.255.60.225 Message-Id: <20130703184047.292996366@goodmis.org> User-Agent: quilt/0.60-1 Date: Wed, 03 Jul 2013 14:39:13 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Jiri Kosina , Theodore Tso , Greg KH , Andrew Morton Subject: [016/141] random: fix accounting race condition with lockless irq entropy_count update References: <20130703183857.307196999@goodmis.org> Content-Disposition: inline; filename=0016-random-fix-accounting-race-condition-with-lockless-i.patch Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.6.11.6 stable review patch. If anyone has any objections, please let me know. ------------------ From: Jiri Kosina [ Upstream commit 10b3a32d292c21ea5b3ad5ca5975e88bb20b8d68 ] 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 Cc: Theodore Ts'o Cc: Greg KH Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Steven Rostedt --- drivers/char/random.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index b86eae9..35cfbb0 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -867,16 +867,24 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, 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->entropy_count / 8 >= nbytes + reserved) - r->entropy_count -= nbytes*8; - else - r->entropy_count = reserved; + if (r->limit && nbytes + reserved >= entropy_count / 8) + nbytes = entropy_count/8 - 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) { wake_up_interruptible(&random_write_wait); kill_fasync(&fasync, SIGIO, POLL_OUT); } -- 1.7.10.4