Bug 26646

Summary: srand() provides only 8-bit table
Product: Base System Reporter: Seth <seth>
Component: kernAssignee: Andrey A. Chernov <ache>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: Unspecified   
Hardware: Any   
OS: Any   

Description Seth 2001-04-17 15:10:01 UTC
This is not a serious problem; in fact, it's well documented in the
srand() and rand() manpages.  However, the behavior on FreeBSD is not
consistent with other operating systems, and ports that fail to take
the differences into account will exhibit bad behavior under FreeBSD
while appearing fine under other OSes (linux and solaris tested).

The issue is that FreeBSD's srand() is acknowleged to be weak, but it's
been strengthened in other OSes. (linux and solaris).  FreeBSD's srand()
provides an 8-bit-wide seed table, where srand(n) produces the same
sequence of random numbers (returned by rand()) as srand(n*(256*m)).

This affects at least one port -- ident2 -- which uses srand() and rand()
with time() to produce a pseudorandom sequence of 6 characters to respond
to an ident request.  In FreeBSD, the weakness in srand() will cause
ident2 to repeat the same 6-character ident string every 256 seconds, and
will cause significant overlap in other cases (where the last 3-5 characters
are the same as the first 3-5 characters of the last request).  The same
code on linux and solaris does not repeat with this frequency.

Admittedly, this is not a huge problem in itself, but the consequences
of having this weakness when other OSes don't may be a bit troubling.
If coders code on linux, for example, and don't see that there's a problem
with srand() /rand() returning predictable values, then ports (like ident2)
will show acceptable behavior on linux but unacceptably bad randomness
in FreeBSD.

Now, it's entirely possible that some code (probably FreeBSD-specific, since
other OSes "fix" srand()) relies on the weakness of srand() to operate
correctly.  I will leave it up to other, more experienced programmers to
determine (a) if this in fact the case, and (b) whether that's a good way
of coding.

Fix: 

There are two possible workarounds.  The first is to identify all third-party
code that uses srand() and rand() and apply the necessary patches to
make them use srandom() and random().  The second is to "fix" srand()
and rand() by redefining them as srandom() and random():

#define rand (int)random
#define srand(seed) srandom((int)(seed))

(The above two lines, when applied to the code, seem to "fix" the problem.)
How-To-Repeat: 
The weakness of srand() in FreeBSD can be demonstrated by the following code:
(Please forgive the code quality; I'm not a programmer.)

#define SEED 68
#define STR 6
main() {
  int i,j;
  char randstr[STR+1];

  for (j = SEED;;j+=256) {
    printf ("testing seed of %d: ",j);
    srand(j);
          for (i = 0; i < STR; i++) {
                 randstr[i] = rand();
                 while (randstr[i] > 'z')
                         randstr[i] -= 26;
                 while (randstr[i] < 'a')
                         randstr[i] += 26;
         }
     randstr[STR] = 0;
     printf ("%s\n",randstr);
  }
}
Comment 1 Peter Pentchev 2001-04-17 15:15:08 UTC
On Tue, Apr 17, 2001 at 10:02:23AM -0400, Seth wrote:
> 
> >Number:         26646
> >Category:       misc
> >Synopsis:       srand() provides only 8-bit table
> >Originator:     Seth
> >Release:        FreeBSD 4.0-20000710-STABLE i386
> >Organization:

[snip]

> >Fix:
> 
> There are two possible workarounds.  The first is to identify all third-party
> code that uses srand() and rand() and apply the necessary patches to
> make them use srandom() and random().  The second is to "fix" srand()
> and rand() by redefining them as srandom() and random():

There was a recent discussion on -arch, which seemed to suggest that the first
workaround would be the better one.  There seem to be people running programs
that depend on the exact algorithm rand() uses - don't as me why.. and.. hm..
I don't seem to remember any other reasons for not strengthening s/rand()
that popped up then..

G'luck,
Peter

-- 
I am jealous of the first word in this sentence.
Comment 2 Andrey A. Chernov freebsd_committer freebsd_triage 2001-04-17 15:21:04 UTC
State Changed
From-To: open->analyzed

Already fixed in -current
Comment 3 Andrey A. Chernov freebsd_committer freebsd_triage 2002-06-08 21:18:09 UTC
State Changed
From-To: analyzed->patched

This PR state must be "patched" according to guideline
Comment 4 Kris Kennaway freebsd_committer freebsd_triage 2003-07-13 04:45:33 UTC
Responsible Changed
From-To: freebsd-bugs->ache

Assign to ache as reminder to MFC
Comment 5 Gavin Atkinson freebsd_committer freebsd_triage 2008-05-29 11:05:19 UTC
State Changed
From-To: patched->closed

Fixed in -HEAD before 5.0 was branched, so fixed in all supported releases