Created
January 11, 2020 11:30
-
-
Save ethercflow/129d6c91e5f5564eb28db5ace960655b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <uapi/linux/ptrace.h> | |
#include <linux/time.h> | |
#define NANOS_PER_SEC 1000000000 | |
#define MICROS_PER_SEC 1000000 | |
#define MAX_JMP_SEQ 8192 | |
struct clock_filter { | |
long sec; | |
union { | |
long nsec; | |
long usec; | |
}; | |
union { | |
struct timespec *ts; | |
struct timeval *tv; | |
}; | |
}; | |
BPF_HASH(clock_filters, u32, struct clock_filter); | |
int syscall__clock_gettime_entry(struct pt_regs *ctx, | |
clockid_t cid, struct timespec *ts) | |
{ | |
u64 id = bpf_get_current_pid_tgid(); | |
struct clock_filter *cf = NULL; | |
PID_TID_FILTER; | |
cf = clock_filters.lookup(&fid); | |
if (!cf) | |
return 0; | |
cf->ts = ts; | |
return 0; | |
} | |
static inline void balance_timespec_m(struct timespec *t) { | |
for (u16 i = 0; i < MAX_JMP_SEQ && t->tv_nsec <= NANOS_PER_SEC; i++) { | |
t->tv_sec -= 1; | |
t->tv_nsec += NANOS_PER_SEC; | |
} | |
for (u16 i = 0; i < MAX_JMP_SEQ && NANOS_PER_SEC <= t->tv_nsec; i++) { | |
t->tv_sec += 1; | |
t->tv_nsec -= NANOS_PER_SEC; | |
} | |
} | |
int do_ret_sys_clock_gettime_return(struct pt_regs *ctx) | |
{ | |
u64 id = bpf_get_current_pid_tgid(); | |
struct clock_filter *cf = NULL; | |
struct timespec *ts = NULL; | |
struct timespec nts = {}; | |
s64 tv_sec = 0; | |
s64 tv_nsec = 0; | |
PID_TID_FILTER; | |
cf = clock_filters.lookup(&fid); | |
if (!cf) | |
return 0; | |
ts = cf->ts; | |
bpf_probe_read(&tv_nsec, sizeof(tv_nsec), &ts->tv_nsec); | |
bpf_probe_read(&tv_sec, sizeof(tv_sec), &ts->tv_sec); | |
nts.tv_nsec = tv_nsec + cf->nsec; | |
nts.tv_sec = tv_sec + cf->sec; | |
balance_timespec_m(&nts); | |
bpf_probe_write_user(ts, &nts, sizeof(nts)); | |
return 0; | |
} | |
int syscall__gettimeofday_entry(struct pt_regs *ctx, | |
struct timeval *tv, struct timezone *tz) | |
{ | |
u64 id = bpf_get_current_pid_tgid(); | |
struct clock_filter *cf = NULL; | |
PID_TID_FILTER; | |
cf = clock_filters.lookup(&fid); | |
if (!cf) | |
return 0; | |
cf->tv = tv; | |
return 0; | |
} | |
static inline void balance_timeval_m(struct timeval *t) { | |
for (u16 i = 0; i < MAX_JMP_SEQ && t->tv_sec <= MICROS_PER_SEC; i++) { | |
t->tv_sec -= 1; | |
t->tv_usec += MICROS_PER_SEC; | |
} | |
for (u16 i = 0; i < MAX_JMP_SEQ && MICROS_PER_SEC <= t->tv_usec; i++) { | |
t->tv_sec += 1; | |
t->tv_usec -= MICROS_PER_SEC; | |
} | |
} | |
int do_ret_sys_gettimeofday_return(struct pt_regs *ctx) | |
{ | |
u64 id = bpf_get_current_pid_tgid(); | |
struct clock_filter *cf = NULL; | |
struct timeval *tv = NULL; | |
struct timeval ntv = {}; | |
s64 tv_sec = 0; | |
s64 tv_usec = 0; | |
PID_TID_FILTER; | |
cf = clock_filters.lookup(&fid); | |
if (!cf) | |
return 0; | |
tv = cf->tv; | |
bpf_probe_read(&tv_usec, sizeof(tv_usec), &tv->tv_usec); | |
bpf_probe_read(&tv_sec, sizeof(tv_sec), &tv->tv_sec); | |
ntv.tv_sec = tv_sec + cf->sec; | |
ntv.tv_usec = tv_usec + cf->usec; | |
balance_timeval_m(&ntv); | |
bpf_probe_write_user(tv, &ntv, sizeof(ntv)); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment