Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 27 Jan 2010 18:57:44 GMT
From:      James Juran <james.juran@baesystems.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/143298: random_yarrow_block() doesn't actually block when not seeded
Message-ID:  <201001271857.o0RIviL6090816@www.freebsd.org>
Resent-Message-ID: <201001271900.o0RJ01vl029463@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         143298
>Category:       kern
>Synopsis:       random_yarrow_block() doesn't actually block when not seeded
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jan 27 19:00:01 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     James Juran
>Release:        FreeBSD-8.0
>Organization:
BAE Systems
>Environment:
FreeBSD freebsd8.goldlnk.rootlnka.net 8.0-RELEASE FreeBSD 8.0-RELEASE #0: Sat Nov 21 15:48:17 UTC 2009     root@almeida.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  i386
>Description:
I believe r153575 introduced a problem with the /dev/random yarrow random number generator's blocking when it is not seeded.

This has likely not been noticed until now because yarrow is marked as seeded when it is loaded by default, so someone would have to change the sysctl value from the default.  This problem likely only affects users who want to do "better" seeding of /dev/random than is provided by /etc/rc.d/initrandom.

In this change the blocking logic was moved from random_read() into a .block method for the particular random number generation method so that the GIANT lock could be removed.  In doing this though, the loop guard appears to have been inadvertently changed from

while (!random_systat.seeded && !error)

to 

while (random_systat.seeded && !error)

>How-To-Repeat:
In FreeBSD 8.0, this incorrect behavior can be observed by doing:

// By default it is seeded and outputs data; no problem here
[root@freebsd8 ~]# sysctl kern.random.sys.seeded
kern.random.sys.seeded: 1
[root@freebsd8 ~]# time dd if=/dev/random bs=1 count=1
=1+0 records in
1+0 records out
1 bytes transferred in 0.000006 secs (167772 bytes/sec)

real    0m0.005s
user    0m0.000s
sys     0m0.006s


// Now mark it as unseeded.  It still produces data and is still marked
// as unseeded after the data is produced.  It should block until the
// seeding is complete.
[root@freebsd8 ~]# sysctl kern.random.sys.seeded=0
kern.random.sys.seeded: 1 -> 0
[root@freebsd8 ~]# time dd if=/dev/random bs=1 count=1
¿1+0 records in
1+0 records out
1 bytes transferred in 0.000006 secs (167772 bytes/sec)

real    0m0.006s
user    0m0.000s
sys     0m0.006s
[root@freebsd8 ~]# sysctl kern.random.sys.seeded
kern.random.sys.seeded: 0

>Fix:
I have not tested this fix and am not able to do so, but I think this will solve the problem and restore the intended behavior.




Patch attached with submission follows:

Index: sys/dev/random/randomdev_soft.c
===================================================================
--- sys/dev/random/randomdev_soft.c	(revision 203082)
+++ sys/dev/random/randomdev_soft.c	(working copy)
@@ -391,7 +391,7 @@ random_yarrow_block(int flag)
 	mtx_lock(&random_reseed_mtx);
 
 	/* Blocking logic */
-	while (random_systat.seeded && !error) {
+	while (!random_systat.seeded && !error) {
 		if (flag & O_NONBLOCK)
 			error = EWOULDBLOCK;
 		else {


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001271857.o0RIviL6090816>