Skip to content

Instantly share code, notes, and snippets.

@ethercflow
Created January 11, 2020 11:30
Show Gist options
  • Save ethercflow/129d6c91e5f5564eb28db5ace960655b to your computer and use it in GitHub Desktop.
Save ethercflow/129d6c91e5f5564eb28db5ace960655b to your computer and use it in GitHub Desktop.
#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