diff --git a/src/Makefile b/src/Makefile index 963128b..2af4804 100644 --- a/src/Makefile +++ b/src/Makefile @@ -38,6 +38,9 @@ # FAKE_SETTIME # - Intercept clock_settime(), settimeofday(), and adjtime() # +# FAKE_RANDOM +# - Intercept getrandom() +# # FORCE_MONOTONIC_FIX # - If the test program hangs forever on # " pthread_cond_timedwait: CLOCK_MONOTONIC test diff --git a/src/libfaketime.c b/src/libfaketime.c index 1d8b429..6936991 100644 --- a/src/libfaketime.c +++ b/src/libfaketime.c @@ -122,6 +122,10 @@ struct utimbuf { }; #endif +#ifdef FAKE_RANDOM +#include +#endif + /* * Per thread variable, which we turn on inside real_* calls to avoid modifying * time multiple times of for the whole process to prevent faking time @@ -219,6 +223,10 @@ static int (*real_utimensat) (int dirfd, const char *filename, co static int (*real_futimens) (int fd, const struct timespec times[2]); #endif +#ifdef FAKE_RANDOM +static ssize_t (*real_getrandom) (void *buf, size_t buflen, unsigned int flags); +#endif + static int initialized = 0; /* prototypes */ @@ -1181,7 +1189,7 @@ static void fake_two_timespec(const struct timespec in_times[2], struct timespec out_times[j] = in_times[j]; } } - else + else { timersub2(&in_times[j], &user_offset, &out_times[j], n); } @@ -2412,6 +2420,11 @@ static void ftpl_init(void) # endif real___clock_gettime = dlsym(RTLD_NEXT, "__clock_gettime"); #endif + +#ifdef FAKE_RANDOM + real_getrandom = dlsym(RTLD_NEXT, "getrandom"); +#endif + #ifdef FAKE_PTHREAD #ifdef __GLIBC__ @@ -3613,6 +3626,41 @@ int adjtime (const struct timeval *delta, struct timeval *olddelta) } #endif +#ifdef FAKE_RANDOM +/* + Local copy of + Middle Square Weyl Sequence Random Number Generator + Copyright (c) 2014-2020 Bernard Widynski + License: GNU GPL v3 + see https://mswsrng.wixsite.com/rand + + adapted to take the seed s as a parameter and return only a byte +*/ +inline static uint32_t fakerandom_msws(uint64_t s) { + static uint64_t x = 0, w = 0; + x *= x; x += (w += s); + x = (x>>32) | (x<<32); + return (char) x & 0xFF; +} + + +ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) { + char *seedstring = getenv("FAKERANDOM_SEED"); + char *b = buf; + + if (seedstring != NULL) { + long long int seed = strtoll(seedstring, NULL, 0); + for (size_t i = 0; i < buflen; i++) { + b[i] = fakerandom_msws(seed); + } + return buflen; + } + else { /* if no FAKERANDOM_SEED was given, use the original function */ + return real_getrandom(buf, buflen, flags); + } +} +#endif + /* * Editor modelines * diff --git a/test/getrandom_test.c b/test/getrandom_test.c new file mode 100644 index 0000000..b47f10d --- /dev/null +++ b/test/getrandom_test.c @@ -0,0 +1,25 @@ +#include +#include +#include + +int main(int argc, char **argv) { + char *buf = calloc(100, 1); + size_t buflen = 100; + unsigned flags = GRND_NONBLOCK; + + fprintf(stdout, "Before getrandom:\n"); + for (int i=0; i < buflen; i++) { fprintf(stdout, "%hhu ", buf[i]); } + fprintf(stdout, "\n"); + + int result = getrandom(buf, buflen, flags); + fprintf(stdout, "getrandom() result: %d\n", result); + if (result == -1) perror("getrandom() unsuccessful"); + + + fprintf(stdout, "After getrandom:\n"); + for (int i=0; i < buflen; i++) { fprintf(stdout, "%hhu ", buf[i]); } + fprintf(stdout, "\n"); + + free(buf); + return 0; +}