libdispatch compiles under Linux but arc4random(3) is missing
Good news: libdispatch now compiles successfully under Linux using libkqueue r96 or higher. The test programs in the testing/ directory fail to link because arc4random(3) is not available on Linux. I found a compatibility function written for BIND that might work; the URI is: http://mirror.its.uidaho.edu/pub/netbsd/NetBSD-current/src/external/bsd/bind... See below for the actual code. Any objections to adding something like this to libdispatch? Regards, - Mark /* $NetBSD: random.c,v 1.1.1.1 2009/03/22 15:02:07 christos Exp $ */ /* * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /* Id: random.c,v 1.25 2007/06/19 23:47:17 tbox Exp */ /*! \file */ #include <config.h> #include <stdlib.h> #include <time.h> /* Required for time(). */ #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> #endif #ifdef HAVE_UNISTD_H #include <unistd.h> #endif #include <isc/mutex.h> #include <isc/once.h> #include <isc/random.h> #include <isc/string.h> #include <isc/util.h> static isc_once_t once = ISC_ONCE_INIT; static void initialize_rand(void) { #ifndef HAVE_ARC4RANDOM unsigned int pid = getpid(); /* * The low bits of pid generally change faster. * Xor them with the high bits of time which change slowly. */ pid = ((pid << 16) & 0xffff0000) | ((pid >> 16) & 0xffff); srand(time(NULL) ^ pid); #endif } static void initialize(void) { RUNTIME_CHECK(isc_once_do(&once, initialize_rand) == ISC_R_SUCCESS); } void isc_random_seed(isc_uint32_t seed) { initialize(); #ifndef HAVE_ARC4RANDOM srand(seed); #else arc4random_addrandom((u_char *) &seed, sizeof(isc_uint32_t)); #endif } void isc_random_get(isc_uint32_t *val) { REQUIRE(val != NULL); initialize(); #ifndef HAVE_ARC4RANDOM /* * rand()'s lower bits are not random. * rand()'s upper bit is zero. */ *val = ((rand() >> 4) & 0xffff) | ((rand() << 12) & 0xffff0000); #else *val = arc4random(); #endif } isc_uint32_t isc_random_jitter(isc_uint32_t max, isc_uint32_t jitter) { REQUIRE(jitter < max); if (jitter == 0) return (max); else #ifndef HAVE_ARC4RANDOM return (max - rand() % jitter); #else return (max - arc4random() % jitter); #endif }
On Nov 15, 2009, at 6:09 PM, Mark Heily wrote:
Good news: libdispatch now compiles successfully under Linux using libkqueue r96 or higher.
The test programs in the testing/ directory fail to link because arc4random(3) is not available on Linux. I found a compatibility function written for BIND that might work; the URI is:
http://mirror.its.uidaho.edu/pub/netbsd/NetBSD-current/src/external/bsd/bind...
See below for the actual code. Any objections to adding something like this to libdispatch?
I'm not sure I really see why... This is something that should logically be handled instead by a HAVE_ARC4RANDOM check, with the alternate sides of the #ifdef being the appropriate calls to srand() and rand(), just as the ISC has done. No need to add shims just for the use of a single library, in other words. Am I missing something? - Jordan
Jordan K. Hubbard wrote:
See below for the actual code. Any objections to adding something like this to libdispatch?
I'm not sure I really see why... This is something that should logically be handled instead by a HAVE_ARC4RANDOM check, with the alternate sides of the #ifdef being the appropriate calls to srand() and rand(), just as the ISC has done. No need to add shims just for the use of a single library, in other words. Am I missing something?
- Jordan
Thanks for the advice to keep things simple. Here is a patch to provide arc4random(3) that is based on the ISC code. There is one other consumer of arc4random() in the tree -- testing/fd_stress.c -- but this program is not built by default in Makefile.am, so I am not going to worry about it right now. Regards, - Mark Index: configure.ac =================================================================== --- configure.ac (revision 166) +++ configure.ac (working copy) @@ -191,7 +191,7 @@ AC_CHECK_DECLS([FD_COPY], [], [], [[#include <sys/select.h>]]) AC_CHECK_DECLS([SIGEMT], [], [], [[#include <signal.h>]]) AC_CHECK_DECLS([VQ_UPDATE, VQ_VERYLOWDISK], [], [], [[#include <sys/mount.h>]]) -AC_CHECK_FUNCS([pthread_key_init_np pthread_main_np mach_absolute_time malloc_create_zone sysconf]) +AC_CHECK_FUNCS([pthread_key_init_np pthread_main_np mach_absolute_time malloc_create_zone sysconf arc4random]) AC_CHECK_DECLS([POSIX_SPAWN_START_SUSPENDED], [have_posix_spawn_start_suspended=true], Index: testing/queue_finalizer.c =================================================================== --- testing/queue_finalizer.c (revision 166) +++ testing/queue_finalizer.c (working copy) @@ -32,6 +32,35 @@ void *ctxt_magic; +/* +* Based on ISC BIND lib/isc/random.c +*/ +#ifndef HAVE_ARC4RANDOM +static uint32_t +arc4random(void) +{ + unsigned int pid; + static int arc4random_init; + + /* + * The low bits of pid generally change faster. + * Xor them with the high bits of time which change slowly. + */ + if (!arc4random_init) { + pid = getpid(); + pid = ((pid << 16) & 0xffff0000) | ((pid >> 16) & 0xffff); + srand(time(NULL) ^ pid); + arc4random_init = 1; + } + + /* + * rand()'s lower bits are not random. + * rand()'s upper bit is zero. + */ + return ((rand() >> 4) & 0xffff) | ((rand() << 12) & 0xffff0000); +} +#endif /* ! HAVE_ARC4RANDOM */ + static void finalizer(void *ctxt) {
Hi, Mark Heily schrieb:
Good news: libdispatch now compiles successfully under Linux using libkqueue r96 or higher.
Great. I also like to use libdispatch on linux.
The test programs in the testing/ directory fail to link because arc4random(3) is not available on Linux. I found a compatibility function written for BIND that might work; the URI is:
See below for the actual code. Any objections to adding something like this to libdispatch?
Why does libdispatch has to use arc4random at all? Since, this is not a security-sensitive application but some testing code, why don't we use rand/random, that should be available on all systems? ciao, Mario
On 16 Nov 2009, at 12:47, Mario Schwalbe wrote:
The test programs in the testing/ directory fail to link because arc4random(3) is not available on Linux. I found a compatibility function written for BIND that might work; the URI is:
See below for the actual code. Any objections to adding something like this to libdispatch?
Why does libdispatch has to use arc4random at all? Since, this is not a security-sensitive application but some testing code, why don't we use rand/random, that should be available on all systems?
I can't speak to the reason Apple made this design choice in the first place, but I can speak to *a* reason why this would be a problem: The rand(3) and random(3) APIs have well-defined characteristics with respect to repeatable behavior given a specific seed. If libdispatch uses srand(),rand(), it may interfere with the application's use of the same interfaces, replacing the application's seeding and consuming numbers from the sequence so that they are no longer returned to the application. Consider, for example, a simulator that accepts a seed as an argument so that the same sequence can be replayed. Robert
On 11/16/2009 01:58 PM, Robert N. M. Watson wrote:
The rand(3) and random(3) APIs have well-defined characteristics with respect to repeatable behavior given a specific seed. If libdispatch uses srand(),rand(), it may interfere with the application's use of the same interfaces, replacing the application's seeding and consuming numbers from the sequence so that they are no longer returned to the application. Consider, for example, a simulator that accepts a seed as an argument so that the same sequence can be replayed.
That's in the test harness though, not in libdispatch. Paolo
On Mon, 16 Nov 2009, Paolo Bonzini wrote:
On 11/16/2009 01:58 PM, Robert N. M. Watson wrote:
The rand(3) and random(3) APIs have well-defined characteristics with respect to repeatable behavior given a specific seed. If libdispatch uses srand(),rand(), it may interfere with the application's use of the same interfaces, replacing the application's seeding and consuming numbers from the sequence so that they are no longer returned to the application. Consider, for example, a simulator that accepts a seed as an argument so that the same sequence can be replayed.
That's in the test harness though, not in libdispatch.
Indeed. :-) Robert N M Watson Computer Laboratory University of Cambridge
participants (6)
-
Jordan K. Hubbard
-
Mario Schwalbe
-
Mark Heily
-
Paolo Bonzini
-
Robert N. M. Watson
-
Robert Watson