[compiler-rt] c2aab0d - [MSAN] add interceptor for timer_create, timer_settime, timer_gettime
Kevin Athey via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 8 16:59:48 PST 2022
Author: Kevin Athey
Date: 2022-03-08T16:59:43-08:00
New Revision: c2aab0d3808b3e3058febe637148ca66b0f03c71
URL: https://github.com/llvm/llvm-project/commit/c2aab0d3808b3e3058febe637148ca66b0f03c71
DIFF: https://github.com/llvm/llvm-project/commit/c2aab0d3808b3e3058febe637148ca66b0f03c71.diff
LOG: [MSAN] add interceptor for timer_create, timer_settime, timer_gettime
Reviewed By: vitalybuka
Differential Revision: https://reviews.llvm.org/D120602
Added:
compiler-rt/test/sanitizer_common/TestCases/Posix/timer.cpp
Modified:
compiler-rt/lib/msan/tests/msan_test.cpp
compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h
compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h
compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.h
Removed:
################################################################################
diff --git a/compiler-rt/lib/msan/tests/msan_test.cpp b/compiler-rt/lib/msan/tests/msan_test.cpp
index 00b736e93adeb..ceb0d0eef9310 100644
--- a/compiler-rt/lib/msan/tests/msan_test.cpp
+++ b/compiler-rt/lib/msan/tests/msan_test.cpp
@@ -4679,6 +4679,40 @@ TEST(MemorySanitizer, LargeAllocatorUnpoisonsOnFree) {
munmap(q, 4096);
}
+TEST(MemorySanitizer, timer_create) {
+ struct sigevent sev {};
+ sev.sigev_notify = SIGEV_NONE;
+ timer_t timerid;
+ EXPECT_POISONED(timerid);
+ ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &sev, &timerid));
+ EXPECT_NOT_POISONED(timerid);
+}
+
+TEST(MemorySanitizer, timer_settime) {
+ struct sigevent sev {};
+ sev.sigev_notify = SIGEV_NONE;
+ timer_t timerid;
+ ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &sev, &timerid));
+ struct itimerspec new_value {};
+ new_value.it_interval.tv_sec = 10;
+ new_value.it_value.tv_sec = 10;
+ struct itimerspec old_value;
+ EXPECT_POISONED(old_value);
+ ASSERT_EQ(0, timer_settime(timerid, 0, &new_value, &old_value));
+ EXPECT_NOT_POISONED(old_value);
+}
+
+TEST(MemorySanitizer, timer_gettime) {
+ struct sigevent sev {};
+ sev.sigev_notify = SIGEV_NONE;
+ timer_t timerid;
+ ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &sev, &timerid));
+ struct itimerspec curr_value;
+ EXPECT_POISONED(curr_value);
+ ASSERT_EQ(0, timer_gettime(timerid, &curr_value));
+ EXPECT_NOT_POISONED(curr_value);
+}
+
#if SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE
TEST(MemorySanitizer, MallocUsableSizeTest) {
const size_t kArraySize = 100;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index b0ab08dff1db2..f19bc36d788d3 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -10211,6 +10211,51 @@ INTERCEPTOR(int, __xuname, int size, void *utsname) {
#define INIT___XUNAME
#endif
+#if SANITIZER_INTERCEPT_TIMER
+INTERCEPTOR(int, timer_create, __sanitizer_clockid_t clockid,
+ struct sigevent *sevp, __sanitizer_timer_t *timerid) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, timer_create, clockid, sevp, timerid);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(timer_create)(clockid, sevp, timerid);
+ if (!res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, timerid, sizeof(*timerid));
+ return res;
+}
+INTERCEPTOR(int, timer_settime, __sanitizer_timer_t timerid, int flags,
+ const void *new_value, void *old_value) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, timer_settime, timerid, flags, new_value,
+ old_value);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(timer_settime)(timerid, flags, new_value, old_value);
+ if (!res && old_value)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
+ return res;
+}
+INTERCEPTOR(int, timer_gettime, __sanitizer_timer_t timerid, void *curr_value) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, timer_gettime, timerid, curr_value);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(timer_gettime)(timerid, curr_value);
+ if (!res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz);
+ return res;
+}
+#define INIT_TIMER \
+ COMMON_INTERCEPT_FUNCTION(timer_create); \
+ COMMON_INTERCEPT_FUNCTION(timer_settime); \
+ COMMON_INTERCEPT_FUNCTION(timer_gettime);
+#else
+#define INIT_TIMER
+#endif
+
#include "sanitizer_common_interceptors_netbsd_compat.inc"
static void InitializeCommonInterceptors() {
@@ -10529,6 +10574,7 @@ static void InitializeCommonInterceptors() {
INIT_SIGALTSTACK;
INIT_UNAME;
INIT___XUNAME;
+ INIT_TIMER;
INIT___PRINTF_CHK;
}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
index 14610f2df78df..d8c1b76e55e8d 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -588,6 +588,8 @@
(SI_POSIX && !(SANITIZER_MAC && SANITIZER_I386))
#define SANITIZER_INTERCEPT_UNAME (SI_POSIX && !SI_FREEBSD)
#define SANITIZER_INTERCEPT___XUNAME SI_FREEBSD
+#define SANITIZER_INTERCEPT_TIMER \
+ (SI_FREEBSD || SI_NETBSD || SI_LINUX || SI_SOLARIS)
#define SANITIZER_INTERCEPT_FLOPEN SI_FREEBSD
// This macro gives a way for downstream users to override the above
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h
index 9859c52ec69f3..e89665034ec06 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h
@@ -255,6 +255,7 @@ struct __sanitizer_dirent {
// 'clock_t' is 32 bits wide on x64 FreeBSD
typedef int __sanitizer_clock_t;
typedef int __sanitizer_clockid_t;
+typedef void *__sanitizer_timer_t;
# if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
defined(__mips__)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h
index dc6eb59b2800e..98d05bb78ddb9 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h
@@ -259,6 +259,7 @@ struct __sanitizer_dirent {
typedef int __sanitizer_clock_t;
typedef int __sanitizer_clockid_t;
+typedef void *__sanitizer_timer_t;
typedef u32 __sanitizer___kernel_uid_t;
typedef u32 __sanitizer___kernel_gid_t;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index 054b5dd131bce..849255f43bba9 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -511,6 +511,7 @@ typedef long __sanitizer_clock_t;
#if SANITIZER_LINUX
typedef int __sanitizer_clockid_t;
+typedef void *__sanitizer_timer_t;
#endif
#if SANITIZER_LINUX
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.h
index 84a81265162c6..854e79fc0118b 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.h
@@ -235,6 +235,7 @@ struct __sanitizer_dirent64 {
typedef long __sanitizer_clock_t;
typedef int __sanitizer_clockid_t;
+typedef void *__sanitizer_timer_t;
// This thing depends on the platform. We are only interested in the upper
// limit. Verified with a compiler assert in .cpp.
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/timer.cpp b/compiler-rt/test/sanitizer_common/TestCases/Posix/timer.cpp
new file mode 100644
index 0000000000000..5da470d5a1dec
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/timer.cpp
@@ -0,0 +1,38 @@
+// RUN: %clangxx -O0 -g %s -o %t && %run %t
+// UNSUPPORTED: darwin
+#include <assert.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+int main(int argc, char **argv) {
+ struct sigevent sev {};
+ sev.sigev_notify = SIGEV_NONE;
+ timer_t timerid;
+ assert(timer_create(CLOCK_REALTIME, &sev, &timerid) == 0);
+
+ struct itimerspec new_value {};
+ new_value.it_value.tv_sec = 10;
+ new_value.it_value.tv_nsec = 1000000;
+ new_value.it_interval.tv_sec = new_value.it_value.tv_sec;
+ new_value.it_interval.tv_nsec = new_value.it_value.tv_nsec;
+
+ assert(timer_settime(timerid, 0, &new_value, nullptr) == 0);
+
+ struct itimerspec old_value;
+ assert(timer_settime(timerid, 0, &new_value, &old_value) == 0);
+ assert(old_value.it_interval.tv_sec == new_value.it_interval.tv_sec);
+ assert(old_value.it_interval.tv_nsec == new_value.it_interval.tv_nsec);
+ assert(old_value.it_value.tv_sec <= new_value.it_value.tv_sec);
+ assert(old_value.it_value.tv_nsec <= new_value.it_value.tv_nsec);
+
+ struct itimerspec curr_value;
+ assert(timer_gettime(timerid, &curr_value) == 0);
+ assert(curr_value.it_interval.tv_sec == new_value.it_interval.tv_sec);
+ assert(curr_value.it_interval.tv_nsec == new_value.it_interval.tv_nsec);
+ assert(curr_value.it_value.tv_sec <= new_value.it_value.tv_sec);
+ assert(curr_value.it_value.tv_nsec <= new_value.it_value.tv_nsec);
+
+ return 0;
+}
More information about the llvm-commits
mailing list