On Wed, 1 May 2013, Theodore Ts'o wrote:

> > > ------------------------------------------------------
> > > From: Jiri Kosina <[email protected]>
> > > Subject: random: fix accounting race condition with lockless irq 
> > > entropy_count update
> > 
> > I see this hasn't been included even in the third (last?) batch of your 
> > pile going to Linus for rc1 ... was this intentional, please?
> > 
> 
> Hi Jiri,
> 
> Can you send me a copy of the patch?

Hi Ted,

absolutely, please find it below.

> I can't find it in my inbox...

Odd. I can see you CCed in both cases when I have been sending it, and 
when Andrew has been sending his "added to mm tree" message.
Something went wrong somewhere ...

Thanks.


------------------------------------------------------
From: Jiri Kosina <[email protected]>
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 <[email protected]>
Cc: Theodore Ts'o <[email protected]>
Cc: Greg KH <[email protected]>
Cc: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
---

 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to