mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 19:06:44 +00:00
[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
This commit is contained in:
parent
c1b6aa77bb
commit
2b053b1c28
@ -919,6 +919,10 @@ const s32 kReleaseToOSIntervalNever = -1;
|
||||
|
||||
void CheckNoDeepBind(const char *filename, int flag);
|
||||
|
||||
// Returns the requested amount of random data (up to 256 bytes) that can then
|
||||
// be used to seed a PRNG.
|
||||
bool GetRandom(void *buffer, uptr length);
|
||||
|
||||
} // namespace __sanitizer
|
||||
|
||||
inline void *operator new(__sanitizer::operator_new_size_type size,
|
||||
|
@ -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
|
||||
|
@ -923,6 +923,11 @@ void CheckNoDeepBind(const char *filename, int flag) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
// FIXME: implement on this platform.
|
||||
bool GetRandom(void *buffer, uptr length) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
} // namespace __sanitizer
|
||||
|
||||
#endif // SANITIZER_MAC
|
||||
|
@ -1002,6 +1002,11 @@ void CheckNoDeepBind(const char *filename, int flag) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
// FIXME: implement on this platform.
|
||||
bool GetRandom(void *buffer, uptr length) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
} // namespace __sanitizer
|
||||
|
||||
#endif // _WIN32
|
||||
|
@ -300,4 +300,21 @@ TEST(SanitizerCommon, InternalScopedString) {
|
||||
EXPECT_STREQ("012345678", str.data());
|
||||
}
|
||||
|
||||
#if SANITIZER_LINUX
|
||||
TEST(SanitizerCommon, GetRandom) {
|
||||
u8 buffer_1[32], buffer_2[32];
|
||||
EXPECT_FALSE(GetRandom(nullptr, 32));
|
||||
EXPECT_FALSE(GetRandom(buffer_1, 0));
|
||||
EXPECT_FALSE(GetRandom(buffer_1, 512));
|
||||
EXPECT_EQ(ARRAY_SIZE(buffer_1), ARRAY_SIZE(buffer_2));
|
||||
for (uptr size = 4; size <= ARRAY_SIZE(buffer_1); size += 4) {
|
||||
for (uptr i = 0; i < 100; i++) {
|
||||
EXPECT_TRUE(GetRandom(buffer_1, size));
|
||||
EXPECT_TRUE(GetRandom(buffer_2, size));
|
||||
EXPECT_NE(internal_memcmp(buffer_1, buffer_2, size), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace __sanitizer
|
||||
|
Loading…
x
Reference in New Issue
Block a user