[PATCH] rand.c updates from FreeBSD RELENG_5

看板DFBSD_submit作者時間21年前 (2004/05/13 03:32), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串1/18 (看更多)
This is a multi-part message in MIME format. --------------060203080303080604030109 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Hi. I know there is the random(3) function, which is much better at randomness than rand(3); however, rand(3) is ISO C, whereas random(3) is not, as far as I know. Plus, many students and others tend to use rand(3) because its taught. The FreeBSD team has already made some updates to rand.c; so, I did not need to do much to port it to DragonFly in the form of an update that generates some better randomness. I have included the patch, but to see what I mean about the current rand(3) not being great, try this code (yes, I know, the seeding could have been done better): #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { int cs, i,r; /*cs == case*/ srand(time(0)); while(1) { cs = rand() % 2; if(cs) printf("O"); else printf("o"); fflush(stdout); } return EXIT_SUCCESS; } Notice that this code prints "OoOoOoOoOo..." in a very predictable manner. Now, the update doesn't make rand(3) all that more secure, but it's just nice to have it be better than its current state. Oh, and if you check revision 1.15 of the FreeBSD rand.c code (where I got this), you will notice I removed the '#include "namespace.h"' and '#include "un-namespace.h"' lines. They wrapped around the headers to make them use different functions. This doesn't seem to have any negative effects with the code I have, but it'd be nice if someone who knows more can comment. It'd be easy to just copy those files if need be and re-add the lines. If this is viable for a commit, I would appreciate it. If not, send it back to me and I'll make the necessary changes. Thanks again, Mike --------------060203080303080604030109 Content-Type: text/plain; name="rand.c.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="rand.c.patch" --- rand.c.orig 2004-05-11 01:34:30.000000000 -0500 +++ rand.c 2004-05-12 05:50:54.000000000 -0500 @@ -31,15 +31,18 @@ * SUCH DAMAGE. * * Posix rand_r function added May 1999 by Wes Peters <wes@softweyr.com>. - * - * $FreeBSD: src/lib/libc/stdlib/rand.c,v 1.2.2.1 2001/03/05 11:33:57 obrien Exp $ - * $DragonFly: src/lib/libc/stdlib/rand.c,v 1.2 2003/06/17 04:26:46 dillon Exp $ - * - * @(#)rand.c 8.1 (Berkeley) 6/14/93 */ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rand.c 8.1 (Berkeley) 6/14/93"; +#endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> + +#include <sys/time.h> /* for sranddev() */ #include <sys/types.h> +#include <fcntl.h> /* for sranddev() */ #include <stdlib.h> +#include <unistd.h> /* for sranddev() */ #ifdef TEST #include <stdio.h> @@ -48,7 +51,34 @@ static int do_rand(unsigned long *ctx) { +#ifdef USE_WEAK_SEEDING +/* + * Historic implementation compatibility. + * The random sequences do not vary much with the seed, + * even with overflowing. + */ return ((*ctx = *ctx * 1103515245 + 12345) % ((u_long)RAND_MAX + 1)); +#else /* !USE_WEAK_SEEDING */ +/* + * Compute x = (7^5 * x) mod (2^31 - 1) + * wihout overflowing 31 bits: + * (2^31 - 1) = 127773 * (7^5) + 2836 + * From "Random number generators: good ones are hard to find", + * Park and Miller, Communications of the ACM, vol. 31, no. 10, + * October 1988, p. 1195. + */ + long hi, lo, x; + + /* Can't be initialized with 0, so use another value. */ + if (*ctx == 0) + *ctx = 123459876; + hi = *ctx / 127773; + lo = *ctx % 127773; + x = 16807 * lo - 2836 * hi; + if (x < 0) + x += 0x7fffffff; + return ((*ctx = x) % ((u_long)RAND_MAX + 1)); +#endif /* !USE_WEAK_SEEDING */ } @@ -56,8 +86,10 @@ rand_r(unsigned int *ctx) { u_long val = (u_long) *ctx; - *ctx = do_rand(&val); - return (int) *ctx; + int r = do_rand(&val); + + *ctx = (unsigned int) val; + return (r); } @@ -66,7 +98,7 @@ int rand() { - return do_rand(&next); + return (do_rand(&next)); } void @@ -76,6 +108,37 @@ next = seed; } + +/* + * sranddev: + * + * Many programs choose the seed value in a totally predictable manner. + * This often causes problems. We seed the generator using the much more + * secure random(4) interface. + */ +void +sranddev() +{ + int fd, done; + + done = 0; + fd = _open("/dev/random", O_RDONLY, 0); + if (fd >= 0) { + if (_read(fd, (void *) &next, sizeof(next)) == sizeof(next)) + done = 1; + _close(fd); + } + + if (!done) { + struct timeval tv; + unsigned long junk; + + gettimeofday(&tv, NULL); + srand((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk); + } +} + + #ifdef TEST main() --------------060203080303080604030109--
文章代碼(AID): #10edky00 (DFBSD_submit)
討論串 (同標題文章)
文章代碼(AID): #10edky00 (DFBSD_submit)