GetRandom / OpenBSD, using getentropy to get high quality randomness

Summary:
- getentropy presence since late 2014, safe to use.
- guarantees to delivers good random data up to 256 bytes.
- fall back to /dev/urandom as long the buffer is correct.

Patch by David CARLIER

Reviewers: kubamracek, vitalybuka

Reviewed By: vitalybuka

Subscribers: cryptoad, llvm-commits, #sanitizers

Differential Revision: https://reviews.llvm.org/D44866

llvm-svn: 329633
This commit is contained in:
Vitaly Buka 2018-04-09 22:46:40 +00:00
parent 2a84e4ab12
commit 3539c09d3b

View File

@ -140,6 +140,9 @@ extern void internal_sigreturn();
}
#endif
// Note : FreeBSD had implemented both
// Linux and OpenBSD apis, available from
// future 12.x version most likely
#if SANITIZER_LINUX && defined(__NR_getrandom)
# if !defined(GRND_NONBLOCK)
# define GRND_NONBLOCK 1
@ -149,6 +152,12 @@ extern void internal_sigreturn();
# define SANITIZER_USE_GETRANDOM 0
#endif // SANITIZER_LINUX && defined(__NR_getrandom)
#if SANITIZER_OPENBSD
# define SANITIZER_USE_GETENTROPY 1
#else
# define SANITIZER_USE_GETENTROPY 0
#endif // SANITIZER_USE_GETENTROPY
namespace __sanitizer {
#if SANITIZER_LINUX && defined(__x86_64__)
@ -1906,6 +1915,15 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
bool GetRandom(void *buffer, uptr length, bool blocking) {
if (!buffer || !length || length > 256)
return false;
#if SANITIZER_USE_GETENTROPY
uptr rnd = getentropy(buffer, length);
int rverrno = 0;
if (internal_iserror(rnd, &rverrno) && rverrno == EFAULT)
return false;
else if (rnd == 0)
return true;
#endif // SANITIZER_USE_GETENTROPY
#if SANITIZER_USE_GETRANDOM
static atomic_uint8_t skip_getrandom_syscall;
if (!atomic_load_relaxed(&skip_getrandom_syscall)) {
@ -1918,7 +1936,7 @@ bool GetRandom(void *buffer, uptr length, bool blocking) {
else if (res == length)
return true;
}
#endif // SANITIZER_USE_GETRANDOM
#endif // SANITIZER_USE_GETRANDOM
// Up to 256 bytes, a read off /dev/urandom will not be interrupted.
// blocking is moot here, O_NONBLOCK has no effect when opening /dev/urandom.
uptr fd = internal_open("/dev/urandom", O_RDONLY);