From ee4f57d8a581fe2fb826d820954eecc0c33e8724 Mon Sep 17 00:00:00 2001 From: Wolfgang Hommel Date: Wed, 16 Feb 2022 21:27:08 +0100 Subject: Additional dyld interposing for macOS Monterey support (addresses #357) --- src/Makefile.OSX | 20 ++++++++++++++++--- src/libfaketime.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/Makefile.OSX b/src/Makefile.OSX index ee9efde..d5f4c88 100644 --- a/src/Makefile.OSX +++ b/src/Makefile.OSX @@ -18,8 +18,22 @@ # without this, but the performance impact may require you to # try it unsynchronized. # -# FAKE_SLEEP -# - Also intercept sleep(), nanosleep(), usleep(), alarm(), [p]poll() +# FAKE_SLEEP +# - Also intercept sleep(), nanosleep(), usleep(), alarm(), [p]poll() +# +# MACOS_DYLD_INTERPOSE +# - Use dlyd interposing instead of name-based function interception +# (required since macOS Monterey) +# +# FAKE_RANDOM +# - Intercept getentropy(). Dangerous for production use. +# See README about FAKE_RANDOM. +# +# FAKE_SETTIME +# - Intercept clock_settime(), settimeofday(), and adjtime() +# +# FAKE_PID +# - Enable faked values for getpid() calls through FAKETIME_FAKEPID # # * Compilation addition: second libMT target added for building the pthread- # enabled library as a separate library @@ -38,7 +52,7 @@ INSTALL ?= install PREFIX ?= /usr/local -CFLAGS += -DFAKE_SLEEP -DFAKE_INTERNAL_CALLS -DPREFIX='"'${PREFIX}'"' $(FAKETIME_COMPILE_CFLAGS) -DMACOS_DYLD_INTERPOSE +CFLAGS += -DFAKE_SLEEP -DFAKE_INTERNAL_CALLS -DPREFIX='"'${PREFIX}'"' $(FAKETIME_COMPILE_CFLAGS) -DMACOS_DYLD_INTERPOSE -DFAKE_SETTIME LIB_LDFLAGS += -dynamiclib -current_version 0.9.9 -compatibility_version 0.7 SONAME = 1 diff --git a/src/libfaketime.c b/src/libfaketime.c index 2583370..228b766 100644 --- a/src/libfaketime.c +++ b/src/libfaketime.c @@ -3802,7 +3802,11 @@ __asm__(".symver pthread_cond_destroy_232, pthread_cond_destroy@@GLIBC_2.3.2"); * Based on suggestion and prototype by @ojura, see https://github.com/wolfcw/libfaketime/issues/179 */ #ifdef FAKE_SETTIME +#ifdef MACOS_DYLD_INTERPOSE +int macos_clock_settime(clockid_t clk_id, const struct timespec *tp) { +#else int clock_settime(clockid_t clk_id, const struct timespec *tp) { +#endif /* only CLOCK_REALTIME can be set */ if (clk_id != CLOCK_REALTIME) { @@ -3820,7 +3824,11 @@ int clock_settime(clockid_t clk_id, const struct timespec *tp) { we do not have to care about 'x' or 'i' modifiers given previously, as they are not erased when parsing them. */ struct timespec current_time; +#ifdef MACOS_DYLD_INTERPOSE + DONT_FAKE_TIME(macos_clock_gettime(clk_id, ¤t_time)) +#else DONT_FAKE_TIME(clock_gettime(clk_id, ¤t_time)) +#endif ; time_t sec_diff = tp->tv_sec - current_time.tv_sec; @@ -3873,7 +3881,11 @@ int clock_settime(clockid_t clk_id, const struct timespec *tp) { return 0; } +#ifdef MACOS_DYLD_INTERPOSE +int macos_settimeofday(const struct timeval *tv, void *tz) +#else int settimeofday(const struct timeval *tv, void *tz) +#endif { /* The use of timezone *tz is obsolete and simply ignored here. */ if (tz == NULL) tz = NULL; @@ -3888,12 +3900,20 @@ int settimeofday(const struct timeval *tv, void *tz) struct timespec tp; tp.tv_sec = tv->tv_sec; tp.tv_nsec = tv->tv_usec * 1000; +#ifdef MACOS_DYLD_INTERPOSE + macos_clock_settime(CLOCK_REALTIME, &tp); +#else clock_settime(CLOCK_REALTIME, &tp); +#endif } return 0; } +#ifdef MACOS_DYLD_INTERPOSE +int macos_adjtime (const struct timeval *delta, struct timeval *olddelta) +#else int adjtime (const struct timeval *delta, struct timeval *olddelta) +#endif { /* Always signal true full success when olddelta is requested. */ if (olddelta != NULL) @@ -3905,14 +3925,22 @@ int adjtime (const struct timeval *delta, struct timeval *olddelta) if (delta != NULL) { struct timespec tp; +#ifdef MACOS_DYLD_INTERPOSE + macos_clock_gettime(CLOCK_REALTIME, &tp); +#else clock_gettime(CLOCK_REALTIME, &tp); +#endif tp.tv_sec += delta->tv_sec; tp.tv_nsec += delta->tv_usec * 1000; /* This actually will make the clock jump instead of gradually adjusting it, but we fulfill the caller's intention and an additional thread just for the gradual changes does not seem to be worth the effort presently. */ +#ifdef MACOS_DYLD_INTERPOSE clock_settime(CLOCK_REALTIME, &tp); +#else + clock_settime(CLOCK_REALTIME, &tp); +#endif } return 0; } @@ -3960,19 +3988,31 @@ ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) { return real_getrandom(buf, buflen, flags); } } +#ifdef MACOS_DYLD_INTERPOSE +int macos_getentropy(void *buffer, size_t length) { +#else int getentropy(void *buffer, size_t length) { +#endif if (bypass_randomness(buffer, length)) { return 0; } else { if (!initialized) ftpl_init(); +#ifdef MACOS_DYLD_INTERPOSE + return getentropy(buffer, length); +#else return real_getentropy(buffer, length); +#endif } } #endif #ifdef FAKE_PID +#ifdef MACOS_DYLD_INTERPOSE +pid_t macos_getpid() { +#else pid_t getpid() { +#endif const char *pidstring = getenv("FAKETIME_FAKEPID"); if (pidstring != NULL) { long int pid = strtol(pidstring, NULL, 0); @@ -4026,17 +4066,30 @@ long syscall(long number, ...) { #ifdef MACOS_DYLD_INTERPOSE void do_macos_dyld_interpose(void) { - DYLD_INTERPOSE(macos_alarm, alarm); DYLD_INTERPOSE(macos_clock_gettime, clock_gettime); DYLD_INTERPOSE(macos_gettimeofday, gettimeofday); DYLD_INTERPOSE(macos_time, time); DYLD_INTERPOSE(macos_ftime, ftime); +#ifdef FAKE_SLEEP + DYLD_INTERPOSE(macos_alarm, alarm); DYLD_INTERPOSE(macos_sleep, sleep); DYLD_INTERPOSE(macos_usleep, usleep); DYLD_INTERPOSE(macos_nanosleep, nanosleep); DYLD_INTERPOSE(macos_poll, poll); - DYLD_INTERPOSE(macos_select, select); +#endif DYLD_INTERPOSE(macos_timespec_get, timespec_get); + DYLD_INTERPOSE(macos_select, select); +#ifdef FAKE_RANDOM + DYLD_INTERPOSE(macos_getentropy, getentropy); +#endif +#ifdef FAKE_SETTIME + DYLD_INTERPOSE(macos_clock_settime, clock_settime); + DYLD_INTERPOSE(macos_settimeofday, settimeofday); + DYLD_INTERPOSE(macos_adjtime, adjtime); +#endif +#ifdef FAKE_PID + DYLD_INTERPOSE(macos_getpid, getpid); +#endif } #endif -- cgit v1.2.1