[compiler-rt] r305922 - [sanitizer] Add a function to gather random bytes

Kostya Kortchinsky via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 21 08:56:03 PDT 2017


Author: cryptoad
Date: Wed Jun 21 10:56:03 2017
New Revision: 305922

URL: http://llvm.org/viewvc/llvm-project?rev=305922&view=rev
Log:
[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

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h?rev=305922&r1=305921&r2=305922&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Wed Jun 21 10:56:03 2017
@@ -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,

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=305922&r1=305921&r2=305922&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc Wed Jun 21 10:56:03 2017
@@ -1604,6 +1604,32 @@ uptr FindAvailableMemoryRange(uptr size,
   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

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc?rev=305922&r1=305921&r2=305922&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc Wed Jun 21 10:56:03 2017
@@ -923,6 +923,11 @@ void CheckNoDeepBind(const char *filenam
   // Do nothing.
 }
 
+// FIXME: implement on this platform.
+bool GetRandom(void *buffer, uptr length) {
+  UNIMPLEMENTED();
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_MAC

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc?rev=305922&r1=305921&r2=305922&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc Wed Jun 21 10:56:03 2017
@@ -1002,6 +1002,11 @@ void CheckNoDeepBind(const char *filenam
   // Do nothing.
 }
 
+// FIXME: implement on this platform.
+bool GetRandom(void *buffer, uptr length) {
+  UNIMPLEMENTED();
+}
+
 }  // namespace __sanitizer
 
 #endif  // _WIN32

Modified: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc?rev=305922&r1=305921&r2=305922&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc Wed Jun 21 10:56:03 2017
@@ -300,4 +300,21 @@ TEST(SanitizerCommon, InternalScopedStri
   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




More information about the llvm-commits mailing list