| Summary: | srand() provides only 8-bit table | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Seth <seth> |
| Component: | kern | Assignee: | Andrey A. Chernov <ache> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | Unspecified | ||
| Hardware: | Any | ||
| OS: | Any | ||
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. State Changed From-To: open->analyzed Already fixed in -current State Changed From-To: analyzed->patched This PR state must be "patched" according to guideline Responsible Changed From-To: freebsd-bugs->ache Assign to ache as reminder to MFC State Changed From-To: patched->closed Fixed in -HEAD before 5.0 was branched, so fixed in all supported releases |
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); } }