Skip to content

Commit 0488d17

Browse files
authored
Reland "[Sanitizers] Intercept timer_create" (#113710) (#116717)
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
1 parent 2e0a3c2 commit 0488d17

File tree

5 files changed

+104
-0
lines changed

5 files changed

+104
-0
lines changed

compiler-rt/lib/hwasan/hwasan_platform_interceptors.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@
200200
#undef SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID
201201
#define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID 0
202202

203+
#undef SANITIZER_INTERCEPT_TIMER_CREATE
204+
#define SANITIZER_INTERCEPT_TIMER_CREATE 0
205+
203206
#undef SANITIZER_INTERCEPT_GETITIMER
204207
#define SANITIZER_INTERCEPT_GETITIMER 0
205208

compiler-rt/lib/msan/tests/msan_test.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4881,4 +4881,32 @@ TEST(MemorySanitizer, throw_catch) {
48814881
// pass
48824882
}
48834883
}
4884+
4885+
#if defined(__GLIBC__)
4886+
TEST(MemorySanitizer, timer_create) {
4887+
timer_t timer;
4888+
EXPECT_POISONED(timer);
4889+
int res = timer_create(CLOCK_REALTIME, nullptr, &timer);
4890+
ASSERT_EQ(0, res);
4891+
EXPECT_NOT_POISONED(timer);
4892+
4893+
// Make sure the timer is usable.
4894+
struct itimerspec cur_value {};
4895+
cur_value.it_value.tv_sec = 1;
4896+
EXPECT_EQ(0, timer_settime(timer, 0, &cur_value, nullptr));
4897+
4898+
struct itimerspec read_value;
4899+
EXPECT_POISONED(read_value);
4900+
EXPECT_EQ(0, timer_gettime(timer, &read_value));
4901+
EXPECT_NOT_POISONED(read_value);
4902+
4903+
timer_t timer2;
4904+
EXPECT_POISONED(timer2);
4905+
// Use an invalid clock_id to make timer_create fail.
4906+
res = timer_create(INT_MAX, nullptr, &timer2);
4907+
ASSERT_EQ(-1, res);
4908+
EXPECT_POISONED(timer2);
4909+
timer_delete(timer);
4910+
}
4911+
#endif
48844912
} // namespace

compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2289,6 +2289,61 @@ INTERCEPTOR(int, pthread_getcpuclockid, uptr thread,
22892289
#define INIT_CLOCK_GETCPUCLOCKID
22902290
#endif
22912291

2292+
#if SANITIZER_INTERCEPT_TIMER_CREATE
2293+
INTERCEPTOR(int, timer_create, __sanitizer_clockid_t clockid, void *sevp,
2294+
__sanitizer_timer_t *timer) {
2295+
void *ctx;
2296+
COMMON_INTERCEPTOR_ENTER(ctx, timer_create, clockid, sevp, timer);
2297+
int res = REAL(timer_create)(clockid, sevp, timer);
2298+
if (!res && timer) {
2299+
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, timer, sizeof *timer);
2300+
}
2301+
return res;
2302+
}
2303+
2304+
INTERCEPTOR(int, timer_delete, __sanitizer_timer_t timer) {
2305+
void *ctx;
2306+
COMMON_INTERCEPTOR_ENTER(ctx, timer_delete, timer);
2307+
int res = REAL(timer_delete)(timer);
2308+
return res;
2309+
}
2310+
2311+
INTERCEPTOR(int, timer_gettime, __sanitizer_timer_t timer,
2312+
struct __sanitizer_itimerspec *curr_value) {
2313+
void *ctx;
2314+
COMMON_INTERCEPTOR_ENTER(ctx, timer_gettime, timer, curr_value);
2315+
int res = REAL(timer_gettime)(timer, curr_value);
2316+
if (!res && curr_value) {
2317+
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, sizeof *curr_value);
2318+
}
2319+
return res;
2320+
}
2321+
2322+
INTERCEPTOR(int, timer_settime, __sanitizer_timer_t timer, int flags,
2323+
const struct __sanitizer_itimerspec *new_value,
2324+
struct __sanitizer_itimerspec *old_value) {
2325+
void *ctx;
2326+
COMMON_INTERCEPTOR_ENTER(ctx, timer_settime, timer, flags, new_value,
2327+
old_value);
2328+
int res = REAL(timer_settime)(timer, flags, new_value, old_value);
2329+
if (!res) {
2330+
if (new_value)
2331+
COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, sizeof *new_value);
2332+
if (old_value)
2333+
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, sizeof *old_value);
2334+
}
2335+
return res;
2336+
}
2337+
2338+
# define INIT_TIMER_CREATE \
2339+
COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_create, "GLIBC_2.3.3"); \
2340+
COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_delete, "GLIBC_2.3.3"); \
2341+
COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_gettime, "GLIBC_2.3.3"); \
2342+
COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_settime, "GLIBC_2.3.3");
2343+
#else
2344+
# define INIT_TIMER_CREATE
2345+
#endif
2346+
22922347
#if SANITIZER_INTERCEPT_GETITIMER
22932348
INTERCEPTOR(int, getitimer, int which, void *curr_value) {
22942349
void *ctx;
@@ -10266,6 +10321,7 @@ static void InitializeCommonInterceptors() {
1026610321
INIT_SETPWENT;
1026710322
INIT_CLOCK_GETTIME;
1026810323
INIT_CLOCK_GETCPUCLOCKID;
10324+
INIT_TIMER_CREATE;
1026910325
INIT_GETITIMER;
1027010326
INIT_TIME;
1027110327
INIT_GLOB;

compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,9 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
256256
(SI_FREEBSD || SI_NETBSD || SI_LINUX || SI_SOLARIS)
257257
#define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID \
258258
(SI_LINUX || SI_FREEBSD || SI_NETBSD)
259+
// TODO: This should be SI_POSIX, adding glibc first until I have time
260+
// to verify all timer_t typedefs on other platforms.
261+
#define SANITIZER_INTERCEPT_TIMER_CREATE SI_GLIBC
259262
#define SANITIZER_INTERCEPT_GETITIMER SI_POSIX
260263
#define SANITIZER_INTERCEPT_TIME SI_POSIX
261264
#define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS)

compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,16 @@ typedef long __sanitizer_time_t;
389389

390390
typedef long __sanitizer_suseconds_t;
391391

392+
struct __sanitizer_timespec {
393+
__sanitizer_time_t tv_sec; /* seconds */
394+
u64 tv_nsec; /* nanoseconds */
395+
};
396+
397+
struct __sanitizer_itimerspec {
398+
struct __sanitizer_timespec it_interval; /* timer period */
399+
struct __sanitizer_timespec it_value; /* timer expiration */
400+
};
401+
392402
struct __sanitizer_timeval {
393403
__sanitizer_time_t tv_sec;
394404
__sanitizer_suseconds_t tv_usec;
@@ -1517,6 +1527,10 @@ extern const int si_SEGV_ACCERR;
15171527

15181528
#define SIGACTION_SYMNAME sigaction
15191529

1530+
# if SANITIZER_LINUX
1531+
typedef void *__sanitizer_timer_t;
1532+
# endif
1533+
15201534
#endif // SANITIZER_LINUX || SANITIZER_APPLE
15211535

15221536
#endif

0 commit comments

Comments
 (0)