mirror of https://github.com/aria2/aria2
Handle linux getrandom returning EINTR on interrupts/signals
Also handle ENOTSUP failures where aria2 was build with linux headers newer than the actual running kernel. Fixes GH-336random-webseeding
parent
9cbbe9f1bb
commit
ba0e32abae
|
@ -42,6 +42,8 @@
|
||||||
|
|
||||||
#include "a2time.h"
|
#include "a2time.h"
|
||||||
#include "a2functional.h"
|
#include "a2functional.h"
|
||||||
|
#include "LogFactory.h"
|
||||||
|
#include "fmt.h"
|
||||||
|
|
||||||
#ifdef HAVE_GETRANDOM_INTERFACE
|
#ifdef HAVE_GETRANDOM_INTERFACE
|
||||||
# include "getrandom_linux.h"
|
# include "getrandom_linux.h"
|
||||||
|
@ -88,10 +90,24 @@ void SimpleRandomizer::getRandomBytes(unsigned char* buf, size_t len)
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
BOOL r = CryptGenRandom(provider_, len, reinterpret_cast<BYTE*>(buf));
|
BOOL r = CryptGenRandom(provider_, len, reinterpret_cast<BYTE*>(buf));
|
||||||
assert(r);
|
assert(r);
|
||||||
#elif defined(HAVE_GETRANDOM_INTERFACE)
|
|
||||||
auto rv = getrandom_linux(buf, len);
|
|
||||||
assert(rv >= 0 && (size_t)rv == len);
|
|
||||||
#else // ! __MINGW32__
|
#else // ! __MINGW32__
|
||||||
|
#if defined(HAVE_GETRANDOM_INTERFACE)
|
||||||
|
static bool have_random_support = true;
|
||||||
|
if (have_random_support) {
|
||||||
|
auto rv = getrandom_linux(buf, len);
|
||||||
|
if (rv != -1 || errno != ENOSYS) {
|
||||||
|
if (rv < -1) {
|
||||||
|
A2_LOG_ERROR(fmt("Failed to produce randomness: %d", errno));
|
||||||
|
}
|
||||||
|
assert(rv >= 0 && (size_t)rv == len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
have_random_support = false;
|
||||||
|
A2_LOG_INFO("Disabled getrandom support, because kernel does not "\
|
||||||
|
"implement this feature (ENOSYS)");
|
||||||
|
}
|
||||||
|
// Fall through to generic implementation
|
||||||
|
#endif // defined(HAVE_GETRANDOM_INTERFACE)
|
||||||
auto ubuf = reinterpret_cast<result_type*>(buf);
|
auto ubuf = reinterpret_cast<result_type*>(buf);
|
||||||
size_t q = len / sizeof(result_type);
|
size_t q = len / sizeof(result_type);
|
||||||
auto gen = std::uniform_int_distribution<result_type>();
|
auto gen = std::uniform_int_distribution<result_type>();
|
||||||
|
|
|
@ -54,8 +54,6 @@ private:
|
||||||
private:
|
private:
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
HCRYPTPROV provider_;
|
HCRYPTPROV provider_;
|
||||||
#elif defined(HAVE_GETRANDOM_INTERFACE)
|
|
||||||
// Nothing special needed
|
|
||||||
#else
|
#else
|
||||||
std::random_device dev_;
|
std::random_device dev_;
|
||||||
#endif // ! __MINGW32__
|
#endif // ! __MINGW32__
|
||||||
|
|
|
@ -37,14 +37,42 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "getrandom_linux.h"
|
#include "getrandom_linux.h"
|
||||||
|
|
||||||
int getrandom_linux(void *buf, size_t buflen) {
|
int getrandom_linux(void *buf, size_t buflen) {
|
||||||
|
int rv = 0;
|
||||||
|
uint8_t* p = buf;
|
||||||
|
while (buflen) {
|
||||||
|
int read;
|
||||||
#ifdef HAVE_GETRANDOM
|
#ifdef HAVE_GETRANDOM
|
||||||
return getrandom(buf, buflen, 0);
|
read = getrandom(p, buflen, 0);
|
||||||
#else // HAVE_GETRANDOM
|
#else // HAVE_GETRANDOM
|
||||||
return syscall(SYS_getrandom, buf, buflen, 0);
|
read = syscall(SYS_getrandom, p, buflen, 0);
|
||||||
|
/* Some libc impl. might mess this up */
|
||||||
|
if (read == -EINTR || read == -ERESTART) {
|
||||||
|
errno = EINTR;
|
||||||
|
read = -1;
|
||||||
|
}
|
||||||
|
if (read < -1) {
|
||||||
|
errno = -read;
|
||||||
|
read = -1;
|
||||||
|
}
|
||||||
#endif // HAVE_GETRANDOM
|
#endif // HAVE_GETRANDOM
|
||||||
|
if (read < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p += read;
|
||||||
|
rv += read;
|
||||||
|
buflen -= read;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue