Skip to content

Reland "[Sanitizers] Intercept timer_create" (#113710) #116717

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler-rt/lib/hwasan/hwasan_platform_interceptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
28 changes: 28 additions & 0 deletions compiler-rt/lib/msan/tests/msan_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4881,4 +4881,32 @@ TEST(MemorySanitizer, throw_catch) {
// pass
}
}

#if defined(__GLIBC__)
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
56 changes: 56 additions & 0 deletions compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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"); \
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?

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;
Expand Down Expand Up @@ -10266,6 +10321,7 @@ static void InitializeCommonInterceptors() {
INIT_SETPWENT;
INIT_CLOCK_GETTIME;
INIT_CLOCK_GETCPUCLOCKID;
INIT_TIMER_CREATE;
INIT_GETITIMER;
INIT_TIME;
INIT_GLOB;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 glibc first until I have time
// to verify all timer_t typedefs on other platforms.
#define SANITIZER_INTERCEPT_TIMER_CREATE SI_GLIBC
#define SANITIZER_INTERCEPT_GETITIMER SI_POSIX
#define SANITIZER_INTERCEPT_TIME SI_POSIX
#define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS)
Expand Down
14 changes: 14 additions & 0 deletions compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Loading