From 1f33caee527682028b1a6aaff7f47518389573a8 Mon Sep 17 00:00:00 2001 From: Nicholas Chaimov Date: Fri, 2 Oct 2026 14:16:57 -0700 Subject: [PATCH 1/3] Use initial-exec TLS for fixed_locale, crash handler reentrancy --- src/client/auditclient/fixlocale.c | 2 +- src/client/crash_handler/crash_handler.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/auditclient/fixlocale.c b/src/client/auditclient/fixlocale.c index 2db017f4..43ab852a 100644 --- a/src/client/auditclient/fixlocale.c +++ b/src/client/auditclient/fixlocale.c @@ -23,7 +23,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #if defined(NEWTHREAD_LOCALE_BUG) #include -static __thread int fixed_locale __attribute__((tls_model("local-dynamic"))) = 0; +static __thread int fixed_locale __attribute__((tls_model("initial-exec"))) = 0; static pid_t gettid() { diff --git a/src/client/crash_handler/crash_handler.c b/src/client/crash_handler/crash_handler.c index a59b3037..ba521d9c 100644 --- a/src/client/crash_handler/crash_handler.c +++ b/src/client/crash_handler/crash_handler.c @@ -222,7 +222,7 @@ static int crash_query_server(const char *site, const char *corepath, static void crash_handler_entry(int sig, siginfo_t *info, void *uctx) { /* Reentrancy flag to detect if we crash again while handling the crash. */ - static __thread sig_atomic_t reentering = 0; + static __thread sig_atomic_t reentering __attribute__((tls_model("initial-exec"))) = 0; /* We need to restore errno before returning. */ int saved_errno = errno; From 8fbf9188838e4e9254d611b51506793792d13c21 Mon Sep 17 00:00:00 2001 From: Nicholas Chaimov Date: Mon, 5 Oct 2026 14:03:05 -0700 Subject: [PATCH 2/3] Tests for chapel, adios2-style failures --- testsuite/Makefile.am | 27 ++++++++++++++-- testsuite/Makefile.in | 33 ++++++++++++++++--- testsuite/long_needed_path_test.c | 6 ++++ testsuite/realpath_free_test.c | 10 ++++++ testsuite/runTests_template | 15 +++++++++ testsuite/tagmalloc.c | 54 +++++++++++++++++++++++++++++++ 6 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 testsuite/long_needed_path_test.c create mode 100644 testsuite/realpath_free_test.c create mode 100644 testsuite/tagmalloc.c diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am index 6385a998..580d35bf 100644 --- a/testsuite/Makefile.am +++ b/testsuite/Makefile.am @@ -1,7 +1,7 @@ noinst_PROGRAMS = libgenerator ABS_TEST_DIR = $(abspath $(top_builddir)/testsuite) -BUILT_SOURCES = libtest10.so libtest11.so libtest12.so libtest13.so libtest14.so libtest15.so libtest16.so libtest17.so libtest18.so libtest19.so libtest20.so libtest50.so libtest100.so libtest500.so libtest1000.so libtest2000.so libtest4000.so libtest6000.so libtest8000.so libtest10000.so libtls1.c libtls2.c libtls3.c libtls4.c libtls5.c libtls6.c libtls7.c libtls8.c libtls9.c libtls10.c libtls11.c libtls12.c libtls13.c libtls14.c libtls15.c libtls16.c libtls17.c libtls18.c libtls19.c libtls20.c libsymlink.so libdepC.so libdepB.so libdepA.so libcxxexceptB.so libcxxexceptA.so origin_dir/liboriginlib.so origin_dir/origin_subdir/liborigintarget.so libtestoutput.so libfuncdict.so runTests run_driver run_driver_rm spindle.rc preload_file_list test_driver test_driver_libs retzero_rx retzero_r retzero_x retzero_ badinterp hello_r.py hello_x.py hello_rx.py hello_.py hello_l.py badlink.py spindle_exec_test spindle_deactivated.sh liblocal.so symbind_test interpreter_test interpreter_test_dir/interpreter_test_perl alias/aliastest.py exec_shell.sh exec_shell.tcsh exec_shell_expected_output exec_shell exec_shell_env.sh libbigtls1024.so libbigtls204800.so libbigtls1048576.so close_range_test +BUILT_SOURCES = libtest10.so libtest11.so libtest12.so libtest13.so libtest14.so libtest15.so libtest16.so libtest17.so libtest18.so libtest19.so libtest20.so libtest50.so libtest100.so libtest500.so libtest1000.so libtest2000.so libtest4000.so libtest6000.so libtest8000.so libtest10000.so libtls1.c libtls2.c libtls3.c libtls4.c libtls5.c libtls6.c libtls7.c libtls8.c libtls9.c libtls10.c libtls11.c libtls12.c libtls13.c libtls14.c libtls15.c libtls16.c libtls17.c libtls18.c libtls19.c libtls20.c libsymlink.so libdepC.so libdepB.so libdepA.so libcxxexceptB.so libcxxexceptA.so origin_dir/liboriginlib.so origin_dir/origin_subdir/liborigintarget.so libtestoutput.so libfuncdict.so runTests run_driver run_driver_rm spindle.rc preload_file_list test_driver test_driver_libs retzero_rx retzero_r retzero_x retzero_ badinterp hello_r.py hello_x.py hello_rx.py hello_.py hello_l.py badlink.py spindle_exec_test spindle_deactivated.sh liblocal.so symbind_test interpreter_test interpreter_test_dir/interpreter_test_perl alias/aliastest.py exec_shell.sh exec_shell.tcsh exec_shell_expected_output exec_shell exec_shell_env.sh libbigtls1024.so libbigtls204800.so libbigtls1048576.so close_range_test libtagmalloc.so long_needed_path_test long_needed_app_malloc_test long_needed_lib_malloc_test realpath_free_test realpath_free_lib_test BUILT_SOURCES += crash_test crash_test_fixedaddr crash_test_pie libcrashfuncs.so libcrashctor.so libcrashfixed.so run_crash_tests.sh @@ -482,5 +482,28 @@ exec_shell: $(srcdir)/exec_shell.c close_range_test: $(srcdir)/close_range_test.c $(AM_V_CCLD)$(CC) $(CFLAGS) -o $@ $< -CLEANFILES = libtest10.c libtest11.c libtest12.c libtest13.c libtest14.c libtest15.c libtest16.c libtest17.c libtest18.c libtest19.c libtest20.c libtest10.so libtest50.c libtest50.so libtest100.c libtest100.so libtest500.c libtest500.so libtest1000.c libtest1000.so libtest2000.c libtest2000.so libtest4000.c libtest4000.so libtest6000.c libtest6000.so libtest8000.c libtest8000.so libtest10000.c libtest10000.so libsymlink.so libdepA.so libdepB.so libdepC.so libcxxexceptA.so libcxxexceptB.so libtestoutput.so libfuncdict.so runTests run_driver run_driver_rm spindle.rc test_driver test_driver_libs preload_file_list retzero_rx retzero_r retzero_x retzero_ badinterp hello_r.py hello_x.py hello_rx.py hello_.py hello_l.py badlink.py libtls1.c libtls2.c libtls3.c libtls4.c libtls5.c libtls6.c libtls7.c libtls8.c libtls9.c libtls10.c libtls11.c libtls12.c libtls13.c libtls14.c libtls15.c libtls16.c libtls17.c libtls18.c libtls19.c libtls20.c libtls1.so libtls2.so libtls3.so libtls4.so libtls5.so libtls6.so libtls7.so libtls8.so libtls9.so libtls10.so libtls11.so libtls12.so libtls13.so libtls14.so libtls15.so libtls16.so libtls17.so libtls18.so libtls19.so libtls20.so symbind_test libsymbind_a.so libsymbind_b.so libsymbind_c.so libsymbind_d.so libsymbind_e.so libsymbind_f.so libsymbind_g.so interpreter_test interpreter_test_dir/interpreter_test_perl alias exec_shell.sh exec_shell.tcsh exec_shell_env.sh exec_shell_expected_output exec_shell crash_test crash_test_fixedaddr crash_test_pie libcrashfuncs.so libcrashctor.so libcrashfixed.so run_crash_tests.sh libbigtls204800.so libbigtls1048576.so close_range_test +LONG_NEEDED_TARGET = origin_dir/origin_subdir/liborigintarget.so +LONG_NEEDED_LIBS = -Wl,--no-as-needed -lc "$$(printf '/%.0s' $$(seq 300))$(abs_builddir)/$(LONG_NEEDED_TARGET)" + +TAGMALLOC_LIBS = -L. -Wl,--no-as-needed -ltagmalloc -Wl,-rpath,$(abs_builddir) + +libtagmalloc.so: $(srcdir)/tagmalloc.c + $(AM_V_CCLD)$(CC) $(CFLAGS) -fno-builtin -o $@ -shared -fPIC $< + +long_needed_path_test: $(srcdir)/long_needed_path_test.c $(LONG_NEEDED_TARGET) + $(AM_V_CCLD)$(CC) $(CFLAGS) -o $@ $(srcdir)/long_needed_path_test.c $(LONG_NEEDED_LIBS) + +long_needed_app_malloc_test: $(srcdir)/long_needed_path_test.c $(srcdir)/tagmalloc.c $(LONG_NEEDED_TARGET) + $(AM_V_CCLD)$(CC) $(CFLAGS) -fno-builtin -fPIE -pie -o $@ $(srcdir)/long_needed_path_test.c $(srcdir)/tagmalloc.c $(LONG_NEEDED_LIBS) + +long_needed_lib_malloc_test: $(srcdir)/long_needed_path_test.c libtagmalloc.so $(LONG_NEEDED_TARGET) + $(AM_V_CCLD)$(CC) $(CFLAGS) -o $@ $(srcdir)/long_needed_path_test.c $(TAGMALLOC_LIBS) $(LONG_NEEDED_LIBS) + +realpath_free_test: $(srcdir)/realpath_free_test.c $(srcdir)/tagmalloc.c + $(AM_V_CCLD)$(CC) $(CFLAGS) -fno-builtin -o $@ $(srcdir)/realpath_free_test.c $(srcdir)/tagmalloc.c + +realpath_free_lib_test: $(srcdir)/realpath_free_test.c libtagmalloc.so + $(AM_V_CCLD)$(CC) $(CFLAGS) -o $@ $(srcdir)/realpath_free_test.c $(TAGMALLOC_LIBS) + +CLEANFILES = libtest10.c libtest11.c libtest12.c libtest13.c libtest14.c libtest15.c libtest16.c libtest17.c libtest18.c libtest19.c libtest20.c libtest10.so libtest50.c libtest50.so libtest100.c libtest100.so libtest500.c libtest500.so libtest1000.c libtest1000.so libtest2000.c libtest2000.so libtest4000.c libtest4000.so libtest6000.c libtest6000.so libtest8000.c libtest8000.so libtest10000.c libtest10000.so libsymlink.so libdepA.so libdepB.so libdepC.so libcxxexceptA.so libcxxexceptB.so libtestoutput.so libfuncdict.so runTests run_driver run_driver_rm spindle.rc test_driver test_driver_libs preload_file_list retzero_rx retzero_r retzero_x retzero_ badinterp hello_r.py hello_x.py hello_rx.py hello_.py hello_l.py badlink.py libtls1.c libtls2.c libtls3.c libtls4.c libtls5.c libtls6.c libtls7.c libtls8.c libtls9.c libtls10.c libtls11.c libtls12.c libtls13.c libtls14.c libtls15.c libtls16.c libtls17.c libtls18.c libtls19.c libtls20.c libtls1.so libtls2.so libtls3.so libtls4.so libtls5.so libtls6.so libtls7.so libtls8.so libtls9.so libtls10.so libtls11.so libtls12.so libtls13.so libtls14.so libtls15.so libtls16.so libtls17.so libtls18.so libtls19.so libtls20.so symbind_test libsymbind_a.so libsymbind_b.so libsymbind_c.so libsymbind_d.so libsymbind_e.so libsymbind_f.so libsymbind_g.so interpreter_test interpreter_test_dir/interpreter_test_perl alias exec_shell.sh exec_shell.tcsh exec_shell_env.sh exec_shell_expected_output exec_shell crash_test crash_test_fixedaddr crash_test_pie libcrashfuncs.so libcrashctor.so libcrashfixed.so run_crash_tests.sh libbigtls204800.so libbigtls1048576.so close_range_test libtagmalloc.so long_needed_path_test long_needed_app_malloc_test long_needed_lib_malloc_test realpath_free_test realpath_free_lib_test diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index fa308678..63cd7835 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -360,9 +360,11 @@ BUILT_SOURCES = libtest10.so libtest11.so libtest12.so libtest13.so \ alias/aliastest.py exec_shell.sh exec_shell.tcsh \ exec_shell_expected_output exec_shell exec_shell_env.sh \ libbigtls1024.so libbigtls204800.so libbigtls1048576.so \ - close_range_test crash_test crash_test_fixedaddr \ - crash_test_pie libcrashfuncs.so libcrashctor.so \ - libcrashfixed.so run_crash_tests.sh + close_range_test libtagmalloc.so long_needed_path_test \ + long_needed_app_malloc_test long_needed_lib_malloc_test \ + realpath_free_test realpath_free_lib_test crash_test \ + crash_test_fixedaddr crash_test_pie libcrashfuncs.so \ + libcrashctor.so libcrashfixed.so run_crash_tests.sh @BGQ_BLD_FALSE@DYNAMIC_FLAG = @BGQ_BLD_TRUE@DYNAMIC_FLAG = -dynamic @BGQ_BLD_FALSE@IS_BLUEGENE = false @@ -379,6 +381,9 @@ test_driver_libsLDFLAGS = -Wl,-E -L$(top_builddir)/testsuite $(MPI_CLDFLAGS) -L$ REGLIB_SRC = $(srcdir)/registerlib.c LD_FUNCDICT = -L$(top_builddir)/testsuite -lfuncdict EXTRA_DIST = run_crash_tests_template.sh crash_test.c crash_functions.c crash_functions.h libcrashfuncs.c libcrashctor.c libcrashfixed.c +LONG_NEEDED_TARGET = origin_dir/origin_subdir/liborigintarget.so +LONG_NEEDED_LIBS = -Wl,--no-as-needed -lc "$$(printf '/%.0s' $$(seq 300))$(abs_builddir)/$(LONG_NEEDED_TARGET)" +TAGMALLOC_LIBS = -L. -Wl,--no-as-needed -ltagmalloc -Wl,-rpath,$(abs_builddir) CLEANFILES = libtest10.c libtest11.c libtest12.c libtest13.c \ libtest14.c libtest15.c libtest16.c libtest17.c libtest18.c \ libtest19.c libtest20.c libtest10.so libtest50.c libtest50.so \ @@ -408,7 +413,9 @@ CLEANFILES = libtest10.c libtest11.c libtest12.c libtest13.c \ exec_shell crash_test crash_test_fixedaddr crash_test_pie \ libcrashfuncs.so libcrashctor.so libcrashfixed.so \ run_crash_tests.sh libbigtls204800.so libbigtls1048576.so \ - close_range_test + close_range_test libtagmalloc.so long_needed_path_test \ + long_needed_app_malloc_test long_needed_lib_malloc_test \ + realpath_free_test realpath_free_lib_test all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am @@ -1166,6 +1173,24 @@ exec_shell: $(srcdir)/exec_shell.c close_range_test: $(srcdir)/close_range_test.c $(AM_V_CCLD)$(CC) $(CFLAGS) -o $@ $< +libtagmalloc.so: $(srcdir)/tagmalloc.c + $(AM_V_CCLD)$(CC) $(CFLAGS) -fno-builtin -o $@ -shared -fPIC $< + +long_needed_path_test: $(srcdir)/long_needed_path_test.c $(LONG_NEEDED_TARGET) + $(AM_V_CCLD)$(CC) $(CFLAGS) -o $@ $(srcdir)/long_needed_path_test.c $(LONG_NEEDED_LIBS) + +long_needed_app_malloc_test: $(srcdir)/long_needed_path_test.c $(srcdir)/tagmalloc.c $(LONG_NEEDED_TARGET) + $(AM_V_CCLD)$(CC) $(CFLAGS) -fno-builtin -fPIE -pie -o $@ $(srcdir)/long_needed_path_test.c $(srcdir)/tagmalloc.c $(LONG_NEEDED_LIBS) + +long_needed_lib_malloc_test: $(srcdir)/long_needed_path_test.c libtagmalloc.so $(LONG_NEEDED_TARGET) + $(AM_V_CCLD)$(CC) $(CFLAGS) -o $@ $(srcdir)/long_needed_path_test.c $(TAGMALLOC_LIBS) $(LONG_NEEDED_LIBS) + +realpath_free_test: $(srcdir)/realpath_free_test.c $(srcdir)/tagmalloc.c + $(AM_V_CCLD)$(CC) $(CFLAGS) -fno-builtin -o $@ $(srcdir)/realpath_free_test.c $(srcdir)/tagmalloc.c + +realpath_free_lib_test: $(srcdir)/realpath_free_test.c libtagmalloc.so + $(AM_V_CCLD)$(CC) $(CFLAGS) -o $@ $(srcdir)/realpath_free_test.c $(TAGMALLOC_LIBS) + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/testsuite/long_needed_path_test.c b/testsuite/long_needed_path_test.c new file mode 100644 index 00000000..80f310ae --- /dev/null +++ b/testsuite/long_needed_path_test.c @@ -0,0 +1,6 @@ +int origin_target(); + +int main(void) +{ + return origin_target() == 2 ? 0 : 1; +} diff --git a/testsuite/realpath_free_test.c b/testsuite/realpath_free_test.c new file mode 100644 index 00000000..e292aa88 --- /dev/null +++ b/testsuite/realpath_free_test.c @@ -0,0 +1,10 @@ +#include + +int main(void) +{ + char *r = realpath("/proc/self/exe", NULL); + if (!r || r[0] != '/') + return 1; + free(r); + return 0; +} diff --git a/testsuite/runTests_template b/testsuite/runTests_template index 64a1b301..ea73937e 100644 --- a/testsuite/runTests_template +++ b/testsuite/runTests_template @@ -196,6 +196,21 @@ CHECK_RETCODE ./run_driver --serial ./close_range_test CHECK_RETCODE +./run_driver --serial ./long_needed_path_test +CHECK_RETCODE + +./run_driver --serial ./long_needed_app_malloc_test +CHECK_RETCODE + +./run_driver --serial ./long_needed_lib_malloc_test +CHECK_RETCODE + +./run_driver --serial ./realpath_free_test +CHECK_RETCODE + +./run_driver --serial ./realpath_free_lib_test +CHECK_RETCODE + if [[ $GLOBAL_RESULT != 0 ]]; then echo SOME TESTS FAILED exit -1 diff --git a/testsuite/tagmalloc.c b/testsuite/tagmalloc.c new file mode 100644 index 00000000..d7f0cd59 --- /dev/null +++ b/testsuite/tagmalloc.c @@ -0,0 +1,54 @@ +/* malloc/free wrapper which tags allocated memory in order + * to check that it came from this malloc implementation rather + * than a different one. free() exits if given an untagged pointer */ +#include +#include + +#define TAG 0xabcdef1234567890UL +#define HEADER 16 + +void *__libc_malloc(size_t n); +void *__libc_calloc(size_t n, size_t m); +void *__libc_realloc(void *p, size_t n); +void __libc_free(void *p); + +static void *tag(char *block) +{ + if (!block) + return NULL; + *(unsigned long *) block = TAG; + return block + HEADER; +} + +static char *untag(void *p) +{ + char *block = (char *) p - HEADER; + if (*(unsigned long *) block != TAG) { + /* We got an untagged pointer */ + _exit(5); + } + return block; +} + +void *malloc(size_t n) +{ + return tag(__libc_malloc(n + HEADER)); +} + +void *calloc(size_t n, size_t m) +{ + return tag(__libc_calloc(1, n * m + HEADER)); +} + +void *realloc(void *p, size_t n) +{ + if (!p) + return malloc(n); + return tag(__libc_realloc(untag(p), n + HEADER)); +} + +void free(void *p) +{ + if (p) + __libc_free(untag(p)); +} From eee52342434270a8bb14377520bda3d3029b7df8 Mon Sep 17 00:00:00 2001 From: Nicholas Chaimov Date: Mon, 5 Oct 2026 15:04:30 -0700 Subject: [PATCH 3/3] Find malloc instead of assuming it's in libc; don't find malloc until LA_ACT_CONSISTENT --- src/client/auditclient/auditclient.c | 1 + src/client/auditclient/patch_bad_dtv.c | 6 +-- src/client/auditclient/patch_linkmap.c | 2 +- src/client/client/client.h | 3 +- src/client/client/lookup_libc.c | 60 ++++++++++++++++++-------- src/client/client/realpath.c | 2 +- 6 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/client/auditclient/auditclient.c b/src/client/auditclient/auditclient.c index cdaacfc5..ce1c8575 100644 --- a/src/client/auditclient/auditclient.c +++ b/src/client/auditclient/auditclient.c @@ -43,6 +43,7 @@ void spindle_la_activity (uintptr_t *cookie, unsigned int flag) "???"); restore_pathpatch(); if (flag == LA_ACT_CONSISTENT) { + mark_startup_done(); patchDTV_check(); lookup_libc_symbols(); updateDataBindingQueue(0); diff --git a/src/client/auditclient/patch_bad_dtv.c b/src/client/auditclient/patch_bad_dtv.c index 856bf6bc..2a63deaa 100644 --- a/src/client/auditclient/patch_bad_dtv.c +++ b/src/client/auditclient/patch_bad_dtv.c @@ -27,11 +27,11 @@ Place, Suite 330, Boston, MA 02111-1307 USA /** * This file works around a glibc problem when LD_AUDIT is enable, where the DTV (dynamic thread vector) - * gets allocated using ld.so's rtld_malloc function, then later gets resized by libc.so's realloc function + * gets allocated using ld.so's rtld_malloc function, then later gets resized by the application's realloc function * (SPINDLE_SRC/scripts/dtvtest/ has a reproducer that can make this happen--you need lots of libraries with TLS). * * We'll work around this problem by A) recognizing when this will happen, and B) copying the DTV to a - * memory region properly controlled by libc.so's malloc. + * memory region properly controlled by the application's malloc. * We recognize this because in the buggy case, the DTV will change values twice before libc.so enters a * consistent state. * We copy the DTV to a proper malloc region by getting its pointer out of TLS space. DTV is a vector, and @@ -120,7 +120,7 @@ void patchDTV_check() debug_printf2("Reallocating dtv to work around glibc bug. initial_dtv = %p ; dtv = %p\n", initial_dtv, dtv); - malloc_sig_t app_malloc = get_libc_malloc(); + malloc_sig_t app_malloc = get_app_malloc(); if (!app_malloc) { debug_printf("Warning: Could not lookup up application malloc to realloc dtv. App may be prone to crashes during dlopen's\n"); return; diff --git a/src/client/auditclient/patch_linkmap.c b/src/client/auditclient/patch_linkmap.c index ab097091..d0a4767e 100644 --- a/src/client/auditclient/patch_linkmap.c +++ b/src/client/auditclient/patch_linkmap.c @@ -63,7 +63,7 @@ void patch_on_linkactivity(struct link_map *lmap) strcpy(lmap->l_name, last_orig_name); } else { - malloc_sig_t app_malloc = get_libc_malloc(); + malloc_sig_t app_malloc = get_app_malloc(); if (app_malloc) { len = strlen(last_orig_name) + 2; oname = (char *) app_malloc(len); diff --git a/src/client/client/client.h b/src/client/client/client.h index 7004d577..2fa63347 100644 --- a/src/client/client/client.h +++ b/src/client/client/client.h @@ -105,7 +105,8 @@ extern int intercept_fork; extern void int_spindle_test_log_msg(char *buffer); typedef void* (*malloc_sig_t)(size_t); -malloc_sig_t get_libc_malloc(); +malloc_sig_t get_app_malloc(); +void mark_startup_done(); void *get_libc_abort_msg(); diff --git a/src/client/client/lookup_libc.c b/src/client/client/lookup_libc.c index 51344dfa..aac8c523 100644 --- a/src/client/client/lookup_libc.c +++ b/src/client/client/lookup_libc.c @@ -46,6 +46,7 @@ struct gnu_hash_header { }; static malloc_sig_t mallocfunc = NULL; +static int startup_done = 0; static void *volatile abort_msg_addr = NULL; @@ -203,21 +204,6 @@ int lookup_libc_symbols() found++; } - result = -1; - if (gnu_hash) - result = lookup_gnu_hash_symbol("malloc", symtab, strtab, (struct gnu_hash_header *) gnu_hash); - if (elf_hash && result == -1) - result = lookup_elf_hash_symbol("malloc", symtab, strtab, (ElfW(Word) *) elf_hash); - if (result == -1) { - debug_printf3("Warning, Could not find symbol malloc in libc\n"); - not_found++; - } - else { - mallocfunc = (malloc_sig_t) (symtab[result].st_value + libc->l_addr); - debug_printf3("Bound mallocfunc to %p\n", mallocfunc); - found++; - } - result = -1; if (gnu_hash) result = lookup_gnu_hash_symbol("__abort_msg", symtab, strtab, (struct gnu_hash_header *) gnu_hash); @@ -292,14 +278,54 @@ int lookup_libdl_symbols() return found; } -malloc_sig_t get_libc_malloc() +static int lookup_defined_symbol(struct link_map *lmap, const char *name, void **addr) { + signed long result = -1; + INIT_DYNAMIC(lmap); + + if (gnu_hash) + result = lookup_gnu_hash_symbol(name, symtab, strtab, (struct gnu_hash_header *) gnu_hash); + if (elf_hash && result == -1) + result = lookup_elf_hash_symbol(name, symtab, strtab, (ElfW(Word) *) elf_hash); + /* We only want to find a defined symbol; check if it's undefined */ + if (result == -1 || symtab[result].st_shndx == SHN_UNDEF) + return -1; + *addr = (void *) (symtab[result].st_value + lmap->l_addr); + return 0; +} + +malloc_sig_t get_app_malloc() +{ + struct link_map *l; + void *addr; + + /* If we haven't gotten LA_ACT_CONSISTENT yet, it's not safe to call the app's malloc */ + if (!startup_done) + return NULL; + if (mallocfunc) return mallocfunc; - lookup_libc_symbols(); + + /* Iterate over the link map looking for a library that defines malloc. */ + for (l = _r_debug.r_map; l != NULL; l = l->l_next) { + /* Skip vDSO when iterating as symbol lookup crashes in it */ + if (l->l_name && (strstr(l->l_name, "linux-vdso") || strstr(l->l_name, "linux-gate"))) + continue; + if (lookup_defined_symbol(l, "malloc", &addr) == 0) { + debug_printf3("Bound app malloc to %p in %s\n", addr, + (l->l_name && *l->l_name) ? l->l_name : "executable"); + mallocfunc = (malloc_sig_t) addr; + break; + } + } return mallocfunc; } +void mark_startup_done() +{ + startup_done = 1; +} + void *get_libc_abort_msg() { return abort_msg_addr; diff --git a/src/client/client/realpath.c b/src/client/client/realpath.c index cea4c6c1..2d068222 100644 --- a/src/client/client/realpath.c +++ b/src/client/client/realpath.c @@ -81,7 +81,7 @@ static char *spindlerp_ext_strdup(const char *s) size_t len; malloc_sig_t mallocf; - mallocf = get_libc_malloc(); + mallocf = get_app_malloc(); if (!mallocf) { err_printf("Could not lookup malloc function for realpath result\n"); return NULL;