diff options
author | Wolfgang Hommel <wolfcw@users.noreply.github.com> | 2022-05-08 20:56:16 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-08 20:56:16 +0200 |
commit | 141d1a7a87a077b0f0cb4119b825089b7491baad (patch) | |
tree | 36c620ed5c6b9956ec7fc02f960e0f95a923c7a9 | |
parent | f836ea3eb392378bc5166b3d68283f69e5330542 (diff) | |
parent | 0f79f21e11f1928bbb081782ef50bbf1cf971316 (diff) | |
download | libfaketime-141d1a7a87a077b0f0cb4119b825089b7491baad.tar.gz |
Merge pull request #389 from psychon/asan
Work-around / fix libasan incompatibility
-rw-r--r-- | src/Makefile | 5 | ||||
-rw-r--r-- | src/libfaketime.c | 11 | ||||
-rw-r--r-- | test/Makefile | 7 | ||||
-rw-r--r-- | test/libmallocintercept.c | 83 | ||||
-rwxr-xr-x | test/test.sh | 9 |
5 files changed, 113 insertions, 2 deletions
diff --git a/src/Makefile b/src/Makefile index 62e924c..6ece674 100644 --- a/src/Makefile +++ b/src/Makefile @@ -84,6 +84,11 @@ # - avoid that the faketime wrapper complains when running within a # libfaketime environment # +# FAIL_PRE_INIT_CALLS +# - If the time is queried before the library was initialised, let the +# call fail instead of trying to initialise on-the-fly. This fixes / +# works around hangs that were seen with address sanitizer. +# # * Compilation addition: second libMT target added for building the pthread- # enabled library as a separate library # diff --git a/src/libfaketime.c b/src/libfaketime.c index f92ecf8..ec80ec8 100644 --- a/src/libfaketime.c +++ b/src/libfaketime.c @@ -2282,6 +2282,16 @@ int clock_gettime(clockid_t clk_id, struct timespec *tp) if (!initialized) { recursion_depth++; +#ifdef FAIL_PRE_INIT_CALLS + fprintf(stderr, "libfaketime: clock_gettime() was called before initialization.\n"); + fprintf(stderr, "libfaketime: Returning -1 on clock_gettime().\n"); + if (tp != NULL) + { + tp->tv_sec = 0; + tp->tv_nsec = 0; + } + return -1; +#else if (recursion_depth == 2) { fprintf(stderr, "libfaketime: Unexpected recursive calls to clock_gettime() without proper initialization. Trying alternative.\n"); @@ -2302,6 +2312,7 @@ int clock_gettime(clockid_t clk_id, struct timespec *tp) else { ftpl_init(); } +#endif recursion_depth--; } /* sanity check */ diff --git a/test/Makefile b/test/Makefile index afdc594..763ebc4 100644 --- a/test/Makefile +++ b/test/Makefile @@ -26,7 +26,7 @@ all: $(ALL_TESTS) timetest: ${OBJ} ${CC} -o $@ ${OBJ} ${LDFLAGS} -test: timetest functest +test: timetest functest libmallocintercept.so @echo @./test.sh @@ -40,6 +40,9 @@ functest: randomtest: repeat_random ./randomtest.sh +libmallocintercept.so: libmallocintercept.c + ${CC} -shared -o $@ -fpic ${CFLAGS} $< + # ensure our variadic argument unpacking/repacking works as expected confirm_variadic_promotion: variadic_promotion ./variadic_promotion @@ -73,7 +76,7 @@ use_lib_%: _use_lib_test.c snippets/%.c lib%.so ## cleanup and metainformation clean: - @rm -f ${OBJ} timetest getrandom_test syscall_test $(foreach f,${TEST_SNIPPETS},use_lib_${f} lib${f}.so run_${f}) variadic_promotion variadic/*.o repeat_random + @rm -f ${OBJ} timetest getrandom_test syscall_test $(foreach f,${TEST_SNIPPETS},use_lib_${f} lib${f}.so run_${f}) variadic_promotion variadic/*.o repeat_random libmallocintercept.so distclean: clean @echo diff --git a/test/libmallocintercept.c b/test/libmallocintercept.c new file mode 100644 index 0000000..5ed0f67 --- /dev/null +++ b/test/libmallocintercept.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2022 be.storaged GmbH + * + * This file is part of libfaketime + * + * libfaketime is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License v2 as published by the + * Free Software Foundation. + * + * libfaketime is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License v2 along + * with the libfaketime; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <pthread.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +static void print_msg(const char *msg) { + write(0, msg, strlen(msg)); +} + +static void* actual_malloc(size_t size) { + /* We would like to use "the real malloc", but cannot. Thus, this + * implements a trivial, allocate-only bump allocator to make things + * work. + */ + static char memory_arena[16 << 20]; + static size_t allocated_index = 0; + + void *result = &memory_arena[allocated_index]; + + allocated_index += size; + /* align to a multiple of 8 bytes */ + allocated_index = (allocated_index + 7) / 8 * 8; + + if (allocated_index >= sizeof(memory_arena)) { + print_msg("libmallocintercept is out of memory!"); + abort(); + } + + return result; +} + +static void poke_faketime(void) { +#ifdef FAIL_PRE_INIT_CALLS + /* To complicate things for libfaketime, this calls clock_gettime() + * while holding a lock. This should simulate problems that occurred + * with address sanitizer. + */ + static pthread_mutex_t time_mutex = PTHREAD_MUTEX_INITIALIZER; + struct timespec timespec; + + pthread_mutex_lock(&time_mutex); + clock_gettime(CLOCK_REALTIME, ×pec); + pthread_mutex_unlock(&time_mutex); +#else + print_msg("FAIL_PRE_INIT_CALLS not defined, skipping poke_faketime() "); +#endif +} + +void *malloc(size_t size) { + print_msg("Called malloc() from libmallocintercept..."); + poke_faketime(); + print_msg("successfully\n"); + return actual_malloc(size); +} + +void free(void *) { + print_msg("Called free() from libmallocintercept..."); + poke_faketime(); + print_msg("successfully\n"); + + /* We cannot actually free memory */ +} + diff --git a/test/test.sh b/test/test.sh index 35f2a52..1ef7439 100755 --- a/test/test.sh +++ b/test/test.sh @@ -1,6 +1,7 @@ #!/bin/sh FTPL="${FAKETIME_TESTLIB:-../src/libfaketime.so.1}" +MALLOC_INTERCEPT=./libmallocintercept.so if [ -f /etc/faketimerc ] ; then echo "Running the test program with your system-wide default in /etc/faketimerc" @@ -63,6 +64,14 @@ LD_PRELOAD="$FTPL" FAKETIME="-15d" date echo echo "=============================================================================" +echo + +echo "Running the test program with malloc interception" +echo "\$ LD_PRELOAD=./libmallocintercept.so:$FTPL ./timetest" +LD_PRELOAD="./libmallocintercept.so:$FTPL" ./timetest +echo + +echo "=============================================================================" echo "Testing finished." exit 0 |