mirror of
https://github.com/aria2/aria2.git
synced 2025-01-04 09:03:46 +00:00
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-336
This commit is contained in:
parent
9cbbe9f1bb
commit
ba0e32abae
@ -42,6 +42,8 @@
|
||||
|
||||
#include "a2time.h"
|
||||
#include "a2functional.h"
|
||||
#include "LogFactory.h"
|
||||
#include "fmt.h"
|
||||
|
||||
#ifdef HAVE_GETRANDOM_INTERFACE
|
||||
# include "getrandom_linux.h"
|
||||
@ -88,10 +90,24 @@ void SimpleRandomizer::getRandomBytes(unsigned char* buf, size_t len)
|
||||
#ifdef __MINGW32__
|
||||
BOOL r = CryptGenRandom(provider_, len, reinterpret_cast<BYTE*>(buf));
|
||||
assert(r);
|
||||
#elif defined(HAVE_GETRANDOM_INTERFACE)
|
||||
auto rv = getrandom_linux(buf, len);
|
||||
assert(rv >= 0 && (size_t)rv == len);
|
||||
#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);
|
||||
size_t q = len / sizeof(result_type);
|
||||
auto gen = std::uniform_int_distribution<result_type>();
|
||||
|
@ -54,8 +54,6 @@ private:
|
||||
private:
|
||||
#ifdef __MINGW32__
|
||||
HCRYPTPROV provider_;
|
||||
#elif defined(HAVE_GETRANDOM_INTERFACE)
|
||||
// Nothing special needed
|
||||
#else
|
||||
std::random_device dev_;
|
||||
#endif // ! __MINGW32__
|
||||
|
@ -37,14 +37,42 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/random.h>
|
||||
#include <errno.h>
|
||||
#include <linux/errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "getrandom_linux.h"
|
||||
|
||||
int getrandom_linux(void *buf, size_t buflen) {
|
||||
int rv = 0;
|
||||
uint8_t* p = buf;
|
||||
while (buflen) {
|
||||
int read;
|
||||
#ifdef HAVE_GETRANDOM
|
||||
return getrandom(buf, buflen, 0);
|
||||
read = getrandom(p, buflen, 0);
|
||||
#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
|
||||
if (read < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
p += read;
|
||||
rv += read;
|
||||
buflen -= read;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user