randgen.c (dovecot-2.3.16) | : | randgen.c (dovecot-2.3.17) | ||
---|---|---|---|---|
skipping to change at line 64 | skipping to change at line 64 | |||
# define USE_ARC4RANDOM | # define USE_ARC4RANDOM | |||
#else | #else | |||
static bool getrandom_present = FALSE; | static bool getrandom_present = FALSE; | |||
# define USE_RANDOM_DEV | # define USE_RANDOM_DEV | |||
#endif | #endif | |||
static int init_refcount = 0; | static int init_refcount = 0; | |||
static int urandom_fd = -1; | static int urandom_fd = -1; | |||
#if defined(USE_GETRANDOM) || defined(USE_RANDOM_DEV) | #if defined(USE_GETRANDOM) || defined(USE_RANDOM_DEV) | |||
/* Use a small buffer when reading randomness. This is mainly to make small | ||||
random reads more efficient, such as i_rand*(). When reading larger amount | ||||
of randomness this buffer is bypassed. | ||||
There doesn't seem to be a big difference in Linux system CPU usage when | ||||
buffer size is above 16 bytes. Double it just to be safe. Avoid it being | ||||
too large anyway so we don't unnecessarily waste CPU and memory. */ | ||||
#define RANDOM_READ_BUFFER_SIZE 32 | ||||
static unsigned char random_next[RANDOM_READ_BUFFER_SIZE]; | ||||
static size_t random_next_pos = 0; | ||||
static size_t random_next_size = 0; | ||||
static void random_open_urandom(void) | static void random_open_urandom(void) | |||
{ | { | |||
urandom_fd = open(DEV_URANDOM_PATH, O_RDONLY); | urandom_fd = open(DEV_URANDOM_PATH, O_RDONLY); | |||
if (urandom_fd == -1) { | if (urandom_fd == -1) { | |||
if (errno == ENOENT) { | if (errno == ENOENT) { | |||
i_fatal("open("DEV_URANDOM_PATH") failed: doesn't exist," | i_fatal("open("DEV_URANDOM_PATH") failed: doesn't exist," | |||
"currently we require it"); | "currently we require it"); | |||
} else { | } else { | |||
i_fatal("open("DEV_URANDOM_PATH") failed: %m"); | i_fatal("open("DEV_URANDOM_PATH") failed: %m"); | |||
} | } | |||
} | } | |||
fd_close_on_exec(urandom_fd, TRUE); | fd_close_on_exec(urandom_fd, TRUE); | |||
} | } | |||
static inline int random_read(char *buf, size_t size) | static inline int random_read(unsigned char *buf, size_t size) | |||
{ | { | |||
ssize_t ret = 0; | ssize_t ret = 0; | |||
# if defined(USE_GETRANDOM) | # if defined(USE_GETRANDOM) | |||
if (getrandom_present) { | if (getrandom_present) { | |||
ret = getrandom(buf, size, 0); | ret = getrandom(buf, size, 0); | |||
if (ret < 0 && errno == ENOSYS) { | if (ret < 0 && errno == ENOSYS) { | |||
getrandom_present = FALSE; | getrandom_present = FALSE; | |||
/* It gets complicated here... While the libc (and its | /* It gets complicated here... While the libc (and its | |||
headers) indicated that getrandom() was available when | headers) indicated that getrandom() was available when | |||
we were compiled, the kernel disagreed just now at | we were compiled, the kernel disagreed just now at | |||
skipping to change at line 135 | skipping to change at line 147 | |||
} | } | |||
#endif | #endif | |||
#if defined(USE_ARC4RANDOM) | #if defined(USE_ARC4RANDOM) | |||
arc4random_buf(buf, size); | arc4random_buf(buf, size); | |||
#else | #else | |||
size_t pos; | size_t pos; | |||
ssize_t ret; | ssize_t ret; | |||
for (pos = 0; pos < size; ) { | for (pos = 0; pos < size; ) { | |||
ret = random_read(PTR_OFFSET(buf, pos), size - pos); | if (size >= sizeof(random_next) && random_next_size == 0) { | |||
if (ret > -1) | /* Asking for lots of randomness. Read directly to the | |||
pos += ret; | destination buffer. */ | |||
ret = random_read(PTR_OFFSET(buf, pos), size - pos); | ||||
if (ret > -1) | ||||
pos += ret; | ||||
} else { | ||||
/* Asking for a little randomness. Read via a larger | ||||
buffer to reduce the number of syscalls. */ | ||||
if (random_next_size > random_next_pos) | ||||
ret = random_next_size - random_next_pos; | ||||
else { | ||||
random_next_pos = 0; | ||||
ret = random_read(random_next, | ||||
sizeof(random_next)); | ||||
random_next_size = ret < 0 ? 0 : ret; | ||||
} | ||||
if (ret > 0) { | ||||
size_t used = I_MIN(size - pos, (size_t)ret); | ||||
memcpy(PTR_OFFSET(buf, pos), | ||||
random_next + random_next_pos, used); | ||||
random_next_pos += used; | ||||
pos += used; | ||||
} | ||||
} | ||||
} | } | |||
#endif /* defined(USE_ARC4RANDOM) */ | #endif /* defined(USE_ARC4RANDOM) */ | |||
} | } | |||
void random_init(void) | void random_init(void) | |||
{ | { | |||
/* static analyzer seems to require this */ | /* static analyzer seems to require this */ | |||
unsigned int seed = 0; | unsigned int seed = 0; | |||
const char *env_seed; | const char *env_seed; | |||
End of changes. 3 change blocks. | ||||
4 lines changed or deleted | 38 lines changed or added |