[<prev] [next>] [day] [month] [year] [list]
Message-ID: <alpine.LNX.2.00.1305231515510.22195@pobox.suse.cz>
Date: Thu, 23 May 2013 15:22:55 +0200 (CEST)
From: Jiri Kosina <jkosina@...e.cz>
To: tytso@....edu, "H. Peter Anvin" <hpa@...ux.intel.com>,
Ingo Molnar <mingo@...nel.org>
Cc: linux-kernel@...r.kernel.org,
Andrew Morton <akpm@...ux-foundation.org>
Subject: [PATCH umpteenth RESEND] random: fix accounting race condition with
lockless irq entropy_count update
Hi everybody,
this is an umpteenth resend of patch that has been queued in -mm tree for
quite some time, but apart from that, hasn't been acted upon for some
reason. A few more CCs added.
As the bug is causing observable failures of userspace services relying on
/dev/urandom never EOFing (openssh and apache reported to fail) on certain
architectures (s390 known to be hit by this), I think it shouldn't be
unnecessarily delayed.
Thanks in advance.
From: Jiri Kosina <jkosina@...e.cz>
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@...e.cz>
Cc: Theodore Ts'o <tytso@....edu>
Cc: Greg KH <greg@...ah.com>
Cc: <stable@...r.kernel.org>
Signed-off-by: Andrew Morton <akpm@...ux-foundation.org>
---
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;
}
_
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists