New pseudo random number generator
Some checks are pending
Build / build-mac (push) Waiting to run
Build / build-linux (push) Waiting to run
Build / build-win (push) Waiting to run
CodeQL / Analyze (push) Waiting to run

This commit is contained in:
Andrea Mazzoleni 2026-01-05 17:20:22 +01:00
parent 0aafcd1819
commit 13fae39eb3
6 changed files with 80 additions and 33 deletions

View file

@ -163,13 +163,10 @@ void os_init(int opt)
/* check for Wine presence */
is_wine = GetProcAddress(ntdll, "wine_get_version") != 0;
/* setup the standard random generator used as fallback */
srand(GetTickCount());
/* get pointer to RtlGenRandom, note that it was reported missing in some cases */
ptr_RtlGenRandom = (void*)GetProcAddress(dll_advapi32, "SystemFunction036");
/* get pointer to RtlGenRandom, note that it was reported missing in some cases */
/* get pointer to ptr_GetTickCount64 */
ptr_GetTickCount64 = (void*)GetProcAddress(kernel32, "GetTickCount64");
/* set the thread execution level to avoid sleep */
@ -2239,21 +2236,9 @@ int randomize(void* void_ptr, size_t size)
if (ptr_RtlGenRandom != 0 && ptr_RtlGenRandom(ptr, size) != 0)
return 0;
/* try rand_s */
for (i = 0; i < size; ++i) {
unsigned v = 0;
if (rand_s(&v) != 0)
break;
ptr[i] = v;
}
if (i == size)
return 0;
/* fallback to standard rand */
for (i = 0; i < size; ++i)
ptr[i] = rand();
ptr[i] = random_u8();
return 0;
}

View file

@ -46,11 +46,6 @@
*/
#define _WIN32_WINNT 0x600
/**
* Enable the rand_s() function.l
*/
#define _CRT_RAND_S
#include <windows.h>
#endif

View file

@ -1360,6 +1360,7 @@ int snapraid_main(int argc, char* argv[])
os_init(opt.force_scan_winfind);
raid_init();
crc32c_init();
random_reseed();
if (speedtest != 0) {
speed(period);

View file

@ -28,6 +28,7 @@
#if HAVE_THREAD
static thread_mutex_t msg_lock;
static thread_mutex_t memory_lock;
static thread_mutex_t random_lock;
#endif
void lock_msg(void)
@ -58,12 +59,28 @@ void unlock_memory(void)
#endif
}
void lock_random(void)
{
#if HAVE_THREAD
thread_mutex_lock(&random_lock);
#endif
}
void unlock_random(void)
{
#if HAVE_THREAD
thread_mutex_unlock(&random_lock);
#endif
}
void lock_init(void)
{
#if HAVE_THREAD
/* initialize the locks as first operation as log_fatal depends on them */
thread_mutex_init(&msg_lock);
thread_mutex_init(&memory_lock);
thread_mutex_init(&random_lock);
#endif
}
@ -72,9 +89,50 @@ void lock_done(void)
#if HAVE_THREAD
thread_mutex_destroy(&msg_lock);
thread_mutex_destroy(&memory_lock);
thread_mutex_destroy(&random_lock);
#endif
}
/****************************************************************************/
/* random */
static uint64_t random_state = 1;
void random_reseed(void)
{
random_state = tick();
}
unsigned char random_u8(void)
{
return random_u64() & 0xFF;
}
/*
* SplitMix64
*
* - Zero-safe: Any 64-bit seed is valid (even 0).
* - Full period: Guaranteed to visit every 2^64 value.
* - Logic: Uses a Weyl sequence + MurmurHash3-style finalizer.
*
* See: https://rosettacode.org/wiki/Pseudo-random_numbers/Splitmix64
*/
uint64_t random_u64(void)
{
uint64_t z;
lock_random();
z = random_state += 0x9E3779B97F4A7C15ULL;
unlock_random();
z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ULL;
z = (z ^ (z >> 27)) * 0x94D049BB133111EBULL;
return z ^ (z >> 31);
}
/****************************************************************************/
/* print */

View file

@ -52,6 +52,24 @@ void unlock_msg(void);
void lock_memory(void);
void unlock_memory(void);
/****************************************************************************/
/* random */
/**
* Reseed the random pseudo random number generator
*/
void random_reseed(void);
/**
* Return a pseudo random number of 8 bits
*/
unsigned char random_u8(void);
/**
* Return a pseudo random number of 64 bits
*/
uint64_t random_u64(void);
/****************************************************************************/
/* log */

View file

@ -1622,16 +1622,6 @@ static int devup(dev_t device, const char* name)
void* buf;
uint64_t size;
uint64_t offset;
uint64_t pseudo_random;
/* get a pseudo random number */
ret = randomize(&pseudo_random, sizeof(pseudo_random));
if (ret < 0) {
/* LCOV_EXCL_START */
log_fatal("Failed to retrieve random values.\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (devresolve(device, file, sizeof(file)) != 0) {
/* LCOV_EXCL_START */
@ -1669,7 +1659,7 @@ static int devup(dev_t device, const char* name)
}
/* select a random offset */
offset = (pseudo_random % (size / 4096)) * 4096;
offset = (random_u64() % (size / 4096)) * 4096;
#if HAVE_POSIX_FADVISE
/* clear cache */