| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,93 @@ |
| 1 |
+/* |
|
| 2 |
+ * libyesterday.c |
|
| 3 |
+ * |
|
| 4 |
+ * Captures gettimeofday(), time() and clock_gettime() to simulate yesterday's date |
|
| 5 |
+ * |
|
| 6 |
+ * History: |
|
| 7 |
+ * 01/11/2025 Creation. |
|
| 8 |
+ * |
|
| 9 |
+ * Documentation: |
|
| 10 |
+ * https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/ |
|
| 11 |
+ * |
|
| 12 |
+ * Usage examples: |
|
| 13 |
+ * # load date program with day set to yesterday |
|
| 14 |
+ * LD_PRELOAD=/path/to/libyesterday.so /bin/date |
|
| 15 |
+ * # load date program with day set to a week ago |
|
| 16 |
+ * LIBYESTERDAY=$((3600*24*7)) LD_PRELOAD=/path/to/libyesterday.so /bin/date |
|
| 17 |
+ * |
|
| 18 |
+ * Author: Dario Rodriguez antartica@whereismybit.com |
|
| 19 |
+ * This program is licensed under the terms of the MIT/X license. |
|
| 20 |
+ */ |
|
| 21 |
+ |
|
| 22 |
+#define _GNU_SOURCE |
|
| 23 |
+#include <dlfcn.h> |
|
| 24 |
+#include <time.h> |
|
| 25 |
+#include <sys/time.h> |
|
| 26 |
+#include <stdlib.h> |
|
| 27 |
+ |
|
| 28 |
+typedef time_t (*time_fn_type)(time_t *tloc); |
|
| 29 |
+typedef int (*gettimeofday_fn_type)(struct timeval *restrict tv, void *restrict tz); |
|
| 30 |
+typedef int (*clock_gettime_fn_type)(clockid_t clockid, struct timespec *tp); |
|
| 31 |
+ |
|
| 32 |
+static int |
|
| 33 |
+libyesterdaydata(time_fn_type *paramtime_fn, gettimeofday_fn_type *paramgettimeofday_fn, clock_gettime_fn_type *paramclock_gettime_fn) |
|
| 34 |
+{
|
|
| 35 |
+ static int init=0; |
|
| 36 |
+ static int seconds=3600*24; |
|
| 37 |
+ static time_fn_type realtimefn=(time_fn_type)NULL; |
|
| 38 |
+ static gettimeofday_fn_type realgettimeofdayfn=(gettimeofday_fn_type)NULL; |
|
| 39 |
+ static clock_gettime_fn_type realclock_gettimefn=(clock_gettime_fn_type)NULL; |
|
| 40 |
+ if(init==0) {
|
|
| 41 |
+ char *ptr; |
|
| 42 |
+ realtimefn = (time_fn_type)dlsym(RTLD_NEXT,"time"); |
|
| 43 |
+ realgettimeofdayfn = (gettimeofday_fn_type)dlsym(RTLD_NEXT,"gettimeofday"); |
|
| 44 |
+ realclock_gettimefn = (clock_gettime_fn_type)dlsym(RTLD_NEXT,"clock_gettime"); |
|
| 45 |
+ if((ptr=getenv("LIBYESTERDAY"))!=NULL)
|
|
| 46 |
+ seconds=atoi(ptr); |
|
| 47 |
+ init=1; |
|
| 48 |
+ } |
|
| 49 |
+ if(paramtime_fn!=NULL) |
|
| 50 |
+ *paramtime_fn=realtimefn; |
|
| 51 |
+ if(paramgettimeofday_fn!=NULL) |
|
| 52 |
+ *paramgettimeofday_fn=realgettimeofdayfn; |
|
| 53 |
+ if(paramclock_gettime_fn!=NULL) |
|
| 54 |
+ *paramclock_gettime_fn=realclock_gettimefn; |
|
| 55 |
+ return(seconds); |
|
| 56 |
+} |
|
| 57 |
+ |
|
| 58 |
+extern time_t time(time_t *tloc) |
|
| 59 |
+{
|
|
| 60 |
+ time_fn_type realtimefn=(time_fn_type)NULL; |
|
| 61 |
+ int seconds; |
|
| 62 |
+ int res; |
|
| 63 |
+ seconds=libyesterdaydata(&realtimefn,NULL,NULL); |
|
| 64 |
+ res=realtimefn(NULL); |
|
| 65 |
+ res-=seconds; |
|
| 66 |
+ if(tloc!=NULL) |
|
| 67 |
+ *tloc=res; |
|
| 68 |
+ return(res); |
|
| 69 |
+} |
|
| 70 |
+ |
|
| 71 |
+extern int gettimeofday(struct timeval *restrict tv, void *restrict tz) |
|
| 72 |
+{
|
|
| 73 |
+ static gettimeofday_fn_type realgettimeofdayfn=(gettimeofday_fn_type)NULL; |
|
| 74 |
+ int seconds; |
|
| 75 |
+ int res; |
|
| 76 |
+ seconds=libyesterdaydata(NULL,&realgettimeofdayfn,NULL); |
|
| 77 |
+ res=realgettimeofdayfn(tv,tz); |
|
| 78 |
+ tv->tv_sec-=seconds; |
|
| 79 |
+ return(res); |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+extern int clock_gettime(clockid_t clockid, struct timespec *tp) |
|
| 83 |
+{
|
|
| 84 |
+ static clock_gettime_fn_type realclock_gettimefn=(clock_gettime_fn_type)NULL; |
|
| 85 |
+ int seconds; |
|
| 86 |
+ int res; |
|
| 87 |
+ seconds=libyesterdaydata(NULL,NULL,&realclock_gettimefn); |
|
| 88 |
+ res=realclock_gettimefn(clockid,tp); |
|
| 89 |
+ tp->tv_sec-=seconds; |
|
| 90 |
+ return(res); |
|
| 91 |
+} |
|
| 92 |
+ |
|
| 93 |
+ |