diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -9550,6 +9550,22 @@ #define INIT_SL_INIT #endif +#if SANITIZER_INTERCEPT_GETRANDOM +INTERCEPTOR(SSIZE_T, getrandom, void* buf, SIZE_T buflen, unsigned int flags) { + void* ctx; + COMMON_INTERCEPTOR_ENTER(ctx, getrandom, buf, buflen, flags); + SSIZE_T n = REAL(getrandom)(buf, buflen, flags); + if (n > 0) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, n); + } + return n; +} +#define INIT_GETRANDOM \ + COMMON_INTERCEPT_FUNCTION(getrandom) +#else +#define INIT_GETRANDOM +#endif + static void InitializeCommonInterceptors() { #if SI_POSIX static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1]; @@ -9848,6 +9864,7 @@ INIT_FDEVNAME; INIT_GETUSERSHELL; INIT_SL_INIT; + INIT_GETRANDOM; INIT___PRINTF_CHK; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc @@ -2873,6 +2873,19 @@ POST_WRITE(oldact, oldact_sz); } } + +PRE_SYSCALL(getrandom)(void *buf, uptr count, long flags) { + if (buf) { + PRE_WRITE(buf, count); + } +} + +POST_SYSCALL(getrandom)(long res, void *buf, uptr count, long flags) { + if (res > 0 && buf) { + POST_WRITE(buf, res); + } +} + } // extern "C" #undef PRE_SYSCALL diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -566,4 +566,6 @@ #define SANITIZER_INTERCEPT_GETUSERSHELL (SI_POSIX && !SI_POSIX) #define SANITIZER_INTERCEPT_SL_INIT (SI_FREEBSD || SI_NETBSD) +#define SANITIZER_INTERCEPT_GETRANDOM SI_LINUX + #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/getrandom.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/getrandom.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/getrandom.cpp @@ -0,0 +1,22 @@ +// RUN: %clangxx -O2 %s -o %t && %run %t +// UNSUPPORTED: android +// + +#include + +#if !defined(__GLIBC_PREREQ) +#define __GLIBC_PREREQ(a, b) 0 +#endif + +#if __GLIBC_PREREQ(2, 25) +#include +#endif + +int main() { + char buf[16]; + ssize_t n = 1; +#if __GLIBC_PREREQ(2, 25) + n = getrandom(buf, sizeof(buf), 0); +#endif + return (int)(n <= 0); +}