diff options
| author | Kostya Kortchinsky <kostyak@google.com> | 2017-06-21 15:56:03 +0000 |
|---|---|---|
| committer | Kostya Kortchinsky <kostyak@google.com> | 2017-06-21 15:56:03 +0000 |
| commit | 2b053b1c28bd1df6475ae133766db2f52dd564e8 (patch) | |
| tree | 60a44660705e270db65616539603fc30561a4510 /compiler-rt/lib/sanitizer_common/sanitizer_linux.cc | |
| parent | c1b6aa77bbdb7c022a47f435ecfc557f01988d3f (diff) | |
| download | bcm5719-llvm-2b053b1c28bd1df6475ae133766db2f52dd564e8.tar.gz bcm5719-llvm-2b053b1c28bd1df6475ae133766db2f52dd564e8.zip | |
[sanitizer] Add a function to gather random bytes
Summary:
AFAICT compiler-rt doesn't have a function that would return 'good' random
bytes to seed a PRNG. Currently, the `SizeClassAllocator64` uses addresses
returned by `mmap` to seed its PRNG, which is not ideal, and
`SizeClassAllocator32` doesn't benefit from the entropy offered by its 64-bit
counterpart address space, so right now it has nothing. This function aims at
solving this, allowing to implement good 32-bit chunk randomization. Scudo also
has a function that does this for Cookie purposes, which would go away in a
later CL once this lands.
This function will try the `getrandom` syscall if available, and fallback to
`/dev/urandom` if not.
Unfortunately, I do not have a way to implement and test a Mac and Windows
version, so those are unimplemented as of now. Note that `kRandomShuffleChunks`
is only used on Linux for now.
Reviewers: alekseyshl
Reviewed By: alekseyshl
Subscribers: zturner, rnk, llvm-commits, kubamracek
Differential Revision: https://reviews.llvm.org/D34412
llvm-svn: 305922
Diffstat (limited to 'compiler-rt/lib/sanitizer_common/sanitizer_linux.cc')
| -rw-r--r-- | compiler-rt/lib/sanitizer_common/sanitizer_linux.cc | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index d31c49d694a..a94a63c7f16 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -1604,6 +1604,32 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding) { return 0; } +bool GetRandom(void *buffer, uptr length) { + if (!buffer || !length || length > 256) + return false; +#if defined(__NR_getrandom) + static atomic_uint8_t skip_getrandom_syscall; + if (!atomic_load_relaxed(&skip_getrandom_syscall)) { + // Up to 256 bytes, getrandom will not be interrupted. + uptr res = internal_syscall(SYSCALL(getrandom), buffer, length, 0); + int rverrno = 0; + if (internal_iserror(res, &rverrno) && rverrno == ENOSYS) + atomic_store_relaxed(&skip_getrandom_syscall, 1); + else if (res == length) + return true; + } +#endif + uptr fd = internal_open("/dev/urandom", O_RDONLY); + if (internal_iserror(fd)) + return false; + // internal_read deals with EINTR. + uptr res = internal_read(fd, buffer, length); + if (internal_iserror(res)) + return false; + internal_close(fd); + return true; +} + } // namespace __sanitizer #endif // SANITIZER_FREEBSD || SANITIZER_LINUX |

