Skip to content

Conversation

@fmayer
Copy link
Contributor

@fmayer fmayer commented Nov 19, 2024

Original commit 2ec5c69 only intercepted timer_create.

Because of how versioned libc symbols work, this could cause problems where a newer timer_create
was used, and the result would be used by an older version. This would cause crashes. This is why we
need to intercept all of the related functions.

Addresses #111847

Created using spr 1.3.4
@llvmbot llvmbot added compiler-rt compiler-rt:hwasan Hardware-assisted address sanitizer compiler-rt:msan Memory sanitizer compiler-rt:sanitizer labels Nov 19, 2024
@llvmbot
Copy link
Member

llvmbot commented Nov 19, 2024

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Florian Mayer (fmayer)

Changes

This reverts commit 2ec5c69.


Full diff: https://github.com/llvm/llvm-project/pull/116717.diff

5 Files Affected:

  • (modified) compiler-rt/lib/hwasan/hwasan_platform_interceptors.h (+3)
  • (modified) compiler-rt/lib/msan/tests/msan_test.cpp (+28)
  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc (+56)
  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h (+3)
  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h (+14)
diff --git a/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h b/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h
index d92b51052194275..e8011014c2331d7 100644
--- a/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h
+++ b/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h
@@ -200,6 +200,9 @@
 #undef SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID
 #define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID 0
 
+#undef SANITIZER_INTERCEPT_TIMER_CREATE
+#define SANITIZER_INTERCEPT_TIMER_CREATE 0
+
 #undef SANITIZER_INTERCEPT_GETITIMER
 #define SANITIZER_INTERCEPT_GETITIMER 0
 
diff --git a/compiler-rt/lib/msan/tests/msan_test.cpp b/compiler-rt/lib/msan/tests/msan_test.cpp
index 41b99fabe84f478..88f48adcb350f6e 100644
--- a/compiler-rt/lib/msan/tests/msan_test.cpp
+++ b/compiler-rt/lib/msan/tests/msan_test.cpp
@@ -4881,4 +4881,32 @@ TEST(MemorySanitizer, throw_catch) {
     // pass
   }
 }
+
+#if defined(__linux__)
+TEST(MemorySanitizer, timer_create) {
+  timer_t timer;
+  EXPECT_POISONED(timer);
+  int res = timer_create(CLOCK_REALTIME, nullptr, &timer);
+  ASSERT_EQ(0, res);
+  EXPECT_NOT_POISONED(timer);
+
+  // Make sure the timer is usable.
+  struct itimerspec cur_value{};
+  cur_value.it_value.tv_sec = 1;
+  EXPECT_EQ(0, timer_settime(timer, 0, &cur_value, nullptr));
+
+  struct itimerspec read_value;
+  EXPECT_POISONED(read_value);
+  EXPECT_EQ(0, timer_gettime(timer, &read_value));
+  EXPECT_NOT_POISONED(read_value);
+
+  timer_t timer2;
+  EXPECT_POISONED(timer2);
+  // Use an invalid clock_id to make timer_create fail.
+  res = timer_create(INT_MAX, nullptr, &timer2);
+  ASSERT_EQ(-1, res);
+  EXPECT_POISONED(timer2);
+  timer_delete(timer);
+}
+#endif
 } // namespace
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index b8627f8557afe29..99fa737adfaf26a 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -2289,6 +2289,61 @@ INTERCEPTOR(int, pthread_getcpuclockid, uptr thread,
 #define INIT_CLOCK_GETCPUCLOCKID
 #endif
 
+#if SANITIZER_INTERCEPT_TIMER_CREATE
+INTERCEPTOR(int, timer_create, __sanitizer_clockid_t clockid, void *sevp,
+            __sanitizer_timer_t *timer) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, timer_create, clockid, sevp, timer);
+  int res = REAL(timer_create)(clockid, sevp, timer);
+  if (!res && timer) {
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, timer, sizeof *timer);
+  }
+  return res;
+}
+
+INTERCEPTOR(int, timer_delete, __sanitizer_timer_t timer) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, timer_delete, timer);
+  int res = REAL(timer_delete)(timer);
+  return res;
+}
+
+INTERCEPTOR(int, timer_gettime, __sanitizer_timer_t timer,
+            struct __sanitizer_itimerspec *curr_value) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, timer_gettime, timer, curr_value);
+  int res = REAL(timer_gettime)(timer, curr_value);
+  if (!res && curr_value) {
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, sizeof *curr_value);
+  }
+  return res;
+}
+
+INTERCEPTOR(int, timer_settime, __sanitizer_timer_t timer, int flags,
+            const struct __sanitizer_itimerspec *new_value,
+            struct __sanitizer_itimerspec *old_value) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, timer_settime, timer, flags, new_value,
+                           old_value);
+  int res = REAL(timer_settime)(timer, flags, new_value, old_value);
+  if (!res) {
+    if (new_value)
+      COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, sizeof *new_value);
+    if (old_value)
+      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, sizeof *old_value);
+  }
+  return res;
+}
+
+#  define INIT_TIMER_CREATE                                                \
+    COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_create, "GLIBC_2.3.3");  \
+    COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_delete, "GLIBC_2.3.3");  \
+    COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_gettime, "GLIBC_2.3.3"); \
+    COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_settime, "GLIBC_2.3.3");
+#else
+#  define INIT_TIMER_CREATE
+#endif
+
 #if SANITIZER_INTERCEPT_GETITIMER
 INTERCEPTOR(int, getitimer, int which, void *curr_value) {
   void *ctx;
@@ -10266,6 +10321,7 @@ static void InitializeCommonInterceptors() {
   INIT_SETPWENT;
   INIT_CLOCK_GETTIME;
   INIT_CLOCK_GETCPUCLOCKID;
+  INIT_TIMER_CREATE;
   INIT_GETITIMER;
   INIT_TIME;
   INIT_GLOB;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
index 3fd6b595ef197f8..30be173369603d7 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -256,6 +256,9 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
   (SI_FREEBSD || SI_NETBSD || SI_LINUX || SI_SOLARIS)
 #define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID \
   (SI_LINUX || SI_FREEBSD || SI_NETBSD)
+// TODO: This should be SI_POSIX, adding Linux first until I have time
+// to verify all timer_t typedefs on other platforms.
+#define SANITIZER_INTERCEPT_TIMER_CREATE SI_LINUX
 #define SANITIZER_INTERCEPT_GETITIMER SI_POSIX
 #define SANITIZER_INTERCEPT_TIME SI_POSIX
 #define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS)
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 e8c81aa8e281637..7d98f8e9a9d8012 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -389,6 +389,16 @@ typedef long __sanitizer_time_t;
 
 typedef long __sanitizer_suseconds_t;
 
+struct __sanitizer_timespec {
+  __sanitizer_time_t tv_sec; /* seconds */
+  u64 tv_nsec;               /* nanoseconds */
+};
+
+struct __sanitizer_itimerspec {
+  struct __sanitizer_timespec it_interval; /* timer period */
+  struct __sanitizer_timespec it_value;    /* timer expiration */
+};
+
 struct __sanitizer_timeval {
   __sanitizer_time_t tv_sec;
   __sanitizer_suseconds_t tv_usec;
@@ -1517,6 +1527,10 @@ extern const int si_SEGV_ACCERR;
 
 #define SIGACTION_SYMNAME sigaction
 
+#  if SANITIZER_LINUX
+typedef void *__sanitizer_timer_t;
+#  endif
+
 #endif  // SANITIZER_LINUX || SANITIZER_APPLE
 
 #endif

@github-actions
Copy link

github-actions bot commented Nov 19, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Created using spr 1.3.4
Created using spr 1.3.4
@fmayer fmayer requested a review from vitalybuka November 19, 2024 01:05
Created using spr 1.3.4
@fmayer fmayer changed the title Reapply "[Sanitizers] Intercept timer_create" (#113710) Reland "[Sanitizers] Intercept timer_create" (#113710) Nov 19, 2024
@fmayer fmayer merged commit 0488d17 into main Nov 19, 2024
7 checks passed
@fmayer fmayer deleted the users/fmayer/spr/reapply-sanitizers-intercept-timer_create-113710 branch November 19, 2024 07:18
}

# define INIT_TIMER_CREATE \
COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_create, "GLIBC_2.3.3"); \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want to use GLIBC_VER_MIN then, maybe always default?

@llvm-ci
Copy link
Collaborator

llvm-ci commented Nov 19, 2024

LLVM Buildbot has detected a new failure on builder sanitizer-x86_64-linux-qemu running on sanitizer-buildbot4 while building compiler-rt at step 2 "annotate".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/139/builds/6590

Here is the relevant piece of the build log for the reference
Step 2 (annotate) failure: 'python ../sanitizer_buildbot/sanitizers/zorg/buildbot/builders/sanitizers/buildbot_selector.py' (failure)
...
[72/77] Generating ScudoCxxUnitTest-mips64-Test
[73/77] Generating ScudoCUnitTest-mips64-Test
[74/77] Generating ScudoUnitTestsObjects.primary_test.cpp.mips64.o
[75/77] Generating ScudoUnitTestsObjects.combined_test.cpp.mips64.o
[76/77] Generating ScudoUnitTest-mips64-Test
[76/77] Running Scudo Standalone tests
llvm-lit: /home/b/sanitizer-x86_64-linux-qemu/build/llvm-project/llvm/utils/lit/lit/main.py:72: note: The test suite configuration requested an individual test timeout of 0 seconds but a timeout of 900 seconds was requested on the command line. Forcing timeout to be 900 seconds.
-- Testing: 158 tests, 88 workers --
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90..
TIMEOUT: ScudoStandalone-Unit :: ./ScudoUnitTest-mips64-Test/69/140 (158 of 158)
******************** TEST 'ScudoStandalone-Unit :: ./ScudoUnitTest-mips64-Test/69/140' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:/home/b/sanitizer-x86_64-linux-qemu/build/llvm_build2_debug_mips64_qemu/lib/scudo/standalone/tests/./ScudoUnitTest-mips64-Test-ScudoStandalone-Unit-1661266-69-140.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=140 GTEST_SHARD_INDEX=69 /home/b/sanitizer-x86_64-linux-qemu/build/qemu_build/qemu-mips64 -L /usr/mips64-linux-gnuabi64 /home/b/sanitizer-x86_64-linux-qemu/build/llvm_build2_debug_mips64_qemu/lib/scudo/standalone/tests/./ScudoUnitTest-mips64-Test
--

Note: This is test shard 70 of 140.
[==========] Running 2 tests from 2 test suites.
[----------] Global test environment set-up.
[----------] 1 test from ScudoCombinedDeathTestBasicCombined14_AndroidConfig
[ RUN      ] ScudoCombinedDeathTestBasicCombined14_AndroidConfig.BasicCombined14
Stats: SizeClassAllocator64: 1M mapped (0M rss) in 19 allocations; remains 19; ReleaseToOsIntervalMs = 1000
  00 (    64): mapped:    256K popped:      13 pushed:       0 inuse:     13 total:    104 releases:      0 last released:      0K latest pushed bytes:      5K region: 0x55560686d000 (0x555606868000)
  27 ( 16400): mapped:    256K popped:       1 pushed:       0 inuse:      1 total:      8 releases:      0 last released:      0K latest pushed bytes:    112K region: 0x555616871000 (0x555616868000)
  28 ( 18448): mapped:    256K popped:       1 pushed:       0 inuse:      1 total:      8 releases:      0 last released:      0K latest pushed bytes:    126K region: 0x5555e6869000 (0x5555e6868000)
  29 ( 23056): mapped:    256K popped:       1 pushed:       0 inuse:      1 total:      8 releases:      0 last released:      0K latest pushed bytes:    157K region: 0x555676869000 (0x555676868000)
  30 ( 29456): mapped:    256K popped:       1 pushed:       0 inuse:      1 total:      8 releases:      0 last released:      0K latest pushed bytes:    201K region: 0x555716869000 (0x555716868000)
  31 ( 33296): mapped:    256K popped:       1 pushed:       0 inuse:      1 total:      7 releases:      0 last released:      0K latest pushed bytes:    195K region: 0x55573686a000 (0x555736868000)
  32 ( 65552): mapped:    256K popped:       1 pushed:       0 inuse:      1 total:      3 releases:      0 last released:      0K latest pushed bytes:    128K region: 0x5556e6874000 (0x5556e6868000)
Stats: MapAllocator: allocated 65 times (6504K), freed 65 times (6504K), remains 0 (0K) max 0M, Fragmented 0K
Stats: MapAllocatorCache: EntriesCount: 32, MaxEntriesCount: 32, MaxEntrySize: 2097152, ReleaseToOsIntervalMs = 1000
Stats: CacheRetrievalStats: SuccessRate: 0/0 (100.00%)
Cache Entry Info (Most Recent -> Least Recent):
  StartBlockAddress: 0x5557670ef000, EndBlockAddress: 0x555767109000, BlockSize: 106496 
  StartBlockAddress: 0x5557670cf000, EndBlockAddress: 0x5557670e7000, BlockSize: 98304 
  StartBlockAddress: 0x5557670af000, EndBlockAddress: 0x5557670c5000, BlockSize: 90112 
  StartBlockAddress: 0x55576708f000, EndBlockAddress: 0x5557670a3000, BlockSize: 81920 
  StartBlockAddress: 0x55576706f000, EndBlockAddress: 0x555767081000, BlockSize: 73728 
  StartBlockAddress: 0x55576703f000, EndBlockAddress: 0x55576705f000, BlockSize: 131072 
  StartBlockAddress: 0x55576701f000, EndBlockAddress: 0x55576703d000, BlockSize: 122880 
  StartBlockAddress: 0x555766fff000, EndBlockAddress: 0x55576701b000, BlockSize: 114688 
  StartBlockAddress: 0x555766fdf000, EndBlockAddress: 0x555766ff9000, BlockSize: 106496 
  StartBlockAddress: 0x555766fbf000, EndBlockAddress: 0x555766fd7000, BlockSize: 98304 
  StartBlockAddress: 0x555766f9f000, EndBlockAddress: 0x555766fb5000, BlockSize: 90112 
  StartBlockAddress: 0x555766f7f000, EndBlockAddress: 0x555766f93000, BlockSize: 81920 
  StartBlockAddress: 0x555766f5f000, EndBlockAddress: 0x555766f71000, BlockSize: 73728 
  StartBlockAddress: 0x555766f2f000, EndBlockAddress: 0x555766f4f000, BlockSize: 131072 
  StartBlockAddress: 0x555766f0f000, EndBlockAddress: 0x555766f2d000, BlockSize: 122880 
  StartBlockAddress: 0x555766eef000, EndBlockAddress: 0x555766f0b000, BlockSize: 114688 
Step 22 (scudo debug_mips64_qemu) failure: scudo debug_mips64_qemu (failure)
...
[72/77] Generating ScudoCxxUnitTest-mips64-Test
[73/77] Generating ScudoCUnitTest-mips64-Test
[74/77] Generating ScudoUnitTestsObjects.primary_test.cpp.mips64.o
[75/77] Generating ScudoUnitTestsObjects.combined_test.cpp.mips64.o
[76/77] Generating ScudoUnitTest-mips64-Test
[76/77] Running Scudo Standalone tests
llvm-lit: /home/b/sanitizer-x86_64-linux-qemu/build/llvm-project/llvm/utils/lit/lit/main.py:72: note: The test suite configuration requested an individual test timeout of 0 seconds but a timeout of 900 seconds was requested on the command line. Forcing timeout to be 900 seconds.
-- Testing: 158 tests, 88 workers --
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90..
TIMEOUT: ScudoStandalone-Unit :: ./ScudoUnitTest-mips64-Test/69/140 (158 of 158)
******************** TEST 'ScudoStandalone-Unit :: ./ScudoUnitTest-mips64-Test/69/140' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:/home/b/sanitizer-x86_64-linux-qemu/build/llvm_build2_debug_mips64_qemu/lib/scudo/standalone/tests/./ScudoUnitTest-mips64-Test-ScudoStandalone-Unit-1661266-69-140.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=140 GTEST_SHARD_INDEX=69 /home/b/sanitizer-x86_64-linux-qemu/build/qemu_build/qemu-mips64 -L /usr/mips64-linux-gnuabi64 /home/b/sanitizer-x86_64-linux-qemu/build/llvm_build2_debug_mips64_qemu/lib/scudo/standalone/tests/./ScudoUnitTest-mips64-Test
--

Note: This is test shard 70 of 140.
[==========] Running 2 tests from 2 test suites.
[----------] Global test environment set-up.
[----------] 1 test from ScudoCombinedDeathTestBasicCombined14_AndroidConfig
[ RUN      ] ScudoCombinedDeathTestBasicCombined14_AndroidConfig.BasicCombined14
Stats: SizeClassAllocator64: 1M mapped (0M rss) in 19 allocations; remains 19; ReleaseToOsIntervalMs = 1000
  00 (    64): mapped:    256K popped:      13 pushed:       0 inuse:     13 total:    104 releases:      0 last released:      0K latest pushed bytes:      5K region: 0x55560686d000 (0x555606868000)
  27 ( 16400): mapped:    256K popped:       1 pushed:       0 inuse:      1 total:      8 releases:      0 last released:      0K latest pushed bytes:    112K region: 0x555616871000 (0x555616868000)
  28 ( 18448): mapped:    256K popped:       1 pushed:       0 inuse:      1 total:      8 releases:      0 last released:      0K latest pushed bytes:    126K region: 0x5555e6869000 (0x5555e6868000)
  29 ( 23056): mapped:    256K popped:       1 pushed:       0 inuse:      1 total:      8 releases:      0 last released:      0K latest pushed bytes:    157K region: 0x555676869000 (0x555676868000)
  30 ( 29456): mapped:    256K popped:       1 pushed:       0 inuse:      1 total:      8 releases:      0 last released:      0K latest pushed bytes:    201K region: 0x555716869000 (0x555716868000)
  31 ( 33296): mapped:    256K popped:       1 pushed:       0 inuse:      1 total:      7 releases:      0 last released:      0K latest pushed bytes:    195K region: 0x55573686a000 (0x555736868000)
  32 ( 65552): mapped:    256K popped:       1 pushed:       0 inuse:      1 total:      3 releases:      0 last released:      0K latest pushed bytes:    128K region: 0x5556e6874000 (0x5556e6868000)
Stats: MapAllocator: allocated 65 times (6504K), freed 65 times (6504K), remains 0 (0K) max 0M, Fragmented 0K
Stats: MapAllocatorCache: EntriesCount: 32, MaxEntriesCount: 32, MaxEntrySize: 2097152, ReleaseToOsIntervalMs = 1000
Stats: CacheRetrievalStats: SuccessRate: 0/0 (100.00%)
Cache Entry Info (Most Recent -> Least Recent):
  StartBlockAddress: 0x5557670ef000, EndBlockAddress: 0x555767109000, BlockSize: 106496 
  StartBlockAddress: 0x5557670cf000, EndBlockAddress: 0x5557670e7000, BlockSize: 98304 
  StartBlockAddress: 0x5557670af000, EndBlockAddress: 0x5557670c5000, BlockSize: 90112 
  StartBlockAddress: 0x55576708f000, EndBlockAddress: 0x5557670a3000, BlockSize: 81920 
  StartBlockAddress: 0x55576706f000, EndBlockAddress: 0x555767081000, BlockSize: 73728 
  StartBlockAddress: 0x55576703f000, EndBlockAddress: 0x55576705f000, BlockSize: 131072 
  StartBlockAddress: 0x55576701f000, EndBlockAddress: 0x55576703d000, BlockSize: 122880 
  StartBlockAddress: 0x555766fff000, EndBlockAddress: 0x55576701b000, BlockSize: 114688 
  StartBlockAddress: 0x555766fdf000, EndBlockAddress: 0x555766ff9000, BlockSize: 106496 
  StartBlockAddress: 0x555766fbf000, EndBlockAddress: 0x555766fd7000, BlockSize: 98304 
  StartBlockAddress: 0x555766f9f000, EndBlockAddress: 0x555766fb5000, BlockSize: 90112 
  StartBlockAddress: 0x555766f7f000, EndBlockAddress: 0x555766f93000, BlockSize: 81920 
  StartBlockAddress: 0x555766f5f000, EndBlockAddress: 0x555766f71000, BlockSize: 73728 
  StartBlockAddress: 0x555766f2f000, EndBlockAddress: 0x555766f4f000, BlockSize: 131072 
  StartBlockAddress: 0x555766f0f000, EndBlockAddress: 0x555766f2d000, BlockSize: 122880 
  StartBlockAddress: 0x555766eef000, EndBlockAddress: 0x555766f0b000, BlockSize: 114688 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

compiler-rt:hwasan Hardware-assisted address sanitizer compiler-rt:msan Memory sanitizer compiler-rt:sanitizer compiler-rt

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants