diff --git a/.gitignore b/.gitignore index 626ce7fa..5fcf4edb 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ run_driver run_driver_rm preload_file_list build +.vscode diff --git a/config.h.in b/config.h.in index 4ebf63f2..51db770c 100644 --- a/config.h.in +++ b/config.h.in @@ -157,6 +157,9 @@ /* The default port for Spindle */ #undef SPINDLE_PORT +/* Defined if GLIBC has static TLS allocation bug */ +#undef STATIC_TLS_ALLOC_BUG + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS diff --git a/configure b/configure index 800f4ee8..0b4da648 100755 --- a/configure +++ b/configure @@ -851,6 +851,7 @@ with_localstorage with_cachepaths with_cachepath with_commpaths +with_commpath with_default_local_prefix with_testrm with_rm @@ -1596,12 +1597,13 @@ Optional Packages: Number of TCP/IP ports to scan for Spindle server communication --with-localstorage=DIR (obsolete) - Use --with-cachepaths and --with-commpath instead. + Use --with-cachepaths and --with-commpaths instead. --with-cachepaths=DIR Colon-separated list of potential back-end cache directories -, - --with-compaths=DIR Colon-separated list of candidate paths for back-end + --with-cachepath=DIR Synonym for --with-cachepaths + --with-commpaths=DIR Colon-separated list of candidate paths for back-end communication and housekeeping + --with-commpath=DIR Synonym for --with-commpaths --with-default-local-prefix=DIRS Colon-seperated list of directories that Spindle will not cache files out of @@ -16675,7 +16677,7 @@ fi # Check whether --with-localstorage was given. if test "${with_localstorage+set}" = set; then : - withval=$with_localstorage; as_fn_error $? "requested obsolete option --with-localstorage. Use --with-cachepaths and --with-commpath instead." "$LINENO" 5 + withval=$with_localstorage; as_fn_error $? "requested obsolete option --with-localstorage. Use --with-cachepaths and --with-commpaths instead." "$LINENO" 5 fi @@ -16689,7 +16691,7 @@ fi # Check whether --with-cachepath was given. if test "${with_cachepath+set}" = set; then : - withval=$with_cachepath; as_fn_error $? "use --with-cachepaths=DIRS (plural) instead of --with-cachepath=DIR to specify one or more cache paths" "$LINENO" 5 + withval=$with_cachepath; CACHEPATHS=${withval} fi @@ -16701,6 +16703,12 @@ else fi +# Check whether --with-commpath was given. +if test "${with_commpath+set}" = set; then : + withval=$with_commpath; COMMPATHS=${withval} +fi + + # Check whether --with-default-local-prefix was given. if test "${with_default_local_prefix+set}" = set; then : withval=$with_default_local_prefix; SPINDLE_LOCAL_PREFIX=${withval} @@ -16848,13 +16856,13 @@ _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for locale tls fault glibc bug" >&5 $as_echo_n "checking for locale tls fault glibc bug... " >&6; } if ${SPINDLE_SOURCE_ROOT}/scripts/locale_tls_fault/tls_locale_fault.sh ${SPINDLE_SOURCE_ROOT}/scripts/locale_tls_fault ${SPINDLE_BUILD_ROOT}/locale_tls_fault $CC; then - LOCALE_FAULT_BUG=0 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -else LOCALE_FAULT_BUG=1 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } +else + LOCALE_FAULT_BUG=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi cat >>confdefs.h <<_ACEOF @@ -16862,6 +16870,22 @@ cat >>confdefs.h <<_ACEOF _ACEOF +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for static tls glibc bug" >&5 +$as_echo_n "checking for static tls glibc bug... " >&6; } +if ${SPINDLE_SOURCE_ROOT}/scripts/static_tls_test/run_test.sh ${CC} "${CFLAGS} -g" ${SPINDLE_SOURCE_ROOT} ${SPINDLE_BUILD_ROOT}; then + STATIC_TLS_BUG=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + STATIC_TLS_BUG=1 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi + +cat >>confdefs.h <<_ACEOF +#define STATIC_TLS_ALLOC_BUG $STATIC_TLS_BUG +_ACEOF + #OS Detection # Check whether --enable-bluegene was given. diff --git a/configure.common.ac b/configure.common.ac index 36f82883..88e33663 100644 --- a/configure.common.ac +++ b/configure.common.ac @@ -115,14 +115,23 @@ AC_DEFINE_UNQUOTED([DTV_ALLOCATION_BUG],[$DTV_ALLOC_BUG],[Defined if GLIBC has a AC_MSG_CHECKING([for locale tls fault glibc bug]) if ${SPINDLE_SOURCE_ROOT}/scripts/locale_tls_fault/tls_locale_fault.sh ${SPINDLE_SOURCE_ROOT}/scripts/locale_tls_fault ${SPINDLE_BUILD_ROOT}/locale_tls_fault $CC; then - LOCALE_FAULT_BUG=0 - AC_MSG_RESULT([no]) -else LOCALE_FAULT_BUG=1 AC_MSG_RESULT([yes]) +else + LOCALE_FAULT_BUG=0 + AC_MSG_RESULT([no]) fi AC_DEFINE_UNQUOTED([NEWTHREAD_LOCALE_BUG],[$LOCALE_FAULT_BUG],[Defined if GLIBC has locale TLS bug]) +AC_MSG_CHECKING([for static tls glibc bug]) +if ${SPINDLE_SOURCE_ROOT}/scripts/static_tls_test/run_test.sh ${CC} "${CFLAGS} -g" ${SPINDLE_SOURCE_ROOT} ${SPINDLE_BUILD_ROOT}; then + STATIC_TLS_BUG=0 + AC_MSG_RESULT([no]) +else + STATIC_TLS_BUG=1 + AC_MSG_RESULT([yes]) +fi +AC_DEFINE_UNQUOTED([STATIC_TLS_ALLOC_BUG],[$STATIC_TLS_BUG],[Defined if GLIBC has static TLS allocation bug]) #OS Detection AC_ARG_ENABLE(bluegene, diff --git a/scripts/static_tls_test/app.c b/scripts/static_tls_test/app.c new file mode 100644 index 00000000..7326ba5d --- /dev/null +++ b/scripts/static_tls_test/app.c @@ -0,0 +1,24 @@ +#include +#include + +extern void set_bigtls(); +extern int get_bigtls(); + +void *runthrd(void *name) +{ + get_bigtls(); + return NULL; +} + +int main(int argc, char *argv[]) +{ + pthread_t thrd; + + pthread_create(&thrd, NULL, runthrd, "thrd"); + set_bigtls(); + runthrd("main"); + pthread_join(thrd, NULL); + printf("Passed\n"); + return 0; +} + diff --git a/scripts/static_tls_test/minaudit.c b/scripts/static_tls_test/minaudit.c new file mode 100644 index 00000000..ad1fde71 --- /dev/null +++ b/scripts/static_tls_test/minaudit.c @@ -0,0 +1,6 @@ +#define _GNU_SOURCE +#include + +unsigned int la_version(unsigned int v) { + return v; +} diff --git a/scripts/static_tls_test/run_test.sh b/scripts/static_tls_test/run_test.sh new file mode 100755 index 00000000..49f9c7e2 --- /dev/null +++ b/scripts/static_tls_test/run_test.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +CC=$1 +CFLAGS=$2 +SRCDIR=$3/scripts/static_tls_test +BINDIR=$4/static_tls_test + +mkdir -p $BINDIR + +if [ ! -f "$BINDIR/statictls" ]; then +$CC $CFLAGS -o $BINDIR/libstatictls.so -shared -fPIC $SRCDIR/statictls.c +$CC $CFLAGS -o $BINDIR/statictls -L$BINDIR -Wl,-rpath,$BINDIR $SRCDIR/app.c -lstatictls -lpthread +$CC $CFLAGS -o $BINDIR/libminaudit.so -fPIC -shared $SRCDIR/minaudit.c +fi +LD_AUDIT=$BINDIR/libminaudit.so $BINDIR/statictls >& /dev/null +RESULT=$? + +exit $RESULT diff --git a/scripts/static_tls_test/statictls.c b/scripts/static_tls_test/statictls.c new file mode 100644 index 00000000..4f58087f --- /dev/null +++ b/scripts/static_tls_test/statictls.c @@ -0,0 +1,17 @@ +__thread unsigned char bigtls[20000000] __attribute__((tls_model("initial-exec"))); + +void set_bigtls() +{ + for (unsigned i = 0; i < sizeof(bigtls); i++) { + bigtls[i] = (unsigned char) i % 255; + } +} + +int get_bigtls() +{ + int result = 0; + for (unsigned i = 0; i < sizeof(bigtls); i++) { + result += bigtls[i]; + } + return result; +} diff --git a/src/client/auditclient/auditclient_common.c b/src/client/auditclient/auditclient_common.c index b82fbb9b..a24e1248 100644 --- a/src/client/auditclient/auditclient_common.c +++ b/src/client/auditclient/auditclient_common.c @@ -130,6 +130,7 @@ void la_activity (uintptr_t *cookie, unsigned int flag) } spindle_la_activity(cookie, flag); + debug_printf3("Returning from la_activity\n"); return; } diff --git a/src/client/auditclient/fixlocale.c b/src/client/auditclient/fixlocale.c index aec83f9b..2db017f4 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 = 0; +static __thread int fixed_locale __attribute__((tls_model("local-dynamic"))) = 0; static pid_t gettid() { diff --git a/src/client/beboot/Makefile.am b/src/client/beboot/Makefile.am index e7b3d577..4b2f9957 100644 --- a/src/client/beboot/Makefile.am +++ b/src/client/beboot/Makefile.am @@ -3,7 +3,7 @@ pkglibexec_PROGRAMS = spindle_bootstrap spindle_bootstrap_LDFLAGS = $(AM_LDFLAGS) $(STATICFLAG) spindle_bootstrap_CPPFLAGS = $(AM_CPPFLAGS) -DLIBEXECDIR=\"$(pkglibexecdir)\" -DPROGLIBDIR=\"$(pkglibdir)\" -I$(top_srcdir)/../include -I$(top_srcdir)/../logging -I$(top_srcdir)/client_comlib -I$(top_srcdir)/client -I$(top_srcdir)/shm_cache -I$(top_srcdir)/../utils spindle_bootstrap_LDADD = $(top_builddir)/logging/libspindleclogc.la $(top_builddir)/shm_cache/libshmcache.la -spindle_bootstrap_SOURCES = spindle_bootstrap.c $(top_srcdir)/../utils/parseloc.c $(top_srcdir)/../utils/spindle_mkdir.c $(top_srcdir)/../utils/getcpu.c $(top_srcdir)/client/exec_util.c $(top_srcdir)/client/lookup.c $(top_srcdir)/../utils/fileutil.c +spindle_bootstrap_SOURCES = spindle_bootstrap.c $(top_srcdir)/../utils/parseloc.c $(top_srcdir)/../utils/spindle_mkdir.c $(top_srcdir)/../utils/getcpu.c $(top_srcdir)/client/exec_util.c $(top_srcdir)/client/lookup.c $(top_srcdir)/../utils/fileutil.c $(top_srcdir)/../utils/static_tls.c if PIPES spindle_bootstrap_LDADD += $(top_builddir)/client_comlib/libclient_pipe.la diff --git a/src/client/beboot/Makefile.in b/src/client/beboot/Makefile.in index a50318b5..67b6a8ea 100644 --- a/src/client/beboot/Makefile.in +++ b/src/client/beboot/Makefile.in @@ -120,7 +120,8 @@ am_spindle_bootstrap_OBJECTS = \ $(top_builddir)/../utils/spindle_bootstrap-getcpu.$(OBJEXT) \ $(top_builddir)/client/spindle_bootstrap-exec_util.$(OBJEXT) \ $(top_builddir)/client/spindle_bootstrap-lookup.$(OBJEXT) \ - $(top_builddir)/../utils/spindle_bootstrap-fileutil.$(OBJEXT) + $(top_builddir)/../utils/spindle_bootstrap-fileutil.$(OBJEXT) \ + $(top_builddir)/../utils/spindle_bootstrap-static_tls.$(OBJEXT) spindle_bootstrap_OBJECTS = $(am_spindle_bootstrap_OBJECTS) spindle_bootstrap_DEPENDENCIES = \ $(top_builddir)/logging/libspindleclogc.la \ @@ -153,6 +154,7 @@ am__depfiles_remade = $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-fileu $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-getcpu.Po \ $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-parseloc.Po \ $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-spindle_mkdir.Po \ + $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-static_tls.Po \ $(top_builddir)/client/$(DEPDIR)/spindle_bootstrap-exec_util.Po \ $(top_builddir)/client/$(DEPDIR)/spindle_bootstrap-lookup.Po \ ./$(DEPDIR)/spindle_bootstrap-spindle_bootstrap.Po @@ -343,7 +345,7 @@ spindle_bootstrap_CPPFLAGS = $(AM_CPPFLAGS) -DLIBEXECDIR=\"$(pkglibexecdir)\" -D spindle_bootstrap_LDADD = $(top_builddir)/logging/libspindleclogc.la \ $(top_builddir)/shm_cache/libshmcache.la $(am__append_1) \ $(am__append_2) -spindle_bootstrap_SOURCES = spindle_bootstrap.c $(top_srcdir)/../utils/parseloc.c $(top_srcdir)/../utils/spindle_mkdir.c $(top_srcdir)/../utils/getcpu.c $(top_srcdir)/client/exec_util.c $(top_srcdir)/client/lookup.c $(top_srcdir)/../utils/fileutil.c +spindle_bootstrap_SOURCES = spindle_bootstrap.c $(top_srcdir)/../utils/parseloc.c $(top_srcdir)/../utils/spindle_mkdir.c $(top_srcdir)/../utils/getcpu.c $(top_srcdir)/client/exec_util.c $(top_srcdir)/client/lookup.c $(top_srcdir)/../utils/fileutil.c $(top_srcdir)/../utils/static_tls.c all: all-am .SUFFIXES: @@ -456,6 +458,9 @@ $(top_builddir)/client/spindle_bootstrap-lookup.$(OBJEXT): \ $(top_builddir)/../utils/spindle_bootstrap-fileutil.$(OBJEXT): \ $(top_builddir)/../utils/$(am__dirstamp) \ $(top_builddir)/../utils/$(DEPDIR)/$(am__dirstamp) +$(top_builddir)/../utils/spindle_bootstrap-static_tls.$(OBJEXT): \ + $(top_builddir)/../utils/$(am__dirstamp) \ + $(top_builddir)/../utils/$(DEPDIR)/$(am__dirstamp) spindle_bootstrap$(EXEEXT): $(spindle_bootstrap_OBJECTS) $(spindle_bootstrap_DEPENDENCIES) $(EXTRA_spindle_bootstrap_DEPENDENCIES) @rm -f spindle_bootstrap$(EXEEXT) @@ -473,6 +478,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-getcpu.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-parseloc.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-spindle_mkdir.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-static_tls.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/client/$(DEPDIR)/spindle_bootstrap-exec_util.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/client/$(DEPDIR)/spindle_bootstrap-lookup.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spindle_bootstrap-spindle_bootstrap.Po@am__quote@ # am--include-marker @@ -605,6 +611,20 @@ $(top_builddir)/../utils/spindle_bootstrap-fileutil.obj: $(top_builddir)/../util @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spindle_bootstrap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o $(top_builddir)/../utils/spindle_bootstrap-fileutil.obj `if test -f '$(top_builddir)/../utils/fileutil.c'; then $(CYGPATH_W) '$(top_builddir)/../utils/fileutil.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/../utils/fileutil.c'; fi` +$(top_builddir)/../utils/spindle_bootstrap-static_tls.o: $(top_builddir)/../utils/static_tls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spindle_bootstrap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT $(top_builddir)/../utils/spindle_bootstrap-static_tls.o -MD -MP -MF $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-static_tls.Tpo -c -o $(top_builddir)/../utils/spindle_bootstrap-static_tls.o `test -f '$(top_builddir)/../utils/static_tls.c' || echo '$(srcdir)/'`$(top_builddir)/../utils/static_tls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-static_tls.Tpo $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-static_tls.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_builddir)/../utils/static_tls.c' object='$(top_builddir)/../utils/spindle_bootstrap-static_tls.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spindle_bootstrap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o $(top_builddir)/../utils/spindle_bootstrap-static_tls.o `test -f '$(top_builddir)/../utils/static_tls.c' || echo '$(srcdir)/'`$(top_builddir)/../utils/static_tls.c + +$(top_builddir)/../utils/spindle_bootstrap-static_tls.obj: $(top_builddir)/../utils/static_tls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spindle_bootstrap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT $(top_builddir)/../utils/spindle_bootstrap-static_tls.obj -MD -MP -MF $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-static_tls.Tpo -c -o $(top_builddir)/../utils/spindle_bootstrap-static_tls.obj `if test -f '$(top_builddir)/../utils/static_tls.c'; then $(CYGPATH_W) '$(top_builddir)/../utils/static_tls.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/../utils/static_tls.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-static_tls.Tpo $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-static_tls.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_builddir)/../utils/static_tls.c' object='$(top_builddir)/../utils/spindle_bootstrap-static_tls.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spindle_bootstrap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o $(top_builddir)/../utils/spindle_bootstrap-static_tls.obj `if test -f '$(top_builddir)/../utils/static_tls.c'; then $(CYGPATH_W) '$(top_builddir)/../utils/static_tls.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/../utils/static_tls.c'; fi` + mostlyclean-libtool: -rm -f *.lo @@ -747,6 +767,7 @@ distclean: distclean-am -rm -f $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-getcpu.Po -rm -f $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-parseloc.Po -rm -f $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-spindle_mkdir.Po + -rm -f $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-static_tls.Po -rm -f $(top_builddir)/client/$(DEPDIR)/spindle_bootstrap-exec_util.Po -rm -f $(top_builddir)/client/$(DEPDIR)/spindle_bootstrap-lookup.Po -rm -f ./$(DEPDIR)/spindle_bootstrap-spindle_bootstrap.Po @@ -799,6 +820,7 @@ maintainer-clean: maintainer-clean-am -rm -f $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-getcpu.Po -rm -f $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-parseloc.Po -rm -f $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-spindle_mkdir.Po + -rm -f $(top_builddir)/../utils/$(DEPDIR)/spindle_bootstrap-static_tls.Po -rm -f $(top_builddir)/client/$(DEPDIR)/spindle_bootstrap-exec_util.Po -rm -f $(top_builddir)/client/$(DEPDIR)/spindle_bootstrap-lookup.Po -rm -f ./$(DEPDIR)/spindle_bootstrap-spindle_bootstrap.Po diff --git a/src/client/beboot/spindle_bootstrap.c b/src/client/beboot/spindle_bootstrap.c index b814c5e2..dabd8516 100644 --- a/src/client/beboot/spindle_bootstrap.c +++ b/src/client/beboot/spindle_bootstrap.c @@ -22,6 +22,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include +#include #include #include #include @@ -34,7 +35,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "exec_util.h" #include "shmcache.h" #include "parseloc.h" - +#include "client_libraries.h" #include "config.h" #if !defined(LIBEXECDIR) @@ -65,27 +66,6 @@ static char *executable_abspath; opt_t opts; -char libstr_socket_subaudit[] = PROGLIBDIR "/libspindle_subaudit_socket.so"; -char libstr_pipe_subaudit[] = PROGLIBDIR "/libspindle_subaudit_pipe.so"; -char libstr_biter_subaudit[] = PROGLIBDIR "/libspindle_subaudit_biter.so"; - -char libstr_socket_audit[] = PROGLIBDIR "/libspindle_audit_socket.so"; -char libstr_pipe_audit[] = PROGLIBDIR "/libspindle_audit_pipe.so"; -char libstr_biter_audit[] = PROGLIBDIR "/libspindle_audit_biter.so"; - -#if defined(COMM_SOCKET) -static char *default_audit_libstr = libstr_socket_audit; -static char *default_subaudit_libstr = libstr_socket_subaudit; -#elif defined(COMM_PIPES) -static char *default_audit_libstr = libstr_pipe_audit; -static char *default_subaudit_libstr = libstr_pipe_subaudit; -#elif defined(COMM_BITER) -static char *default_audit_libstr = libstr_biter_audit; -static char *default_subaudit_libstr = libstr_biter_subaudit; -#else -#error Unknown connection type -#endif - extern int spindle_mkdir(char *path); extern char *parse_location(char *loc, number_t number); extern char *realize(char *path); @@ -229,14 +209,27 @@ static void launch_daemon( void ) static void get_executable() { int errcode = 0; + char *glibc_tunables_env_value = NULL; + char *path_component = NULL; + if (!(opts & OPT_RELOCAOUT) || (opts & OPT_REMAPEXEC)) { debug_printf3("Using default executable %s\n", *cmdline); executable = *cmdline; + path_component = find_path_component(ldcsid, *cmdline, NULL); + calc_static_tls(*cmdline, path_component, NULL, &glibc_tunables_env_value, NULL); + if (glibc_tunables_env_value) { + debug_printf2("Setting GLIBC_TUNABLES to '%s' for %s to fix static tls\n", glibc_tunables_env_value, *cmdline); + setenv("GLIBC_TUNABLES", glibc_tunables_env_value, 1); + } + if (path_component) { + free(path_component); + path_component = NULL; + } return; } debug_printf2("Sending request for executable %s\n", *cmdline); - exec_pathsearch(ldcsid, *cmdline, &executable, &errcode, &executable_abspath); + exec_pathsearch(ldcsid, *cmdline, &executable, &errcode, &executable_abspath, &path_component); if (executable == NULL) { executable = *cmdline; @@ -246,6 +239,16 @@ static void get_executable() debug_printf("Relocated executable %s to %s\n", *cmdline, executable); chmod(executable, 0700); } + + calc_static_tls(*cmdline, path_component, NULL, &glibc_tunables_env_value, NULL); + if (glibc_tunables_env_value) { + debug_printf2("Setting GLIBC_TUNABLES to '%s' for %s to fix static tls\n", glibc_tunables_env_value, *cmdline); + setenv("GLIBC_TUNABLES", glibc_tunables_env_value, 1); + } + + if (path_component) { + free(path_component); + } } static void adjust_script() diff --git a/src/client/client/Makefile.am b/src/client/client/Makefile.am index 46c13d77..465e31d7 100644 --- a/src/client/client/Makefile.am +++ b/src/client/client/Makefile.am @@ -20,7 +20,8 @@ INTERCEPT_SRCS = intercept_open.c intercept_exec.c intercept_stat.c intercept_re BASE_SRCS = client.c \ lookup.c should_intercept.c exec_util.c remap_exec.c \ lookup_libc.c adjust_argv.c $(top_srcdir)/../utils/parseloc.c \ - $(top_srcdir)/../utils/getcpu.c + $(top_srcdir)/../utils/getcpu.c \ + $(top_srcdir)/../utils/static_tls.c BASE_SRCS += $(top_srcdir)/crash_handler/crash_io.c \ $(top_srcdir)/crash_handler/crash_fmt.c \ diff --git a/src/client/client/Makefile.in b/src/client/client/Makefile.in index cf1c9c5b..ae4f64af 100644 --- a/src/client/client/Makefile.in +++ b/src/client/client/Makefile.in @@ -138,6 +138,7 @@ am__objects_2 = client.lo lookup.lo should_intercept.lo exec_util.lo \ remap_exec.lo lookup_libc.lo adjust_argv.lo \ $(top_builddir)/../utils/parseloc.lo \ $(top_builddir)/../utils/getcpu.lo \ + $(top_builddir)/../utils/static_tls.lo \ $(top_builddir)/crash_handler/crash_io.lo \ $(top_builddir)/crash_handler/crash_fmt.lo \ $(top_builddir)/crash_handler/crash_handler.lo \ @@ -179,11 +180,12 @@ am__maybe_remake_depfiles = depfiles am__depfiles_remade = $(top_builddir)/../utils/$(DEPDIR)/getcpu.Plo \ $(top_builddir)/../utils/$(DEPDIR)/libspindle_audit_la-fileutil.Plo \ $(top_builddir)/../utils/$(DEPDIR)/parseloc.Plo \ + $(top_builddir)/../utils/$(DEPDIR)/static_tls.Plo \ + $(top_builddir)/crash_handler/$(DEPDIR)/crash_corename.Plo \ $(top_builddir)/crash_handler/$(DEPDIR)/crash_fmt.Plo \ $(top_builddir)/crash_handler/$(DEPDIR)/crash_handler.Plo \ $(top_builddir)/crash_handler/$(DEPDIR)/crash_io.Plo \ $(top_builddir)/crash_handler/$(DEPDIR)/crash_lib_offset.Plo \ - $(top_builddir)/crash_handler/$(DEPDIR)/crash_corename.Plo \ $(top_builddir)/crash_handler/$(DEPDIR)/crash_sigchain.Plo \ ./$(DEPDIR)/adjust_argv.Plo ./$(DEPDIR)/client.Plo \ ./$(DEPDIR)/exec_util.Plo \ @@ -393,6 +395,7 @@ BASE_SRCS = client.c lookup.c should_intercept.c exec_util.c \ remap_exec.c lookup_libc.c adjust_argv.c \ $(top_srcdir)/../utils/parseloc.c \ $(top_srcdir)/../utils/getcpu.c \ + $(top_srcdir)/../utils/static_tls.c \ $(top_srcdir)/crash_handler/crash_io.c \ $(top_srcdir)/crash_handler/crash_fmt.c \ $(top_srcdir)/crash_handler/crash_handler.c \ @@ -469,6 +472,9 @@ $(top_builddir)/../utils/parseloc.lo: \ $(top_builddir)/../utils/getcpu.lo: \ $(top_builddir)/../utils/$(am__dirstamp) \ $(top_builddir)/../utils/$(DEPDIR)/$(am__dirstamp) +$(top_builddir)/../utils/static_tls.lo: \ + $(top_builddir)/../utils/$(am__dirstamp) \ + $(top_builddir)/../utils/$(DEPDIR)/$(am__dirstamp) $(top_builddir)/crash_handler/$(am__dirstamp): @$(MKDIR_P) $(top_builddir)/crash_handler @: > $(top_builddir)/crash_handler/$(am__dirstamp) @@ -516,11 +522,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/../utils/$(DEPDIR)/getcpu.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/../utils/$(DEPDIR)/libspindle_audit_la-fileutil.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/../utils/$(DEPDIR)/parseloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/../utils/$(DEPDIR)/static_tls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/crash_handler/$(DEPDIR)/crash_corename.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/crash_handler/$(DEPDIR)/crash_fmt.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/crash_handler/$(DEPDIR)/crash_handler.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/crash_handler/$(DEPDIR)/crash_io.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/crash_handler/$(DEPDIR)/crash_lib_offset.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/crash_handler/$(DEPDIR)/crash_corename.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/crash_handler/$(DEPDIR)/crash_sigchain.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adjust_argv.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client.Plo@am__quote@ # am--include-marker @@ -779,6 +786,8 @@ distclean: distclean-am -rm -f $(top_builddir)/../utils/$(DEPDIR)/getcpu.Plo -rm -f $(top_builddir)/../utils/$(DEPDIR)/libspindle_audit_la-fileutil.Plo -rm -f $(top_builddir)/../utils/$(DEPDIR)/parseloc.Plo + -rm -f $(top_builddir)/../utils/$(DEPDIR)/static_tls.Plo + -rm -f $(top_builddir)/crash_handler/$(DEPDIR)/crash_corename.Plo -rm -f $(top_builddir)/crash_handler/$(DEPDIR)/crash_fmt.Plo -rm -f $(top_builddir)/crash_handler/$(DEPDIR)/crash_handler.Plo -rm -f $(top_builddir)/crash_handler/$(DEPDIR)/crash_io.Plo @@ -848,6 +857,8 @@ maintainer-clean: maintainer-clean-am -rm -f $(top_builddir)/../utils/$(DEPDIR)/getcpu.Plo -rm -f $(top_builddir)/../utils/$(DEPDIR)/libspindle_audit_la-fileutil.Plo -rm -f $(top_builddir)/../utils/$(DEPDIR)/parseloc.Plo + -rm -f $(top_builddir)/../utils/$(DEPDIR)/static_tls.Plo + -rm -f $(top_builddir)/crash_handler/$(DEPDIR)/crash_corename.Plo -rm -f $(top_builddir)/crash_handler/$(DEPDIR)/crash_fmt.Plo -rm -f $(top_builddir)/crash_handler/$(DEPDIR)/crash_handler.Plo -rm -f $(top_builddir)/crash_handler/$(DEPDIR)/crash_io.Plo diff --git a/src/client/client/exec_util.c b/src/client/client/exec_util.c index 2ea4c75f..b66c38f3 100644 --- a/src/client/client/exec_util.c +++ b/src/client/client/exec_util.c @@ -28,6 +28,7 @@ #include "client_heap.h" #include "client_api.h" #include "config.h" +#include "spindle_launch.h" static int is_script(int fd, char *path) { @@ -198,7 +199,6 @@ int adjust_if_script(const char *orig_path, char *reloc_path, char **argv, char for (i = 0; i < interp_argc; i++) { (*new_argv)[j++] = spindle_strdup(interpreter_args[i]); } - if (found_from_pathsearch) { (*new_argv)[j++] = spindle_strdup(found_from_pathsearch); } @@ -222,44 +222,117 @@ int adjust_if_script(const char *orig_path, char *reloc_path, char **argv, char return 0; } -int exec_pathsearch(int ldcsid, const char *orig_exec, char **reloc_exec, int *errcode, char **orig_file_abspath) +#define TLSVAR "glibc.rtld.optional_static_tls" +#define TLSVAR_ALIGNMENT "glibc.rtld.optional_static_tls_alignment" +static void update_existing_glibc_tunables(ssize_t tls_needed, size_t tls_alignment, const char *glibc_tunables, char **glibc_tunables_env_value) { - char *saveptr = NULL, *path, *cur; - char newexec[MAX_PATH_LEN+1]; + char *s, *state, *d, *newstr; + size_t newstr_cur = 0, newstr_size, alignment_needed; + ssize_t existing_tls_size = -1, existing_tls_alignment = -1; + int result; + state = NULL; + d = strdup(glibc_tunables); + + newstr_size = strlen(glibc_tunables) + 128; + newstr = (char *) malloc(newstr_size); + for (s = strtok_r(d, ":", &state); s != NULL; s = strtok_r(NULL, ":", &state)) { + if (strncmp(s, TLSVAR "=", strlen(TLSVAR "=")) == 0) { + if (existing_tls_size != -1) + continue; + if (newstr_cur != 0) { //Add a colon if not at the first entry + snprintf(newstr + newstr_cur, newstr_size - newstr_cur, ":"); + newstr_cur++; + } + sscanf(s, TLSVAR "=%zi", &existing_tls_size); + if (existing_tls_size > tls_needed) + tls_needed = existing_tls_size + 4096; + result = snprintf(newstr + newstr_cur, newstr_size - newstr_cur, TLSVAR "=%zu", tls_needed); + newstr_cur += result; + assert(newstr_cur <= newstr_size); + continue; + } + + if (strncmp(s, TLSVAR_ALIGNMENT "=", strlen(TLSVAR_ALIGNMENT "=")) == 0) { + if (existing_tls_alignment != -1) + continue; + if (newstr_cur != 0) { //Add a colon if not at the first entry + snprintf(newstr + newstr_cur, newstr_size - newstr_cur, ":"); + newstr_cur++; + } + sscanf(s, TLSVAR_ALIGNMENT "=%zi", &existing_tls_alignment); + alignment_needed = (existing_tls_alignment > tls_alignment) ? existing_tls_alignment : tls_alignment; + result = snprintf(newstr + newstr_cur, newstr_size - newstr_cur, TLSVAR_ALIGNMENT "=%zu", alignment_needed); + newstr_cur += result; + assert(newstr_cur <= newstr_size); + continue; + } + + if (newstr_cur != 0) { + snprintf(newstr + newstr_cur, newstr_size - newstr_cur, ":"); + newstr_cur++; + } + result = snprintf(newstr + newstr_cur, newstr_size - newstr_cur, "%s", s); + newstr_cur += result; + assert(newstr_cur <= newstr_size); + continue; + } + if (existing_tls_size == -1) { + if (newstr_cur != 0) { + snprintf(newstr + newstr_cur, newstr_size - newstr_cur, ":"); + newstr_cur++; + } + result = snprintf(newstr + newstr_cur, newstr_size - newstr_cur, TLSVAR "=%zu", tls_needed); + newstr_cur += result; + } + if (existing_tls_alignment == -1) { + if (newstr_cur != 0) { + snprintf(newstr + newstr_cur, newstr_size - newstr_cur, ":"); + newstr_cur++; + } + result = snprintf(newstr + newstr_cur, newstr_size - newstr_cur, TLSVAR_ALIGNMENT "=%zu", tls_alignment); + newstr_cur += result; + } + free(d); + *glibc_tunables_env_value = newstr; +} +void setup_new_glibc_tunables(ssize_t tls_needed, size_t tls_alignment, char **glibc_tunables_env_value) +{ + size_t val_size = 128; + char *val = (char *) spindle_malloc(val_size); + snprintf(val, val_size, "%s=%zu:%s=%zu", TLSVAR, tls_needed, TLSVAR_ALIGNMENT, tls_alignment); + *glibc_tunables_env_value = val; +} + +char *find_path_component(int ldcsid, const char *orig_exec, int *errcode) +{ + char *saveptr = NULL, *path, *cur, *found_dir; + char newexec[MAX_PATH_LEN+1]; + int access_denied_found = 0; + if (!orig_exec) { - err_printf("Null exec passed to exec_pathsearch\n"); - *reloc_exec = NULL; - return -1; + return NULL; } - if (orig_file_abspath) { - *orig_file_abspath = NULL; - } - + + /* Absolute or relative paths don't need PATH search */ if (orig_exec[0] == '/' || orig_exec[0] == '.') { - get_relocated_file(ldcsid, (char *) orig_exec, 1, reloc_exec, errcode, NULL); - debug_printf3("exec_pathsearch translated %s to %s\n", orig_exec, *reloc_exec); - return 0; + return NULL; } path = getenv("PATH"); if (!path) { - get_relocated_file(ldcsid, (char *) orig_exec, 1, reloc_exec, errcode, NULL); - debug_printf3("No path. exec_pathsearch translated %s to %s\n", orig_exec, *reloc_exec); - return 0; + return NULL; } path = spindle_strdup(path); - debug_printf3("exec_pathsearch using path %s on file %s\n", path, orig_exec); - int found = 0; - int access_denied_found = 0; + debug_printf3("find_path_component using path %s on file %s\n", path, orig_exec); for (cur = strtok_r(path, ":", &saveptr); cur; cur = strtok_r(NULL, ":", &saveptr)) { struct stat buf; int exists = 0; snprintf(newexec, MAX_PATH_LEN, "%s/%s", cur, orig_exec); newexec[MAX_PATH_LEN] = '\0'; - - debug_printf2("Exec search operation requesting file via stat: %s\n", newexec); + + debug_printf2("Path search operation requesting file via stat: %s\n", newexec); int result = get_stat_result(ldcsid, newexec, 0, &exists, &buf); if (result == STAT_SELF_OPEN) { result = stat(newexec, &buf); @@ -269,39 +342,179 @@ int exec_pathsearch(int ldcsid, const char *orig_exec, char **reloc_exec, int *e continue; if (buf.st_mode & S_IFDIR) { debug_printf3("Skipping file %s in pathsearch: directory\n", newexec); - access_denied_found = 1; + access_denied_found = 1; continue; } if (!(buf.st_mode & 0111)) { debug_printf3("Skipping file %s in pathsearch: not executable\n", newexec); - access_denied_found = 1; + access_denied_found = 1; continue; } - debug_printf2("File %s exists and has execute set, requesting full file\n", newexec); - get_relocated_file(ldcsid, newexec, 1, reloc_exec, errcode, NULL); - debug_printf2("Exec search request returned %s -> %s\n", newexec, *reloc_exec ? *reloc_exec : "NULL"); - if (*reloc_exec) { - if (orig_file_abspath) { - *orig_file_abspath = spindle_strdup(newexec); - } - found = 1; - break; - } - if (*errcode == EACCES) { - *reloc_exec = spindle_strdup(newexec); - found = 1; - break; - } + debug_printf2("File %s exists and has execute set in %s\n", newexec, cur); + found_dir = spindle_strdup(cur); + spindle_free(path); + return found_dir; + } + if (errcode) { + *errcode = access_denied_found ? EACCES : ENOENT; } spindle_free(path); - if (found) + return NULL; +} + +//Magic constants from GLIBC. +#define DEFAULT_TLS_STATIC_SURPLUS 1664 +#define DEFAULT_ALIGNMENT 64 + +int calc_static_tls(const char *orig_exec, const char *path_component, const char **envp, char **glibc_tunables_env_value, int *updated_existing_environ) +{ + const char *ld_preload = NULL, *ld_library_path = NULL, *glibc_tunables = NULL; + char cwd[MAX_PATH_LEN+1]; + int i, result; + ssize_t tls_size, tls_alignment; + + if (glibc_tunables_env_value) + *glibc_tunables_env_value = NULL; + if (updated_existing_environ) + *updated_existing_environ = 0; + if (!(opts & OPT_CALCTLS)) { return 0; + } - if (access_denied_found) { - debug_printf3("Non executable file, setting errcode to %d\n", EACCES); - *errcode = EACCES; + if (envp) { + for(i = 0; envp[i] != NULL; i++) { + if (strncmp(envp[i], "LD_LIBRARY_PATH=", strlen("LD_LIBRARY_PATH=")) == 0) + ld_library_path = envp[i] + strlen("LD_LIBRARY_PATH="); + if (strncmp(envp[i], "LD_PRELOAD=", strlen("LD_PRELOAD=")) == 0) + ld_preload = envp[i] + strlen("LD_PRELOAD="); + if (strncmp(envp[i], "GLIBC_TUNABLES=", strlen("GLIBC_TUNABLES=")) == 0) + glibc_tunables = envp[i] + strlen("GLIBC_TUNABLES="); + } + } + else { + ld_library_path = getenv("LD_LIBRARY_PATH"); + ld_preload = getenv("LD_PRELOAD"); + glibc_tunables = getenv("GLIBC_TUNABLES"); + } + getcwd(cwd, MAX_PATH_LEN+1); + + debug_printf2("calc_static_tls for %s with path_component %s, LD_PRELOAD=%s\n", orig_exec, path_component ? path_component : "NULL", ld_preload ? ld_preload : "NULL"); + result = send_static_tls_query(ldcsid, orig_exec, ld_library_path, ld_preload, cwd, path_component, &tls_size, &tls_alignment); + if (result == -1 || tls_size == -1) { + tls_size = 0; + tls_alignment = 0; + debug_printf("Could not compute TLS. got size %lu/+%lu\n", (unsigned long) tls_size, (unsigned long) tls_alignment); + return 0; + } + + if (tls_size < DEFAULT_TLS_STATIC_SURPLUS && tls_alignment < DEFAULT_ALIGNMENT) { + debug_printf2("Requested TLS size and alignment %lu/+%lu is less than defaults %lu/+%lu\n", + (unsigned long) tls_size, (unsigned long) tls_alignment, + (unsigned long) DEFAULT_TLS_STATIC_SURPLUS, (unsigned long) DEFAULT_ALIGNMENT); + return 0; + } + if (tls_size == 0) { + *glibc_tunables_env_value = NULL; + if (updated_existing_environ) *updated_existing_environ = 0; + } + else if (glibc_tunables) { + update_existing_glibc_tunables(tls_size, tls_alignment, glibc_tunables, glibc_tunables_env_value); + debug_printf3("Setting tunables to %s\n", *glibc_tunables_env_value); + if (updated_existing_environ) *updated_existing_environ = 1; + } + else { + setup_new_glibc_tunables(tls_size, tls_alignment, glibc_tunables_env_value); + debug_printf3("Setting tunables to %s\n", *glibc_tunables_env_value); + if (updated_existing_environ) *updated_existing_environ = 0; + } + + debug_printf2("Calculated static TLS size %zd and alignment %zd for %s\n", tls_size, tls_alignment, orig_exec); + return 0; +} + +int exec_pathsearch(int ldcsid, const char *orig_exec, char **reloc_exec, int *errcode, char **orig_file_abspath, char **path_component) +{ + char *found_path_component = NULL; + char *path; + char newexec[MAX_PATH_LEN+1]; + int local_errcode = 0; + + if (!orig_exec) { + err_printf("Null exec passed to exec_pathsearch\n"); + *reloc_exec = NULL; + return -1; + } + if (orig_file_abspath) { + *orig_file_abspath = NULL; + } + if (path_component) { + *path_component = NULL; + } + + /* Handle absolute/relative paths - no PATH search needed */ + if (orig_exec[0] == '/' || orig_exec[0] == '.') { + get_relocated_file(ldcsid, (char *) orig_exec, 1, reloc_exec, errcode, NULL); + debug_printf3("exec_pathsearch translated %s to %s\n", orig_exec, *reloc_exec); + return 0; + } + + /* Check if PATH is set */ + path = getenv("PATH"); + if (!path) { + /* No PATH set - try to relocate file as-is (execvp fallback behavior) */ + get_relocated_file(ldcsid, (char *) orig_exec, 1, reloc_exec, errcode, NULL); + debug_printf3("No PATH. exec_pathsearch translated %s to %s\n", orig_exec, *reloc_exec); + return 0; + } + + /* Find which PATH component contains the executable */ + found_path_component = find_path_component(ldcsid, orig_exec, &local_errcode); + if (!found_path_component) { + /* File not found in PATH */ + *errcode = local_errcode; return -1; } + + /* Build full path and relocate */ + snprintf(newexec, MAX_PATH_LEN, "%s/%s", found_path_component, orig_exec); + newexec[MAX_PATH_LEN] = '\0'; + + debug_printf2("File %s exists and has execute set, requesting full file\n", newexec); + get_relocated_file(ldcsid, newexec, 1, reloc_exec, errcode, NULL); + debug_printf2("Exec search request returned %s -> %s\n", newexec, *reloc_exec ? *reloc_exec : "NULL"); + + if (*reloc_exec) { + if (orig_file_abspath) { + *orig_file_abspath = spindle_strdup(newexec); + } + if (path_component) { + *path_component = found_path_component; + found_path_component = NULL; /* Transfer ownership */ + } + if (found_path_component) { + spindle_free(found_path_component); + } + return 0; + } + + /* Handle EACCES case */ + if (*errcode == EACCES) { + *reloc_exec = spindle_strdup(newexec); + if (path_component) { + *path_component = found_path_component; + found_path_component = NULL; /* Transfer ownership */ + } + if (found_path_component) { + spindle_free(found_path_component); + } + return 0; + } + + if (found_path_component) { + spindle_free(found_path_component); + } + + /* Not found */ *errcode = ENOENT; return -1; } diff --git a/src/client/client/exec_util.h b/src/client/client/exec_util.h index 177df0e1..7ee826c3 100644 --- a/src/client/client/exec_util.h +++ b/src/client/client/exec_util.h @@ -23,7 +23,9 @@ #define SCRIPT_CANTEMULATE -4 int adjust_if_script(const char *orig_path, char *reloc_path, char **argv, char **interp_path, char ***new_argv, char *found_from_pathsearch); -int exec_pathsearch(int ldcsid, const char *orig_exec, char **new_exec, int *errcode, char **orig_file_abspath); +int exec_pathsearch(int ldcsid, const char *orig_exec, char **new_exec, int *errcode, char **orig_file_abspath, char **path_component); +char *find_path_component(int ldcsid, const char *executable_name, int *errcode); +int calc_static_tls(const char *orig_exec, const char *path_component, const char **envp, char **glibc_tunables_env_value, int *updated_existing_environ); int isExecExcluded(const char *fname); int get_dirlists(char ***prefixes, char ***eexecs); diff --git a/src/client/client/intercept_exec.c b/src/client/client/intercept_exec.c index edb0199a..9cd18b54 100644 --- a/src/client/client/intercept_exec.c +++ b/src/client/client/intercept_exec.c @@ -118,12 +118,30 @@ static void propogateEnvironmentStr(char *const orig_envp[], char **new_envp, in { char *value; - value = orig_getenv ? orig_getenv(var) : getenv(var); - if (!value) - return; - if (envpContains(orig_envp, var)) + /* For GLIBC_TUNABLES, always use regular getenv since we may have just set it with setenv */ + if (strcmp(var, "GLIBC_TUNABLES") == 0) { + value = getenv(var); + } + else { + value = orig_getenv ? orig_getenv(var) : getenv(var); + } + if (!value) { + if (strcmp(var, "GLIBC_TUNABLES") == 0) + debug_printf("propogateEnvironmentStr: GLIBC_TUNABLES not in environment\n"); return; - debug_printf3("Adding environment variable %s to env\n", var); + } + if (envpContains(orig_envp, var)) { + /* Special case: GLIBC_TUNABLES may need to be updated for static TLS */ + if (strcmp(var, "GLIBC_TUNABLES") != 0) + return; + debug_printf("Replacing GLIBC_TUNABLES in env with value: %s\n", value); + } + else { + if (strcmp(var, "GLIBC_TUNABLES") == 0) + debug_printf("Adding GLIBC_TUNABLES to env with value: %s\n", value); + else + debug_printf3("Adding environment variable %s to env\n", var); + } new_envp[*pos] = allocEnvAssignmentStr(var, value); (*pos)++; } @@ -167,7 +185,6 @@ static char **updateEnvironment(char **envp, int *num_modified, int propogate_sp if (num_modified && !envp) { envp = empty_env; } - if (!propogate_spindle) { if (!envp) { debug_printf2("Removing spindle from environment by unsetenv\n"); @@ -196,10 +213,10 @@ static char **updateEnvironment(char **envp, int *num_modified, int propogate_sp if (envp) { debug_printf2("Propogating spindle environment by copying it to new envp list\n"); for (cur = (char **) envp; *cur; cur++, orig_size++); - new_size = orig_size + 9; + new_size = orig_size + 10; newenv = (char **) malloc(new_size * sizeof(char*)); - - propogateEnvironmentStr(envp, newenv, &pos, "SPINDLE"); + + propogateEnvironmentStr(envp, newenv, &pos, "SPINDLE"); propogateEnvironmentStr(envp, newenv, &pos, "LD_AUDIT"); propogateEnvironmentStr(envp, newenv, &pos, "LDCS_COMMPATH"); propogateEnvironmentStr(envp, newenv, &pos, "LDCS_CONNECTION"); @@ -207,8 +224,12 @@ static char **updateEnvironment(char **envp, int *num_modified, int propogate_sp propogateEnvironmentStr(envp, newenv, &pos, "LDCS_OPTIONS"); propogateEnvironmentStr(envp, newenv, &pos, "LDCS_CACHESIZE"); propogateEnvironmentStr(envp, newenv, &pos, "LDCS_NUMBER"); + propogateEnvironmentStr(envp, newenv, &pos, "GLIBC_TUNABLES"); *num_modified = pos; for (cur = (char **) envp; *cur; cur++) { + /* Skip GLIBC_TUNABLES if it was in envp, as we may have updated it */ + if (strIsPrefix("GLIBC_TUNABLES=", *cur)) + continue; newenv[pos++] = *cur; } newenv[pos++] = NULL; @@ -244,11 +265,12 @@ static void cleanEnvironment(char **envp, int num_modified) { static int prep_exec(const char *filepath, char **argv, char *newname, char *newpath, int newpath_size, - char ***new_argv, int errcode, char *found_from_pathsearch) + char ***new_argv, int errcode, char *orig_file_abspath, char *path_component, char **envp) { int result; char *interp_name; int i; + char *glibc_tunables_env_value = NULL; debug_printf3("prep_exec for filepath %s to newpath %s\n", filepath, newpath); if (spindle_debug_prints >= 3) { @@ -257,8 +279,7 @@ static int prep_exec(const char *filepath, char **argv, debug_printf3("%d. %s\n", i, argv[i]); } } - - + if (errcode == EACCES) { strncpy(newpath, filepath, newpath_size); newpath[newpath_size-1] = '\0'; @@ -272,14 +293,23 @@ static int prep_exec(const char *filepath, char **argv, set_errno(errcode); return -1; } - + if (!newname) { snprintf(newpath, newpath_size, "%s/%s", NOT_FOUND_PREFIX, filepath); newpath[newpath_size-1] = '\0'; return 0; } - result = adjust_if_script(filepath, newname, argv, &interp_name, new_argv, found_from_pathsearch); + calc_static_tls(filepath, path_component, (const char **)envp, &glibc_tunables_env_value, NULL); + if (glibc_tunables_env_value) { + debug_printf("Setting GLIBC_TUNABLES to '%s' for %s to fix static tls\n", glibc_tunables_env_value, filepath); + setenv("GLIBC_TUNABLES", glibc_tunables_env_value, 1); + } + else { + debug_printf("calc_static_tls returned NULL for GLIBC_TUNABLES for %s\n", filepath); + } + + result = adjust_if_script(filepath, newname, argv, &interp_name, new_argv, orig_file_abspath); if (opts & OPT_REMAPEXEC) { debug_printf2("exec'ing original path %s because we're running in remap mode\n", filepath); strncpy(newpath, filepath, newpath_size); @@ -379,14 +409,15 @@ static int find_exec(const char *filepath, char **argv, char *newpath, int newpa get_relocated_file(ldcsid, (char *) filepath, 1, &newname, &errcode, NULL); debug_printf("Exec file request returned %s -> %s with errcode %d\n", filepath, newname ? newname : "NULL", errcode); - - return prep_exec(filepath, argv, newname, newpath, newpath_size, new_argv, errcode, NULL); + + return prep_exec(filepath, argv, newname, newpath, newpath_size, new_argv, errcode, NULL, NULL, envp); } static int find_exec_pathsearch(const char *filepath, char **argv, char *newpath, int newpath_size, char ***new_argv, char **envp, int *propogate_spindle) { char *newname = NULL; char *orig_file_abspath = NULL; + char *path_component = NULL; int result; int errcode; int reloc_exec; @@ -415,9 +446,9 @@ static int find_exec_pathsearch(const char *filepath, char **argv, char *newpath newpath[newpath_size-1] = '\0'; return 0; } - + sync_cwd(); - result = exec_pathsearch(ldcsid, filepath, &newname, &errcode, &orig_file_abspath); + result = exec_pathsearch(ldcsid, filepath, &newname, &errcode, &orig_file_abspath, &path_component); if (result == -1) { set_errno(errcode); return -1; @@ -425,7 +456,7 @@ static int find_exec_pathsearch(const char *filepath, char **argv, char *newpath debug_printf("Exec file request returned %s -> %s with errcode %d\n", filepath, newname ? newname : "NULL", errcode); - return prep_exec(filepath, argv, newname, newpath, newpath_size, new_argv, errcode, orig_file_abspath); + return prep_exec(filepath, argv, newname, newpath, newpath_size, new_argv, errcode, orig_file_abspath, path_component, envp); } int execl_wrapper(const char *path, const char *arg0, ...) diff --git a/src/client/client_comlib/Makefile.am b/src/client/client_comlib/Makefile.am index 7c02cf6a..4e44eed8 100644 --- a/src/client/client_comlib/Makefile.am +++ b/src/client/client_comlib/Makefile.am @@ -1,6 +1,6 @@ noinst_LTLIBRARIES = -AM_CPPFLAGS = -I$(top_srcdir)/../logging -I$(top_srcdir)/../include +AM_CPPFLAGS = -I$(top_srcdir)/../logging -I$(top_srcdir)/../include -I$(top_srcdir)/../utils BASE_SRCS = client_api.c client_heap.c client_wrappers.c diff --git a/src/client/client_comlib/Makefile.in b/src/client/client_comlib/Makefile.in index cf33f5e9..5012780a 100644 --- a/src/client/client_comlib/Makefile.in +++ b/src/client/client_comlib/Makefile.in @@ -346,7 +346,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ noinst_LTLIBRARIES = libclient_pipe.la libclient_socket.la \ libclient_biter.la -AM_CPPFLAGS = -I$(top_srcdir)/../logging -I$(top_srcdir)/../include +AM_CPPFLAGS = -I$(top_srcdir)/../logging -I$(top_srcdir)/../include -I$(top_srcdir)/../utils BASE_SRCS = client_api.c client_heap.c client_wrappers.c AM_CFLAGS = -fvisibility=hidden libclient_pipe_la_CPPFLAGS = $(AM_CPPFLAGS) -DCOMM=pipe diff --git a/src/client/client_comlib/client_api.c b/src/client/client_comlib/client_api.c index 093c3344..12e08456 100644 --- a/src/client/client_comlib/client_api.c +++ b/src/client/client_comlib/client_api.c @@ -32,6 +32,7 @@ #include "ldcs_api.h" #include "client_api.h" #include "client_heap.h" +#include "static_tls.h" struct lock_t comm_lock; @@ -43,7 +44,6 @@ void reset_comm_lock(void) reset_lock(&comm_lock); } - int send_cachepath_query( int fd, char **chosen_realized_cachepath, char **chosen_parsed_cachepath){ int rc = 0; ldcs_message_t message; @@ -512,6 +512,50 @@ int send_pickone_query(int fd, char *key, int *result) return 0; } +int send_static_tls_query(int fd, const char *aout, const char *ld_library_path, const char *ld_preload, const char *cwd, const char *path_component, ssize_t *tls_needed, ssize_t *tls_alignment) +{ + int result, size; + char *buffer; + ldcs_message_t message; + + debug_printf2("Sending request for static TLS size needed for '%s' with ld_library_path='%s' ; ld_preload = '%s' ; cwd = '%s' ; path_component = '%s'\n", + aout, ld_library_path, ld_preload, cwd, path_component); + *tls_needed = 0; + *tls_alignment = 0; + size = static_tls_info_encode_size_needed(aout, ld_library_path, ld_preload, cwd, path_component); + if (size < 2*sizeof(ssize_t)) + size = 2*sizeof(ssize_t); + + buffer = (char *) spindle_malloc(size); + result = static_tls_info_encode(aout, ld_library_path, ld_preload, cwd, path_component, buffer, size, &size); + if (result == -1) { + err_printf("Failed to encode static tls packet\n"); + spindle_free(buffer); + return -1; + } + + message.header.type = LDCS_MSG_CLIENT_STATICTLS; + message.header.len = size; + message.data = buffer; + + debug_printf3("Sending LDCS_MSG_CLIENT_STATICTLS for %s\n", aout); + COMM_LOCK; + client_send_msg(fd, &message); + client_recv_msg_static(fd, &message, LDCS_READ_BLOCK); + COMM_UNLOCK; + + if (message.header.type != LDCS_MSG_CLIENT_STATICTLS_RESP) { + err_printf("Unexpected response %d\n", message.header.type); + spindle_free(buffer); + return -1; + } + *tls_needed = *((ssize_t *) message.data); + *tls_alignment = *((ssize_t *) (message.data + sizeof(ssize_t))); + spindle_free(buffer); + debug_printf3("Recvd LDCS_MSG_CLIENT_STATICTLS_RESP for %s of size %zd and alignment %zd\n", aout, *tls_needed, *tls_alignment); + return 0; +} + int send_end(int fd) { ldcs_message_t message; diff --git a/src/client/client_comlib/client_api.h b/src/client/client_comlib/client_api.h index b9531eb4..08c174cd 100644 --- a/src/client/client_comlib/client_api.h +++ b/src/client/client_comlib/client_api.h @@ -45,6 +45,7 @@ int send_dirlists_request(int fd, char **local_result, char **exece_result, char int send_procmaps_query(int fd, int pid, char *result); int send_pickone_query(int fd, char *key, int *result); int send_cachepath_query( int fd, char **chosen_symbolic_cachepath, char **chosen_parsed_cachepath); +int send_static_tls_query(int fd, const char *aout, const char *ld_library_path, const char *ld_preload, const char *cwd, const char *path_component, ssize_t *tls_needed, ssize_t *tls_alignment); int get_python_prefix(int fd, char **prefix); diff --git a/src/client/config.h.in b/src/client/config.h.in index 5b61f2f3..77afb2b6 100644 --- a/src/client/config.h.in +++ b/src/client/config.h.in @@ -144,6 +144,9 @@ /* The default port for Spindle */ #undef SPINDLE_PORT +/* Defined if GLIBC has static TLS allocation bug */ +#undef STATIC_TLS_ALLOC_BUG + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS diff --git a/src/client/configure b/src/client/configure index 290d99d8..cd790db9 100755 --- a/src/client/configure +++ b/src/client/configure @@ -814,6 +814,7 @@ with_localstorage with_cachepaths with_cachepath with_commpaths +with_commpath with_default_local_prefix with_testrm with_rm @@ -1538,12 +1539,13 @@ Optional Packages: Number of TCP/IP ports to scan for Spindle server communication --with-localstorage=DIR (obsolete) - Use --with-cachepaths and --with-commpath instead. + Use --with-cachepaths and --with-commpaths instead. --with-cachepaths=DIR Colon-separated list of potential back-end cache directories -, - --with-compaths=DIR Colon-separated list of candidate paths for back-end + --with-cachepath=DIR Synonym for --with-cachepaths + --with-commpaths=DIR Colon-separated list of candidate paths for back-end communication and housekeeping + --with-commpath=DIR Synonym for --with-commpaths --with-default-local-prefix=DIRS Colon-seperated list of directories that Spindle will not cache files out of @@ -12600,7 +12602,7 @@ fi # Check whether --with-localstorage was given. if test "${with_localstorage+set}" = set; then : - withval=$with_localstorage; as_fn_error $? "requested obsolete option --with-localstorage. Use --with-cachepaths and --with-commpath instead." "$LINENO" 5 + withval=$with_localstorage; as_fn_error $? "requested obsolete option --with-localstorage. Use --with-cachepaths and --with-commpaths instead." "$LINENO" 5 fi @@ -12614,7 +12616,7 @@ fi # Check whether --with-cachepath was given. if test "${with_cachepath+set}" = set; then : - withval=$with_cachepath; as_fn_error $? "use --with-cachepaths=DIRS (plural) instead of --with-cachepath=DIR to specify one or more cache paths" "$LINENO" 5 + withval=$with_cachepath; CACHEPATHS=${withval} fi @@ -12626,6 +12628,12 @@ else fi +# Check whether --with-commpath was given. +if test "${with_commpath+set}" = set; then : + withval=$with_commpath; COMMPATHS=${withval} +fi + + # Check whether --with-default-local-prefix was given. if test "${with_default_local_prefix+set}" = set; then : withval=$with_default_local_prefix; SPINDLE_LOCAL_PREFIX=${withval} @@ -12773,13 +12781,13 @@ _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for locale tls fault glibc bug" >&5 $as_echo_n "checking for locale tls fault glibc bug... " >&6; } if ${SPINDLE_SOURCE_ROOT}/scripts/locale_tls_fault/tls_locale_fault.sh ${SPINDLE_SOURCE_ROOT}/scripts/locale_tls_fault ${SPINDLE_BUILD_ROOT}/locale_tls_fault $CC; then - LOCALE_FAULT_BUG=0 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -else LOCALE_FAULT_BUG=1 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } +else + LOCALE_FAULT_BUG=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi cat >>confdefs.h <<_ACEOF @@ -12787,6 +12795,22 @@ cat >>confdefs.h <<_ACEOF _ACEOF +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for static tls glibc bug" >&5 +$as_echo_n "checking for static tls glibc bug... " >&6; } +if ${SPINDLE_SOURCE_ROOT}/scripts/static_tls_test/run_test.sh ${CC} "${CFLAGS} -g" ${SPINDLE_SOURCE_ROOT} ${SPINDLE_BUILD_ROOT}; then + STATIC_TLS_BUG=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + STATIC_TLS_BUG=1 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi + +cat >>confdefs.h <<_ACEOF +#define STATIC_TLS_ALLOC_BUG $STATIC_TLS_BUG +_ACEOF + #OS Detection # Check whether --enable-bluegene was given. diff --git a/src/cobo/handshake.c b/src/cobo/handshake.c index 74645cab..554984d8 100644 --- a/src/cobo/handshake.c +++ b/src/cobo/handshake.c @@ -1084,7 +1084,7 @@ static int key_decrypt_packet(unsigned char *key, unsigned int key_len, { #if defined(GCRYPT) unsigned char *calcd_hash_val = NULL, *recvd_hash_val; - int result, return_result, hash_val_size; + int result, return_result = 0, hash_val_size; int i; if (recvd_buffer_size < packet_size) { diff --git a/src/fe/config.h.in b/src/fe/config.h.in index 0fb0e6f0..cd178d13 100644 --- a/src/fe/config.h.in +++ b/src/fe/config.h.in @@ -189,6 +189,9 @@ /* The default port for Spindle */ #undef SPINDLE_PORT +/* Defined if GLIBC has static TLS allocation bug */ +#undef STATIC_TLS_ALLOC_BUG + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS diff --git a/src/fe/configure b/src/fe/configure index 293bcfee..380b4e70 100755 --- a/src/fe/configure +++ b/src/fe/configure @@ -835,6 +835,7 @@ with_localstorage with_cachepaths with_cachepath with_commpaths +with_commpath with_default_local_prefix with_testrm with_rm @@ -1576,12 +1577,13 @@ Optional Packages: Number of TCP/IP ports to scan for Spindle server communication --with-localstorage=DIR (obsolete) - Use --with-cachepaths and --with-commpath instead. + Use --with-cachepaths and --with-commpaths instead. --with-cachepaths=DIR Colon-separated list of potential back-end cache directories -, - --with-compaths=DIR Colon-separated list of candidate paths for back-end + --with-cachepath=DIR Synonym for --with-cachepaths + --with-commpaths=DIR Colon-separated list of candidate paths for back-end communication and housekeeping + --with-commpath=DIR Synonym for --with-commpaths --with-default-local-prefix=DIRS Colon-seperated list of directories that Spindle will not cache files out of @@ -16450,7 +16452,7 @@ fi # Check whether --with-localstorage was given. if test "${with_localstorage+set}" = set; then : - withval=$with_localstorage; as_fn_error $? "requested obsolete option --with-localstorage. Use --with-cachepaths and --with-commpath instead." "$LINENO" 5 + withval=$with_localstorage; as_fn_error $? "requested obsolete option --with-localstorage. Use --with-cachepaths and --with-commpaths instead." "$LINENO" 5 fi @@ -16464,7 +16466,7 @@ fi # Check whether --with-cachepath was given. if test "${with_cachepath+set}" = set; then : - withval=$with_cachepath; as_fn_error $? "use --with-cachepaths=DIRS (plural) instead of --with-cachepath=DIR to specify one or more cache paths" "$LINENO" 5 + withval=$with_cachepath; CACHEPATHS=${withval} fi @@ -16476,6 +16478,12 @@ else fi +# Check whether --with-commpath was given. +if test "${with_commpath+set}" = set; then : + withval=$with_commpath; COMMPATHS=${withval} +fi + + # Check whether --with-default-local-prefix was given. if test "${with_default_local_prefix+set}" = set; then : withval=$with_default_local_prefix; SPINDLE_LOCAL_PREFIX=${withval} @@ -16623,13 +16631,13 @@ _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for locale tls fault glibc bug" >&5 $as_echo_n "checking for locale tls fault glibc bug... " >&6; } if ${SPINDLE_SOURCE_ROOT}/scripts/locale_tls_fault/tls_locale_fault.sh ${SPINDLE_SOURCE_ROOT}/scripts/locale_tls_fault ${SPINDLE_BUILD_ROOT}/locale_tls_fault $CC; then - LOCALE_FAULT_BUG=0 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -else LOCALE_FAULT_BUG=1 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } +else + LOCALE_FAULT_BUG=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi cat >>confdefs.h <<_ACEOF @@ -16637,6 +16645,22 @@ cat >>confdefs.h <<_ACEOF _ACEOF +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for static tls glibc bug" >&5 +$as_echo_n "checking for static tls glibc bug... " >&6; } +if ${SPINDLE_SOURCE_ROOT}/scripts/static_tls_test/run_test.sh ${CC} "${CFLAGS} -g" ${SPINDLE_SOURCE_ROOT} ${SPINDLE_BUILD_ROOT}; then + STATIC_TLS_BUG=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + STATIC_TLS_BUG=1 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi + +cat >>confdefs.h <<_ACEOF +#define STATIC_TLS_ALLOC_BUG $STATIC_TLS_BUG +_ACEOF + #OS Detection # Check whether --enable-bluegene was given. diff --git a/src/fe/startup/config_mgr.cc b/src/fe/startup/config_mgr.cc index 18bc5210..27cd87e8 100644 --- a/src/fe/startup/config_mgr.cc +++ b/src/fe/startup/config_mgr.cc @@ -161,6 +161,12 @@ using namespace std; #define PYTHON_PREFIX_DEFAULT "" #endif +#if defined(STATIC_TLS_ALLOC_BUG) && (STATIC_TLS_ALLOC_BUG!=0) +#define DEFAULT_CALC_TLS "true" +#else +#define DEFAULT_CALC_TLS "false" +#endif + #if BINARY_PATCH_LDSO == 1 #define DEFAULT_PATCH_LDSO "true" #else @@ -314,6 +320,8 @@ void initOptionsList() "The command to run rsh/ssh, when doing RSH startup mode." }, { confCrashDedup, "crash-dedup", shortCrashDedup, groupMisc, cvBool, {}, DEFAULT_CRASH_DEDUP_STR, "Deduplicate coredumps by crash site, emitting only one coredump per unique site." }, + { confCalcTLS, "calc-tls", shortCalcTLS, groupMisc, cvBool, {}, DEFAULT_CALC_TLS, + "Enable spindle's manual calculation of an application's IE TLS to work around a glibc bug." }, { confCrashAltstack, "crash-altstack", shortCrashAltstack, groupMisc, cvBool, {}, DEFAULT_CRASH_ALTSTACK_STR, "Registers an alternate stack for signal handlers used by crash deduplication." }, { confCrashLog, "crash-log", shortCrashLog, groupMisc, cvStringOptional, {}, "", @@ -1026,6 +1034,8 @@ bool ConfigMap::toSpindleArgs(spindle_args_t &args, bool alloc_strs) const case confCrashDedup: setopt(args.opts, OPT_CRASH_HANDLER, boolresult); break; + case confCalcTLS: + setopt(args.opts, OPT_CALCTLS, boolresult); case confCrashAltstack: setopt(args.opts, OPT_CRASH_ALTSTACK, boolresult); break; diff --git a/src/fe/startup/config_mgr.h b/src/fe/startup/config_mgr.h index 5fe7a75f..1b90b0f6 100644 --- a/src/fe/startup/config_mgr.h +++ b/src/fe/startup/config_mgr.h @@ -70,6 +70,7 @@ enum SpindleConfigID { confRunSession, confPatchLdso, confCrashDedup, + confCalcTLS, confCrashAltstack, confCrashLog }; @@ -134,6 +135,7 @@ enum CmdlineShortOptions { shortCrashDedup = 301, shortCrashAltstack = 302, shortCrashLog = 303, + shortCalcTLS = 304 }; enum CmdlineGroups { diff --git a/src/include/ldcs_api.h b/src/include/ldcs_api.h index d0a3dcf2..551a1b8e 100644 --- a/src/include/ldcs_api.h +++ b/src/include/ldcs_api.h @@ -89,6 +89,10 @@ typedef enum { LDCS_MSG_CHOSEN_CACHEPATH, LDCS_MSG_CRASH_REPORT, LDCS_MSG_CRASH_RESPONSE, + LDCS_MSG_CLIENT_STATICTLS, + LDCS_MSG_CLIENT_STATICTLS_RESP, + LDCS_MSG_STATICTLS, + LDCS_MSG_STATICTLS_RESP, LDCS_MSG_CRASH_LOG, LDCS_MSG_CRASH_EXE, LDCS_MSG_CRASH_COREPATH, @@ -114,7 +118,6 @@ typedef enum { LDCS_MSG_MDIR_UNKNOWN } ldcs_msg_mdir_t; - /* source, dest: -1: frontend 0...10000: MD server, > 10000 local client */ struct ldcs_message_header_struct { @@ -134,6 +137,7 @@ typedef struct ldcs_message_struct ldcs_message_t; int ldcs_send_msg(int connid, ldcs_message_t * msg); ldcs_message_t * ldcs_recv_msg(int fd, ldcs_read_block_t block); int ldcs_recv_msg_static(int fd, ldcs_message_t *msg, ldcs_read_block_t block); +int ldcs_recv_msg_dynamic(int fd, ldcs_message_t *msg, ldcs_read_block_t block); int ldcs_get_aux_fd(); int ldcs_create_server(char* location, number_t number); diff --git a/src/include/spindle_launch.h b/src/include/spindle_launch.h index 747d8847..a5d3168f 100644 --- a/src/include/spindle_launch.h +++ b/src/include/spindle_launch.h @@ -63,6 +63,7 @@ extern "C" { #define OPT_CRASH_HANDLER ((opt_t) 1 << 32) /* Enables crash handler with coredump deduplication */ #define OPT_CRASH_LOG ((opt_t) 1 << 33) /* Write a log of crash sites and ranks at job end */ #define OPT_CRASH_ALTSTACK ((opt_t) 1 << 34) /* Crash handler registers an alternate signal stack */ +#define OPT_CALCTLS ((opt_t) 1 << 35) /* Enable spindle calculation of IE TLS instead of GLIBC calculation */ #define OPT_SET_SEC(OPT, X) OPT |= (X << 19) #define OPT_GET_SEC(OPT) ((OPT >> 19) & 7) diff --git a/src/server/auditserver/Makefile.am b/src/server/auditserver/Makefile.am index b567d8dd..66b1a331 100644 --- a/src/server/auditserver/Makefile.am +++ b/src/server/auditserver/Makefile.am @@ -1,11 +1,11 @@ #noinst_LTLIBRARIES = libaudit_server_msocket.la libaudit_server_cobo.la libserverbase.la noinst_LTLIBRARIES = libaudit_server_cobo.la libserverbase.la -AM_CPPFLAGS = -I$(top_srcdir)/comlib -I$(top_srcdir)/cache -I$(top_srcdir)/../cobo -I$(top_srcdir)/../logging -I$(top_srcdir)/../include -I$(top_srcdir)/../utils -DLIBEXECDIR=\"$(pkglibexecdir)\" -LDADD = $(top_builddir)/cache/libldcs_cache.la -lrt +AM_CPPFLAGS = -I$(top_srcdir)/comlib -I$(top_srcdir)/cache -I$(top_srcdir)/../cobo -I$(top_srcdir)/../logging -I$(top_srcdir)/../include -I$(top_srcdir)/../utils -DLIBEXECDIR=\"$(pkglibexecdir)\" -DPROGLIBDIR=\"$(pkglibdir)\" +LDADD = $(top_builddir)/cache/libldcs_cache.la -lrt #AM_LDFLAGS = -all-static -libserverbase_la_SOURCES = ldcs_audit_server_client_cb.c ldcs_audit_server_server_cb.c ldcs_audit_server_process.c ldcs_audit_server_filemngt.c ldcs_audit_server_handlers.c ldcs_audit_server_crash_handler.c ldcs_audit_server_crash_log.c ldcs_elf_read.c ldcs_audit_server_requestors.c ldcs_audit_server_numa.c msgbundle.c parse_mounts.cc cleanup_proc.cc translate_maps.c force_exit.c $(top_srcdir)/../utils/fileutil.c +libserverbase_la_SOURCES = ldcs_audit_server_client_cb.c ldcs_audit_server_server_cb.c ldcs_audit_server_process.c ldcs_audit_server_filemngt.c ldcs_audit_server_handlers.c ldcs_audit_server_crash_handler.c ldcs_audit_server_crash_log.c ldcs_elf_read.c ldcs_audit_server_requestors.c ldcs_audit_server_numa.c msgbundle.c parse_mounts.cc cleanup_proc.cc translate_maps.c force_exit.c filemngt_calc_static_tls.c $(top_srcdir)/../utils/fileutil.c $(top_srcdir)/../utils/static_tls.c libserverbase_la_LIBADD = -lpthread #libaudit_server_msocket_la_SOURCES = ldcs_audit_server_md_msocket.c ldcs_audit_server_md_msocket_util.c ldcs_audit_server_md_msocket_topo.c diff --git a/src/server/auditserver/Makefile.in b/src/server/auditserver/Makefile.in index a3fcbe43..d2e4a314 100644 --- a/src/server/auditserver/Makefile.in +++ b/src/server/auditserver/Makefile.in @@ -127,7 +127,9 @@ am_libserverbase_la_OBJECTS = ldcs_audit_server_client_cb.lo \ ldcs_audit_server_crash_log.lo ldcs_elf_read.lo \ ldcs_audit_server_requestors.lo ldcs_audit_server_numa.lo \ msgbundle.lo parse_mounts.lo cleanup_proc.lo translate_maps.lo \ - force_exit.lo $(top_builddir)/../utils/fileutil.lo + force_exit.lo filemngt_calc_static_tls.lo \ + $(top_builddir)/../utils/fileutil.lo \ + $(top_builddir)/../utils/static_tls.lo libserverbase_la_OBJECTS = $(am_libserverbase_la_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) @@ -145,7 +147,10 @@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/../../scripts/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = $(top_builddir)/../utils/$(DEPDIR)/fileutil.Plo \ - ./$(DEPDIR)/cleanup_proc.Plo ./$(DEPDIR)/force_exit.Plo \ + $(top_builddir)/../utils/$(DEPDIR)/static_tls.Plo \ + ./$(DEPDIR)/cleanup_proc.Plo \ + ./$(DEPDIR)/filemngt_calc_static_tls.Plo \ + ./$(DEPDIR)/force_exit.Plo \ ./$(DEPDIR)/ldcs_audit_server_client_cb.Plo \ ./$(DEPDIR)/ldcs_audit_server_crash_handler.Plo \ ./$(DEPDIR)/ldcs_audit_server_crash_log.Plo \ @@ -380,10 +385,10 @@ top_srcdir = @top_srcdir@ #noinst_LTLIBRARIES = libaudit_server_msocket.la libaudit_server_cobo.la libserverbase.la noinst_LTLIBRARIES = libaudit_server_cobo.la libserverbase.la -AM_CPPFLAGS = -I$(top_srcdir)/comlib -I$(top_srcdir)/cache -I$(top_srcdir)/../cobo -I$(top_srcdir)/../logging -I$(top_srcdir)/../include -I$(top_srcdir)/../utils -DLIBEXECDIR=\"$(pkglibexecdir)\" -LDADD = $(top_builddir)/cache/libldcs_cache.la -lrt +AM_CPPFLAGS = -I$(top_srcdir)/comlib -I$(top_srcdir)/cache -I$(top_srcdir)/../cobo -I$(top_srcdir)/../logging -I$(top_srcdir)/../include -I$(top_srcdir)/../utils -DLIBEXECDIR=\"$(pkglibexecdir)\" -DPROGLIBDIR=\"$(pkglibdir)\" +LDADD = $(top_builddir)/cache/libldcs_cache.la -lrt #AM_LDFLAGS = -all-static -libserverbase_la_SOURCES = ldcs_audit_server_client_cb.c ldcs_audit_server_server_cb.c ldcs_audit_server_process.c ldcs_audit_server_filemngt.c ldcs_audit_server_handlers.c ldcs_audit_server_crash_handler.c ldcs_audit_server_crash_log.c ldcs_elf_read.c ldcs_audit_server_requestors.c ldcs_audit_server_numa.c msgbundle.c parse_mounts.cc cleanup_proc.cc translate_maps.c force_exit.c $(top_srcdir)/../utils/fileutil.c +libserverbase_la_SOURCES = ldcs_audit_server_client_cb.c ldcs_audit_server_server_cb.c ldcs_audit_server_process.c ldcs_audit_server_filemngt.c ldcs_audit_server_handlers.c ldcs_audit_server_crash_handler.c ldcs_audit_server_crash_log.c ldcs_elf_read.c ldcs_audit_server_requestors.c ldcs_audit_server_numa.c msgbundle.c parse_mounts.cc cleanup_proc.cc translate_maps.c force_exit.c filemngt_calc_static_tls.c $(top_srcdir)/../utils/fileutil.c $(top_srcdir)/../utils/static_tls.c libserverbase_la_LIBADD = -lpthread #libaudit_server_msocket_la_SOURCES = ldcs_audit_server_md_msocket.c ldcs_audit_server_md_msocket_util.c ldcs_audit_server_md_msocket_topo.c @@ -448,6 +453,9 @@ $(top_builddir)/../utils/$(DEPDIR)/$(am__dirstamp): $(top_builddir)/../utils/fileutil.lo: \ $(top_builddir)/../utils/$(am__dirstamp) \ $(top_builddir)/../utils/$(DEPDIR)/$(am__dirstamp) +$(top_builddir)/../utils/static_tls.lo: \ + $(top_builddir)/../utils/$(am__dirstamp) \ + $(top_builddir)/../utils/$(DEPDIR)/$(am__dirstamp) libserverbase.la: $(libserverbase_la_OBJECTS) $(libserverbase_la_DEPENDENCIES) $(EXTRA_libserverbase_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libserverbase_la_OBJECTS) $(libserverbase_la_LIBADD) $(LIBS) @@ -461,7 +469,9 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/../utils/$(DEPDIR)/fileutil.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@$(top_builddir)/../utils/$(DEPDIR)/static_tls.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cleanup_proc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filemngt_calc_static_tls.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/force_exit.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldcs_audit_server_client_cb.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldcs_audit_server_crash_handler.Plo@am__quote@ # am--include-marker @@ -667,7 +677,9 @@ clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ distclean: distclean-am -rm -f $(top_builddir)/../utils/$(DEPDIR)/fileutil.Plo + -rm -f $(top_builddir)/../utils/$(DEPDIR)/static_tls.Plo -rm -f ./$(DEPDIR)/cleanup_proc.Plo + -rm -f ./$(DEPDIR)/filemngt_calc_static_tls.Plo -rm -f ./$(DEPDIR)/force_exit.Plo -rm -f ./$(DEPDIR)/ldcs_audit_server_client_cb.Plo -rm -f ./$(DEPDIR)/ldcs_audit_server_crash_handler.Plo @@ -729,7 +741,9 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(top_builddir)/../utils/$(DEPDIR)/fileutil.Plo + -rm -f $(top_builddir)/../utils/$(DEPDIR)/static_tls.Plo -rm -f ./$(DEPDIR)/cleanup_proc.Plo + -rm -f ./$(DEPDIR)/filemngt_calc_static_tls.Plo -rm -f ./$(DEPDIR)/force_exit.Plo -rm -f ./$(DEPDIR)/ldcs_audit_server_client_cb.Plo -rm -f ./$(DEPDIR)/ldcs_audit_server_crash_handler.Plo diff --git a/src/server/auditserver/filemngt_calc_static_tls.c b/src/server/auditserver/filemngt_calc_static_tls.c new file mode 100644 index 00000000..ecca7260 --- /dev/null +++ b/src/server/auditserver/filemngt_calc_static_tls.c @@ -0,0 +1,827 @@ +/* +This file is part of Spindle. For copyright information see the COPYRIGHT +file in the top level directory, or at +https://github.com/hpc/Spindle/blob/master/COPYRIGHT + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License (as published by the Free Software +Foundation) version 2.1 dated February 1999. This program 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 terms +and conditions of the GNU Lesser General Public License for more details. You should +have received a copy of the GNU Lesser General Public License along with this +program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "static_tls.h" +#include "ldcs_api.h" +#include "spindle_debug.h" +#include "client_libraries.h" + +typedef struct library_list_t { + char *path; + char *interp; + ssize_t tls_size; + ssize_t tls_alignment; + struct library_list_t *next; + struct library_list_t *hash_next; +} library_list_t; + +typedef struct executable_list_t { + static_tls_info_t *info; + ssize_t tls_size; + ssize_t tls_alignment; + struct executable_list_t *hash_next; +} executable_list_t; + +#define EXECUTABLE_HASH_SIZE 64 +static executable_list_t *executable_hash_table[EXECUTABLE_HASH_SIZE]; +static executable_list_t *executable_hash_lookup(static_tls_info_t *info); +static executable_list_t *executable_hash_add(static_tls_info_t *info); + +#define LIBRARY_HASH_SIZE 512 +static library_list_t *library_hash_table[LIBRARY_HASH_SIZE]; +static library_list_t *library_hash_lookup(const char *path); +static library_list_t *library_hash_add(const char *path); +static void library_list_clean(library_list_t *l); + +static int static_tls_size_for_dso(const char *path, char *interp, size_t interp_str_size, int *is_script_fd, ssize_t *tls_size_result, ssize_t *tls_alignment_result); +static library_list_t *add_to_filelist(library_list_t **head, char *path); +static ssize_t reliable_read(int fd, void *buffer, size_t size); +static library_list_t *get_libraries(static_tls_info_t *info, const char *ldso); +static int handle_script(static_tls_info_t *info, int fd, ssize_t *tls_size, ssize_t *tls_align); +static void add_tls_sizes(ssize_t *tls_total, ssize_t *max_alignment, ssize_t tls_new, ssize_t tls_align); +static int calc_static_tls_for_audit_client(char *interp, ssize_t *tls_size, ssize_t *tls_alignment); +static int calc_static_tls_for_executable_nocache(static_tls_info_t *info, char *use_interp, ssize_t *tls_size_result_p, ssize_t *tls_alignment_result_p); +static int calc_static_tls_for_executable_w_interp(static_tls_info_t *info, char *interp, ssize_t *tls_size, ssize_t *tls_alignment); + +int static_tls_info_lookup(static_tls_info_t *info, ssize_t *tls_size, ssize_t *tls_alignment) +{ + executable_list_t *e; + e = executable_hash_lookup(info); + if (!e) { + return -1; + } + if (e->tls_size == -1 && e->tls_alignment == -1) + return -1; + if (tls_size) + *tls_size = e->tls_size; + if (tls_alignment) + *tls_alignment = e->tls_alignment; + return 0; +} + +int static_tls_info_add(static_tls_info_t *info, ssize_t tls_size, ssize_t tls_alignment) +{ + executable_list_t *e; + e = executable_hash_add(info); + if (!e) { + err_printf("Error adding static tls info for %s\n", info->executable); + return -1; + } + e->tls_size = tls_size; + e->tls_alignment = tls_alignment; + return 0; +} + +static int calc_static_tls_for_executable_w_interp(static_tls_info_t *info, char *interp, ssize_t *tls_size, ssize_t *tls_alignment) +{ + int result; + ssize_t size_result, align_result; + executable_list_t *e; + result = calc_static_tls_for_executable_nocache(info, interp, &size_result, &align_result); + if (result == -1) { + size_result = -1; + align_result = -1; + } + + e = executable_hash_lookup(info); + if (!e) + e = executable_hash_add(info); + e->tls_size = size_result; + e->tls_alignment = align_result; + + if (tls_size) + *tls_size = size_result; + if (align_result) + *tls_alignment = align_result; + + return result; +} + +int calc_static_tls_for_executable(static_tls_info_t *info, ssize_t *tls_size, ssize_t *tls_alignment) +{ + int result; + executable_list_t *e; + ssize_t size_result, align_result; + result = calc_static_tls_for_executable_nocache(info, NULL, &size_result, &align_result); + if (result == -1) { + size_result = -1; + align_result = -1; + } + + e = executable_hash_lookup(info); + if (!e) + e = executable_hash_add(info); + e->tls_size = size_result; + e->tls_alignment = align_result; + + if (tls_size) + *tls_size = size_result; + if (align_result) + *tls_alignment = align_result; + + return result; +} + +static int calc_static_tls_for_executable_nocache(static_tls_info_t *info, char *use_interp, ssize_t *tls_size_result_p, ssize_t *tls_alignment_result_p) +{ + ssize_t tls_size_exe = 0, tls_size_auditclient = 0, tls_size = 0, tls_size_total = 0; + ssize_t tls_align = 0, tls_align_exe = 0, tls_align_auditclient = 0, max_alignment = 0; + int script_fd = -1, result; + library_list_t *dt_needed_libs, *i; + char fullpath[MAX_PATH_LEN+1], *executable_path; + char interp[MAX_PATH_LEN+1]; + interp[0] = '\0'; + + debug_printf2("Asked to calculate static tls needed for %s with ld_library_path='%s' ; ld_preload='%s' ; cwd='%s' ; path_component='%s'\n", + info->executable, info->ld_library_path, info->ld_preload, info->cwd, info->path_component); + debug_printf2("Using interpreter: %s\n", use_interp ? use_interp : "[DEFAULT]\n"); + + //Add path_component to file path if the executable is found via path search + if (info->path_component && strchr(info->executable, '/') == NULL) { + snprintf(fullpath, sizeof(fullpath)-1, "%s/%s", info->path_component, info->executable); + executable_path = fullpath; + } + else { + executable_path = info->executable; + } + + //Look up TLS size and interpreter for the executable + result = static_tls_size_for_dso(executable_path, interp, sizeof(interp), &script_fd, &tls_size_exe, &tls_align_exe); + if (result == -1) { + err_printf("Could not parse executable %s\n", executable_path); + return -1; + } + if (script_fd != -1) { + //This was a script that started with #! + return handle_script(info, script_fd, tls_size_result_p, tls_alignment_result_p); + } + if (use_interp) { + strncpy(interp, use_interp, sizeof(interp)-1); + interp[sizeof(interp)-1] = '\0'; + } + else if (interp[0] == '\0') { + err_printf("%s was not a dynamic executable\n", info->executable); + return -1; + } + add_tls_sizes(&tls_size_total, &max_alignment, tls_size_exe, tls_align_exe); + + if (!use_interp) { + result = calc_static_tls_for_audit_client(interp, &tls_size_auditclient, &tls_align_auditclient); + if (result == -1) { + err_printf("Could not calculate static TLS needed in audit client\n"); + } + else { + add_tls_sizes(&tls_size_total, &max_alignment, tls_size_auditclient, tls_align_auditclient); + } + } + + //Get the statically-determinable list of libraries this exe depends on + dt_needed_libs = get_libraries(info, interp); + if (!dt_needed_libs) { + debug_printf2("Warning: %s could not parse library list\n", info->executable); + return -1; + } + + for (i = dt_needed_libs; i != NULL; i = i->next) { + result = static_tls_size_for_dso(i->path, NULL, 0, NULL, &tls_size, &tls_align); + if (result == -1) + continue; + add_tls_sizes(&tls_size_total, &max_alignment, tls_size, tls_align); + } + library_list_clean(dt_needed_libs); + debug_printf2("Calculated static tls for %s as %ld/+%ld\n", info->executable, tls_size_total, max_alignment); + *tls_size_result_p = tls_size_total; + *tls_alignment_result_p = max_alignment; + return tls_size_total; +} + +static int handle_script(static_tls_info_t *info, int fd, ssize_t *tls_size, ssize_t *tls_align) +{ + char interp[MAX_PATH_LEN+1]; + char *line = NULL; + size_t linesize = 0, i, j; + ssize_t glresult; + executable_list_t *entry; + static_tls_info_t *interp_info; + int result; + + FILE *f = fdopen(fd, "r"); + if (!f) { + close(fd); + err_printf("Error reopening FILE for %s\n", info->executable); + return -1; + } + + glresult = getline(&line, &linesize, f); + if (glresult == -1) { + err_printf("Error reading line in script for %s\n", info->executable); + fclose(f); + return -1; + } + fclose(f); + + //skip '#!' and then initial spaces + for (i = 0; i < linesize && (line[i] == ' ' || line[i] == '\t'); i++); + for (j = 0; + j < sizeof(interp) && i < linesize && line[i] != ' ' && line[i] != '\t' && line[i] != '\n'; + j++, i++) + { + interp[j] = line[i]; + } + if (j == sizeof(interp)) + j--; + interp[j] = '\0'; + + //We have the hashbang string after the intepreter. Make a new static_tls_info_t for the + // script interpreter and Re-run the whole calculation on that. + interp_info = static_tls_info_dup(info); + free(interp_info->executable); + interp_info->executable = strdup(interp); + + result = static_tls_info_lookup(interp_info, tls_size, tls_align); + if (result != -1) { + static_tls_info_free(interp_info); + free(line); + return result; + } + + result = calc_static_tls_for_executable_nocache(interp_info, NULL, tls_size, tls_align); + + //Associate the TLS size from the interpreter with the script + entry = executable_hash_add(interp_info); + entry->tls_size = *tls_size; + entry->tls_alignment = *tls_align; + + free(line); + return 0; +} + +static int static_tls_size_for_dso(const char *path, char *interp, size_t interp_str_size, int *is_script_fd, ssize_t *tls_size_result, ssize_t *tls_alignment_result) +{ + int fd = -1, i, has_static_tls = 0; + void *buffer = NULL; + char *cbuffer; + ssize_t result; + off_t oresult; + ElfW(Ehdr) *ehdr; + ElfW(Phdr) *phdr, *phdrs; + ElfW(Half) phnum, phentsize; + ElfW(Off) phoff = 0, dynamic_off = 0, interp_off = 0; + ElfW(Xword) dynamic_size = 0, interp_size = 0; + ElfW(Dyn) *dyn = NULL, *end_dyn; + ssize_t tls_size = -1, return_result = -1, tls_align = -1; + library_list_t *lib; + char ldso[MAX_PATH_LEN+1]; + ldso[0] = '\0'; + + debug_printf3("Calculating file-specific static TLS needed for %s\n", path); + //Check cache if library has already been parsed. + lib = library_hash_lookup(path); + if (lib) { + if (interp) { + strncpy(interp, lib->interp, interp_str_size); + } + if (tls_size_result) + *tls_size_result = lib->tls_size; + if (tls_alignment_result) + *tls_alignment_result = lib->tls_alignment; + return 0; + } + + fd = open(path, O_RDONLY); + if (fd == -1 && path[0] == '/') { + err_printf("Could not open '%s'\n", path); + goto done; + } + else if (fd == -1) { + goto done; + } + + buffer = (void *) malloc(sizeof(ElfW(Ehdr))); + cbuffer = (char *) buffer; + + //First check the initial two characters for script hashbang '#!' + result = reliable_read(fd, buffer, 2); + if (result < 2) { + err_printf("Not an executable or script %s\n", path); + goto done; + } + else if (cbuffer[0] == '#' && cbuffer[1] == '!') { + *is_script_fd = fd; + free(buffer); + return 0; + } + else if (cbuffer[0] == ELFMAG0 && cbuffer[1] == ELFMAG1) { + //Fall through to the below DSO handling + } + else { + err_printf("Not an executable or script %s\n", path); + goto done; + } + + //Read an elf header (minus the two bytes we already read) + result = reliable_read(fd, cbuffer+2, sizeof(ElfW(Ehdr))-2); + if (result == -1) { + err_printf("Could not read elf eheader %s\n", path); + goto done; + } + if (result != sizeof(ElfW(Ehdr))-2) { + err_printf("Not an executable or script %s\n", path); + return -1; + } + + ehdr = (ElfW(Ehdr) *) buffer; + if (ehdr->e_ident[0] != ELFMAG0 || ehdr->e_ident[1] != ELFMAG1 || + ehdr->e_ident[2] != ELFMAG2 || ehdr->e_ident[3] != ELFMAG3) { + err_printf("Is not an elf file or script %s\n", path); + goto done; + } + + phnum = ehdr->e_phnum; + phentsize = ehdr->e_phentsize; + phoff = ehdr->e_phoff; + + free(buffer); + + //Using info from the elf header, seek to and read the program headers. + buffer = malloc(phentsize * phnum); + oresult = lseek(fd, phoff, SEEK_SET); + if (result == -1) { + err_printf("Could not seek to program headers %s\n", path); + goto done; + } + result = reliable_read(fd, buffer, phentsize * phnum); + if (result == -1) { + err_printf("Could not read program header %s\n", path); + goto done; + } + + //Iterate through program headers for necessary info (TLS size, + // where's the interpreter string, where's the dynamic section. + tls_size = tls_align = 0; + phdrs = (ElfW(Phdr) *) buffer; + for (i = 0; i < phnum; i++) { + phdr = phdrs + i; + if (phdr->p_type == PT_TLS) { + tls_size = phdr->p_memsz; + tls_align = phdr->p_align; + } + if (phdr->p_type == PT_DYNAMIC) { + dynamic_off = phdr->p_offset; + dynamic_size = phdr->p_filesz; + } + if (phdr->p_type == PT_INTERP) { + interp_off = phdr->p_offset; + interp_size = phdr->p_filesz; + } + } + free(buffer); + buffer = NULL; + + if (!dynamic_off && !dynamic_size) { + debug_printf3("Is a static binary: %s\n", path); + goto done; + } + + //Read the interpreter string. + if (interp_off && interp_size) { + oresult = lseek(fd, interp_off, SEEK_SET); + if (oresult == -1) { + err_printf("Could not seek to interpreter for %s\n", path); + goto done; + } + + if (interp_size >= sizeof(ldso)) + interp_size = sizeof(ldso) - 1; + result = reliable_read(fd, ldso, interp_size); + if (result == -1) { + err_printf("Could not read interpreter for %s\n", path); + goto done; + } + ldso[interp_size] = '\0'; + } + + //Read the dynamic section. + buffer = malloc(dynamic_size); + + oresult = lseek(fd, dynamic_off, SEEK_SET); + if (oresult == -1) { + err_printf("Could not seek to dynamic section for %s\n", path); + goto done; + } + + result = reliable_read(fd, buffer, dynamic_size); + if (result == -1) { + err_printf("Could not read dynamic section for %s\n", path); + goto done; + } + + //Look through the dynamic section for the DT_FLAGS and if DT_STATIC_TLS + // is set in it. + end_dyn = (ElfW(Dyn) *) (((unsigned char *) buffer) + dynamic_size); + dyn = (ElfW(Dyn) *) buffer; + for (dyn = (ElfW(Dyn) *) buffer; (dyn->d_tag != DT_NULL) && (dyn < end_dyn); dyn++) { + if (dyn->d_tag == DT_FLAGS) { + has_static_tls = (dyn->d_un.d_val & DF_STATIC_TLS) ? 1 : 0; + break; + } + } + + (void) has_static_tls; + //if (!has_static_tls) + //tls_size = 0; + + if (tls_size_result) + *tls_size_result = tls_size; + if (tls_alignment_result) + *tls_alignment_result = tls_align; + return_result = 0; + + done: + lib = library_hash_add(path); + lib->tls_size = return_result != -1 ? tls_size : -1; + lib->tls_alignment = return_result != -1 ? tls_align : -1; + lib->interp = ldso[0] ? strdup(ldso) : ""; + if (interp) { + strncpy(interp, ldso, interp_size); + } + debug_printf2("Calculated file-specific static TLS for %s as %ld/+%ld\n", path, tls_size, tls_align); + + if (buffer) + free(buffer); + if (fd != -1) + close(fd); + return return_result; +} + +static library_list_t *add_to_filelist(library_list_t **head, char *path) +{ + library_list_t *newfile; + + newfile = (library_list_t *) malloc(sizeof(library_list_t)); + newfile->path = strdup(path); + newfile->interp = NULL; + newfile->tls_size = 0; + newfile->next = *head; + newfile->hash_next = NULL; + *head = newfile; + + return newfile; +} + +#define PRD 0 +#define PWR 1 +static library_list_t *get_libraries(static_tls_info_t *info, const char *ldso) +{ + int pipe_fd[2]; + int result, status, i; + ssize_t sresult; + const char* args[4]; + char *line = NULL, *executable, *new_executable; + size_t line_size = 0, exe_str_size; + pid_t pid; + FILE *f = NULL; + library_list_t *filelist = NULL; + + args[0] = ldso; + args[1] = "--list"; + args[2] = info->executable; + args[3] = NULL; + pipe_fd[0] = pipe_fd[1] = -1; + + result = pipe(pipe_fd); + if (result == -1) { + err_printf("Error creating pipe\n"); + goto done; + } + + if (spindle_debug_prints > 2) { + debug_printf3("Getting static tls library list with "); + for (i = 0; args[i]; i++) { + bare_printf3("%s ", args[i]); + } + bare_printf3("\n"); + } + pid = fork(); + if (pid == -1) { + err_printf("Error forking new process\n"); + goto done; + } + if (pid == 0) { + close(pipe_fd[PRD]); + executable = (char *) args[2]; + if (info->path_component && executable[0] != '/') { + exe_str_size = strlen(executable) + strlen(info->path_component) + 2; + new_executable = (char *) malloc(exe_str_size); + snprintf(new_executable, exe_str_size, "%s/%s", info->path_component, executable); + args[2] = new_executable; + } + if (info->ld_library_path) + setenv("LD_LIBRARY_PATH", info->ld_library_path, 1); + else + unsetenv("LD_LIBRARY_PATH"); + if (info->ld_preload) + setenv("LD_PRELOAD", info->ld_preload, 1); + else + unsetenv("LD_PRELOAD"); + if (info->cwd) + chdir(info->cwd); + dup2(pipe_fd[PWR], 1); + dup2(pipe_fd[PWR], 2); + execv(args[0], (char * const*) args); + err_printf("Error execing ld.so %s\n", ldso); + exit(-1); + } + close(pipe_fd[PWR]); + pipe_fd[PWR] = -1; + result = waitpid(pid, &status, 0); + if (result == -1) { + err_printf("Error during waitpid on %s --list %s: %s\n", + ldso, info->executable, strerror(errno)); + goto done; + } + if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { + err_printf("App exited with error on %d %s\n", + (int) WEXITSTATUS(status), ldso); + goto done; + } + if (WIFSIGNALED(status)) { + err_printf("App exited with signal %d on %s\n", + (int) WTERMSIG(status), ldso); + goto done; + } + if (!WIFEXITED(status)) { + err_printf("App did not exit via status %d on %s\n", + (int) status, ldso); + goto done; + } + + f = fdopen(pipe_fd[PRD], "r"); + if (!f) { + err_printf("Could not convert pipe fd to stream\n"); + goto done; + } + + for (;;) { + char *arrow, *paren, *start, *end; + sresult = getline(&line, &line_size, f); + if (sresult == -1) + break; + start = line; + //skip whitespace and blank lines + while ((*start == '\t' || *start == ' ') && (*start != '\0')) + start++; + if (*start == '\0') + continue; + arrow = strstr(line, " => "); + if (arrow) { + start = arrow + 4; + if (!*start) { + err_printf("parse error at arrow line %s\n", line); + continue; + } + } + paren = strrchr(start, '('); + end = paren ? paren-1 : line+strlen(line)-1; + while ((*end == '\t' || *end == ' ') && (end != start)) end--; + end++; + *end = '\0'; + + add_to_filelist(&filelist, start); + }; + + done: + if (f) { + fclose(f); + } + else if (pipe_fd[PRD] != -1) { + close(pipe_fd[PRD]); + } + if (pipe_fd[PWR] != -1) { + close(pipe_fd[PRD]); + } + if (line) { + free(line); + } + + return filelist; +} + +static unsigned long hash_func(static_tls_info_t *info) +{ + unsigned long hash = 5381; + int c; + char *s; + + if (info->executable) { + s = info->executable; + while ((c = *s++)) + hash = ((hash << 5) + hash) + c; + } + if (info->ld_library_path) { + s = info->ld_library_path; + while ((c = *s++)) + hash = ((hash << 5) + hash) + c; + } + if (info->ld_preload) { + s = info->ld_preload; + while ((c = *s++)) + hash = ((hash << 5) + hash) + c; + } + if (info->path_component) { + s = info->path_component; + while ((c = *s++)) + hash = ((hash << 5) + hash) + c; + } + if (info->cwd) { + s = info->cwd; + while ((c = *s++)) + hash = ((hash << 5) + hash) + c; + } + return hash; +} + +static unsigned long str_hash_func(const char *s) +{ + unsigned long hash = 5381; + int c; + while ((c = *s++)) + hash = ((hash << 5) + hash) + c; + return hash; +} + +static executable_list_t *executable_hash_lookup(static_tls_info_t *info) +{ + unsigned long key; + executable_list_t *i; + + key = hash_func(info) % EXECUTABLE_HASH_SIZE; + for (i = executable_hash_table[key]; i != NULL; i = i->hash_next) { + if (static_tls_info_equal(i->info, info)) + return i; + } + return NULL; +} + +static executable_list_t *executable_hash_add(static_tls_info_t *info) +{ + unsigned long key; + executable_list_t *newh; + + key = hash_func(info) % EXECUTABLE_HASH_SIZE; + newh = (executable_list_t *) malloc(sizeof(executable_list_t)); + newh->info = static_tls_info_dup(info); + newh->hash_next = executable_hash_table[key]; + executable_hash_table[key] = newh; + + return newh; +} + +static library_list_t *library_hash_lookup(const char *path) +{ + unsigned long key; + library_list_t *i; + + key = str_hash_func(path) % LIBRARY_HASH_SIZE; + for (i = library_hash_table[key]; i != NULL; i = i->hash_next) { + if (strcmp(path, i->path) == 0) { + return i; + } + } + return NULL; +} + +static library_list_t *library_hash_add(const char *path) +{ + unsigned long key; + library_list_t *newh; + + key = str_hash_func(path) % LIBRARY_HASH_SIZE; + newh = (library_list_t *) malloc(sizeof(library_list_t)); + newh->path = strdup(path); + newh->hash_next = library_hash_table[key]; + library_hash_table[key] = newh; + + return newh; +} + +static ssize_t reliable_read(int fd, void *buffer, size_t size) +{ + ssize_t bytes_read = 0, result; + int retry_count = 10, error; + + do { + result = read(fd, ((unsigned char *) buffer) + bytes_read, size - bytes_read); + if (result == -1) { + if (errno == EINTR) { + continue; + } + else if (errno == EAGAIN && retry_count-- >= 0) { + continue; + } + error = errno; + err_printf("read returned error %d\n", error); + errno = error; + return -1; + } + else if (result == 0) { + return bytes_read; + } + bytes_read += result; + } while (bytes_read < size); + + return bytes_read; +} + +static void add_tls_sizes(ssize_t *tls_total, ssize_t *max_alignment, ssize_t tls_new, ssize_t tls_align) +{ + *tls_total += tls_new; + if (tls_align > *max_alignment) + *max_alignment = tls_align; + //We don't know the order the linker will use for libraries, so we can't calculate an accurate alignment. + //Instead we'll add the alignment amount to the allocation size an an upper-bound. + *tls_total += tls_align; +} + +static void library_list_clean(library_list_t *l) +{ + library_list_t *j, *next; + next = NULL; + for (j = l; j != NULL; j = next) { + next = j->next; + free(j->path); + if (j->interp && j->interp[0]) + free(j->interp); + free(j); + } +} + +static int calc_static_tls_for_audit_client(char *interp, ssize_t *tls_size, ssize_t *tls_alignment) +{ + static_tls_info_t info; + ssize_t audit_tls_size = 0, audit_tls_alignment = 0; + ssize_t subaudit_tls_size = 0, subaudit_tls_alignment = 0; + int audit_result = -1, subaudit_result = -1; + static ssize_t cached_audit_client_tls_size = -2; + static ssize_t cached_audit_client_tls_align; + + if (cached_audit_client_tls_size != -2) { + *tls_size = cached_audit_client_tls_size; + *tls_alignment = cached_audit_client_tls_align; + return 0; + } + + if (default_audit_libstr && *default_audit_libstr) { + info.executable = default_audit_libstr; + info.ld_library_path = NULL; + info.ld_preload = NULL; + info.cwd = NULL; + info.path_component = NULL; + audit_result = calc_static_tls_for_executable_w_interp(&info, interp, &audit_tls_size, &audit_tls_alignment); + } + + if (default_subaudit_libstr && *default_subaudit_libstr) { + info.executable = default_subaudit_libstr; + info.ld_library_path = NULL; + info.ld_preload = NULL; + info.cwd = NULL; + info.path_component = NULL; + subaudit_result = calc_static_tls_for_executable_w_interp(&info, interp, &subaudit_tls_size, &subaudit_tls_alignment); + } + + if (audit_result == -1 && subaudit_result == -1) { + *tls_size = cached_audit_client_tls_size = -1; + *tls_alignment = cached_audit_client_tls_align = -1; + return -1; + } + + cached_audit_client_tls_size = audit_tls_size > subaudit_tls_size ? audit_tls_size : subaudit_tls_size; + cached_audit_client_tls_align = audit_tls_alignment > subaudit_tls_alignment ? audit_tls_alignment : subaudit_tls_alignment; + + return 0; +} diff --git a/src/server/auditserver/filemngt_calc_static_tls.h b/src/server/auditserver/filemngt_calc_static_tls.h new file mode 100644 index 00000000..ba0ee8f1 --- /dev/null +++ b/src/server/auditserver/filemngt_calc_static_tls.h @@ -0,0 +1,28 @@ +/* +This file is part of Spindle. For copyright information see the COPYRIGHT +file in the top level directory, or at +https://github.com/hpc/Spindle/blob/master/COPYRIGHT + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License (as published by the Free Software +Foundation) version 2.1 dated February 1999. This program 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 terms +and conditions of the GNU Lesser General Public License for more details. You should +have received a copy of the GNU Lesser General Public License along with this +program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#if !defined(_FILEMNGT_CALC_STATIC_TLS_H_) +#define _FILEMNGT_CALC_STATIC_TLS_H_ + +#include "static_tls.h" + +int calc_static_tls_for_executable(static_tls_info_t *info, ssize_t *tls_size, ssize_t *tls_alignment); +int static_tls_info_lookup(static_tls_info_t *info, ssize_t *tls_size, ssize_t *tls_alignment); +int static_tls_info_add(static_tls_info_t *info, ssize_t tls_size, ssize_t tls_alignment); + +#endif diff --git a/src/server/auditserver/ldcs_audit_server_client_cb.c b/src/server/auditserver/ldcs_audit_server_client_cb.c index 7ba8df7b..34ac0c19 100644 --- a/src/server/auditserver/ldcs_audit_server_client_cb.c +++ b/src/server/auditserver/ldcs_audit_server_client_cb.c @@ -35,10 +35,6 @@ extern int ldcs_socket_id_to_nc(int id, int fd, ldcs_process_data_t *process_dat int _ldcs_client_dump_info ( ldcs_process_data_t *ldcs_process_data ); -/* some message container */ -static char buffer_in[MAX_PATH_LEN]; -/* static char buffer_out[MAX_PATH_LEN]; */ - int _ldcs_client_CB ( int fd, int id, void *data ) { int rc=0; ldcs_process_data_t *ldcs_process_data = ( ldcs_process_data_t *) data ; @@ -61,10 +57,10 @@ int _ldcs_client_CB ( int fd, int id, void *data ) { debug_printf3("Receiving message from client %d on fd %d\n", nc, fd); in_msg.header.type=LDCS_MSG_UNKNOWN; in_msg.header.len=0; - in_msg.data=buffer_in; + in_msg.data = NULL; /* get message from client */ - ldcs_recv_msg_static(connid, &in_msg, LDCS_READ_BLOCK); + ldcs_recv_msg_dynamic(connid, &in_msg, LDCS_READ_BLOCK); /* printf("SERVER[%03d]: received message on connection connid=%d\n", nc, connid); */ debug_printf3("received message on connection nc=%d connid=%d\n", nc, connid); diff --git a/src/server/auditserver/ldcs_audit_server_filemngt.c b/src/server/auditserver/ldcs_audit_server_filemngt.c index 1d0f410b..eaf3995c 100644 --- a/src/server/auditserver/ldcs_audit_server_filemngt.c +++ b/src/server/auditserver/ldcs_audit_server_filemngt.c @@ -40,6 +40,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "ccwarns.h" #include "cleanup_proc.h" #include "fileutil.h" +#include "config.h" #if !defined(LIBEXECDIR) #error LIBEXECDIR must be defined diff --git a/src/server/auditserver/ldcs_audit_server_handlers.c b/src/server/auditserver/ldcs_audit_server_handlers.c index 21741048..c7e73e6b 100644 --- a/src/server/auditserver/ldcs_audit_server_handlers.c +++ b/src/server/auditserver/ldcs_audit_server_handlers.c @@ -43,6 +43,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "ccwarns.h" #include "parse_mounts.h" #include "exitnote.h" +#include "static_tls.h" +#include "filemngt_calc_static_tls.h" /** * This file contains the "brains" of Spindle. It's public interface, @@ -183,6 +185,15 @@ static int handle_client_dirlists_req(ldcs_process_data_t *procdata, int nc); static int handle_close_client_query(ldcs_process_data_t *procdata, int nc); static int handle_alive_msg(ldcs_process_data_t *procdata, ldcs_message_t *msg); static int handle_chosen_cachepath_request(ldcs_process_data_t *procdata, int nc); +static int handle_client_static_tls_req(ldcs_process_data_t *procdata, int nc, ldcs_message_t *msg); +static int handle_tls_request(ldcs_process_data_t *procdata, static_tls_info_t *tlsinfo, node_peer_t from); +static int handle_calculate_total_static_tls_needed(static_tls_info_t *tlsinfo, ssize_t *tls_size, ssize_t *tls_alignment); +static int handle_tls_send_request(ldcs_process_data_t *procdata, static_tls_info_t *tlsinfo, char *tlskey, node_peer_t from); +static int handle_tls_send_results(ldcs_process_data_t *procdata, static_tls_info_t *tlsinfo, char *tlskey, ldcs_message_t *msg); +static int handle_tls_process_result(ldcs_process_data_t *procdata, static_tls_info_t *tlsinfo, char *tlskey, ssize_t tls_size, ssize_t tls_alignment); +static int handle_send_client_static_tls_resp(ldcs_process_data_t *procdata, int nc, ssize_t tls_size, ssize_t tls_alignment); +static int handle_static_tls_req(ldcs_process_data_t *procdata, ldcs_message_t *msg, node_peer_t from); +static int handle_static_tls_resp(ldcs_process_data_t *procdata, ldcs_message_t *msg); extern void getValidCachePathByIndex( uint64_t validBitIdx, char **realizedCachePath, char **parsedCachePath, char **symbolicCachePath ); /** @@ -1907,6 +1918,8 @@ int handle_client_message(ldcs_process_data_t *procdata, int nc, ldcs_message_t return handle_client_end(procdata, nc); case LDCS_MSG_CHOSEN_CACHEPATH_REQUEST: return handle_chosen_cachepath_request(procdata, nc); + case LDCS_MSG_CLIENT_STATICTLS: + return handle_client_static_tls_req(procdata, nc, msg); default: err_printf("Received unexpected message from client %d: %d\n", nc, (int) msg->header.type); assert(0); @@ -2008,6 +2021,10 @@ int handle_server_message(ldcs_process_data_t *procdata, node_peer_t peer, ldcs_ return handle_crash_report_recv(procdata, peer, msg); case LDCS_MSG_CRASH_RESPONSE: return handle_crash_response_recv(procdata, peer, msg); + case LDCS_MSG_STATICTLS_RESP: + return handle_static_tls_resp(procdata, msg); + case LDCS_MSG_STATICTLS: + return handle_static_tls_req(procdata, msg, peer); case LDCS_MSG_CRASH_LOG: return handle_crash_log_recv(procdata, peer, msg); default: @@ -3092,6 +3109,381 @@ static int handle_alive_msg(ldcs_process_data_t *procdata, ldcs_message_t *msg) return 0; } +/** + * A client has requested a static TLS size calculation about an executable and its execution environment (LD_LIBRARY_PATH, + * LD_PRELOAD, CWD). + **/ +static int handle_client_static_tls_req(ldcs_process_data_t *procdata, int nc, ldcs_message_t *msg) +{ + int result; + static_tls_info_t *tlsinfo = NULL; + ldcs_client_t *client; + + result = static_tls_info_decode(msg->data, msg->header.len, &tlsinfo); + if (result == -1) { + if (tlsinfo) + static_tls_info_free(tlsinfo); + err_printf("Failed to decode TLS info packet\n"); + return -1; + } + + debug_printf("Client requested tls info for %s\n", tlsinfo->executable); + debug_printf2("Client tls execution environment is ld_library_path='%s' ; ld_preload='%s' ; cwd='%s'\n", + tlsinfo->ld_library_path, tlsinfo->ld_preload, tlsinfo->cwd); + + client = procdata->client_table + nc; + assert(!client->tls_info); + client->tls_info = tlsinfo; + + return handle_tls_request(procdata, tlsinfo, NODE_PEER_CLIENT); +} + +/** + * We have a request for a static TLS calculation, either from the network or a client. Handle + * that request by either reading the info from cache, calculating it from disk, or requesting + * the info from up the network. + **/ +static int handle_tls_request(ldcs_process_data_t *procdata, static_tls_info_t *tlsinfo, node_peer_t from) +{ + char *tls_key = NULL; + ssize_t tls_size, tls_align; + int tls_result, result; + debug_printf2("Processing needing to request TLS info for %s\n", tlsinfo->executable); + tls_key = static_tls_info_to_idstr(tlsinfo); + if (!tls_key) { + err_printf("Error calculating TLS key for executable %s\n", tlsinfo->executable); + tls_result = -1; + goto done; + } + + result = static_tls_info_lookup(tlsinfo, &tls_size, &tls_align); + if (result != -1) { + debug_printf2("TLS info for %s was cached.\n", tlsinfo->executable); + if (from != NODE_PEER_CLIENT) { + debug_printf3("Adding pending_tls_request for '%s' from child %p\n", tls_key, from); + add_requestor(procdata->pending_tls_requests, tls_key, from); + } + tls_result = handle_tls_process_result(procdata, tlsinfo, tls_key, tls_size, tls_align); + goto done; + } + if (ldcs_audit_server_md_is_responsible(procdata, tls_key)) { + debug_printf2("Am responsible for TLS read of %s. Running calculation\n", tlsinfo->executable); + if (from != NODE_PEER_CLIENT) { + debug_printf3("Adding pending_tls_request for '%s' from child %p\n", tls_key, from); + add_requestor(procdata->pending_tls_requests, tls_key, from); + } + result = handle_calculate_total_static_tls_needed(tlsinfo, &tls_size, &tls_align); + if (result == -1) { + debug_printf("WARNING Failure calculating TLS size. Moving forward with TLS of 0\n"); + tls_size = 0; + tls_align = 0; + } + tls_result = handle_tls_process_result(procdata, tlsinfo, tls_key, tls_size, tls_align); + goto done; + } + + debug_printf2("Requesting TLS calculation from network\n"); + result = handle_tls_send_request(procdata, tlsinfo, tls_key, from); + if (result == -1) { + err_printf("Could not send request for TLS\n"); + tls_result = -1; + goto done; + } + + tls_result = 0; +done: + if (tls_key) + free(tls_key); + return tls_result; +} + +/** + * Go to disk and calculate the static TLS of an executable and its execution environment. + **/ +static int handle_calculate_total_static_tls_needed(static_tls_info_t *tlsinfo, ssize_t *tls_size, ssize_t *tls_alignment) +{ + ssize_t tls_result, tls_align; + int result; + + result = calc_static_tls_for_executable(tlsinfo, &tls_result, &tls_align); + if (result == -1) { + debug_printf2("TLS could not be calculated for %s. Setting to 0.\n", tlsinfo->executable); + *tls_size = 0; + *tls_alignment = 0; + return 0; + } + *tls_size = tls_result; + *tls_alignment = tls_align; + + return 0; +} + +/** +* Send a request for a static TLS calculation up the network. +**/ +static int handle_tls_send_request(ldcs_process_data_t *procdata, static_tls_info_t *tlsinfo, char *tlskey, node_peer_t from) { + char *buffer = NULL; + int buffer_size, result; + ldcs_message_t msg; + + if (been_requested(procdata->pending_tls_requests, tlskey)) { + debug_printf2("TLS info for %s has already been requested. Not resending request\n", tlsinfo->executable); + if (from != NODE_PEER_CLIENT) { + debug_printf3("Adding pending_tls_request for '%s' from child %p to existing request\n", tlskey, from); + add_requestor(procdata->pending_tls_requests, tlskey, from); + } + return 0; + } + debug_printf("Sending request for TLS info of %s to parent\n", tlsinfo->executable); + + if (from != NODE_PEER_CLIENT) { + debug_printf3("Adding pending_tls_request for '%s' from child %p\n", tlskey, from); + add_requestor(procdata->pending_tls_requests, tlskey, from); + } + + buffer_size = static_tls_info_encode_size_needed2(tlsinfo) + 1; + buffer = (char *) malloc(buffer_size); + + result = static_tls_info_encode2(tlsinfo, buffer, buffer_size, &buffer_size); + if (result == -1) { + free(buffer); + err_printf("Error encoding TLS request packet for %s\n", tlsinfo->executable); + return -1; + } + + msg.header.type = LDCS_MSG_STATICTLS; + msg.header.len = buffer_size; + msg.data = buffer; + + result = spindle_forward_query(procdata, &msg); + if (result == -1) { + err_printf("Could not forward request for TLS of %s\n", tlsinfo->executable); + free(buffer); + return -1; + } + + free(buffer); + return 0; +} + +/** + * Send the results of a TLS calculation to children nodes on the network. + **/ +static int handle_tls_send_results(ldcs_process_data_t *procdata, static_tls_info_t *tlsinfo, char *tlskey, ldcs_message_t *msg) +{ + int result, global_result = 0; + node_peer_t *nodes = NULL; + int nodes_size, i; + + debug_printf2("Checking if tlskey '%s' for NODE_PEER_ALL is in completed_tls_requests\n", tlskey); + if (peer_requested(procdata->completed_tls_requests, tlskey, NODE_PEER_ALL)) { + debug_printf2("Not sending TLS message for %s, because it's been broadcast\n", tlsinfo->executable); + return 0; + } + + if (procdata->dist_model == LDCS_PUSH) { + debug_printf2("Pushing TLS message to all children\n"); + result = spindle_broadcast_noncontig(procdata, msg, NULL, 0); + if (result == -1) { + err_printf("Could not broadcast TLS message\n"); + global_result = -1; + } + debug_printf2("Adding tlskey '%s' for NODE_PEER_ALL to completed_tls_requests\n", tlskey); + add_requestor(procdata->completed_tls_requests, tlskey, NODE_PEER_ALL); + } + else if (procdata->dist_model == LDCS_PULL) { + debug_printf2("Sending TLS message to select children\n"); + result = get_requestors(procdata->pending_tls_requests, tlskey, &nodes, &nodes_size); + if (result == -1) { + return 0; + } + debug_printf2("Sending TLS message %s to %d nodes who requested it\n", tlskey, nodes_size); + for (i = 0; i < nodes_size; i++) { + if (nodes[i] == NODE_PEER_CLIENT || nodes[i] == NODE_PEER_NULL) + continue; + if (peer_requested(procdata->completed_tls_requests, tlskey, nodes[i])) { + debug_printf2("Not sending message %s to child, because it was already sent\n", tlskey); + continue; + } + result = spindle_send_noncontig(procdata, msg, nodes[i], NULL, 0); + if (result == -1) + global_result = -1; + else + add_requestor(procdata->completed_tls_requests, tlskey, nodes[i]); + } + } + clear_requestor(procdata->pending_tls_requests, tlskey); + + return global_result; +} + +/** + * We have the result of a TLS calculation (whether by calculating it ourselves or from the network). Give that + * result to any clients and the and any network children who requested it. + */ +static int handle_tls_process_result(ldcs_process_data_t *procdata, static_tls_info_t *tlsinfo, char *tlskey, ssize_t tls_size, ssize_t tls_alignment) +{ + int result; + ldcs_message_t msg; + char *buffer = NULL; + int buffer_size = 0, global_error = 0, i; + int *clients_sent_to = NULL; + int clients_sent_to_count = 0; + + debug_printf2("At top of tls_process_result with tlskey='%s'\n", tlskey); + //Send to network children + buffer_size = static_tls_info_encode_size_needed2(tlsinfo); + buffer = (char *) malloc(buffer_size + 2*sizeof(ssize_t)); + *((ssize_t *) buffer) = tls_size; + *((ssize_t *) (buffer + sizeof(ssize_t))) = tls_alignment; + result = static_tls_info_encode2(tlsinfo, buffer+2*sizeof(ssize_t), buffer_size, &buffer_size); + if (result == -1) { + err_printf("Error encoding TLS info for %s into result packet\n", tlsinfo->executable); + free(buffer); + return -1; + } + buffer_size += 2*sizeof(ssize_t); + + msg.header.type = LDCS_MSG_STATICTLS_RESP; + msg.header.len = buffer_size; + msg.data = buffer; + + result = handle_tls_send_results(procdata, tlsinfo, tlskey, &msg); + if (result == -1) { + err_printf("Could not send TLS message to children\n"); + global_error = -1; + } + free(buffer); + buffer = NULL; + + clients_sent_to = (int *) malloc(sizeof(int) * procdata->client_table_used); + + //Send to clients + for (i = 0; i < procdata->client_table_used; i++) { + ldcs_client_t *client= procdata->client_table + i; + if (client->state == LDCS_CLIENT_STATUS_FREE || client->state == LDCS_CLIENT_STATUS_ACTIVE_PSEUDO) + continue; + if (!client->tls_info) + continue; + + if (client->tls_info == tlsinfo || static_tls_info_equal(client->tls_info, tlsinfo)) { + result = handle_send_client_static_tls_resp(procdata, i, tls_size, tls_alignment); + if (result == -1) { + err_printf("Error sending TLS info to client\n"); + global_error = -1; + } + clients_sent_to[clients_sent_to_count++] = i; + } + } + + //Free TLS info for any client we sent to + for (i = 0; i < clients_sent_to_count; i++) { + ldcs_client_t *client = procdata->client_table + clients_sent_to[i]; + static_tls_info_free(client->tls_info); + client->tls_info = NULL; + } + free(clients_sent_to); + + return global_error; +} + + +/** + * Send a TLS calculation result to a client. +**/ +static int handle_send_client_static_tls_resp(ldcs_process_data_t *procdata, int nc, ssize_t tls_size, ssize_t tls_alignment) +{ + ldcs_message_t msg; + ldcs_client_t *client; + int result; + ssize_t tls_data[2]; + + client = procdata->client_table + nc; + + tls_data[0] = tls_size; + tls_data[1] = tls_alignment; + + msg.header.type = LDCS_MSG_CLIENT_STATICTLS_RESP; + msg.header.len = 2*sizeof(ssize_t); + msg.data = (char *) tls_data; + + result = ldcs_send_msg(client->connid, &msg); + procdata->server_stat.clientmsg.cnt++; + procdata->server_stat.clientmsg.time += (ldcs_get_time() - client->query_arrival_time); + handle_close_client_query(procdata, nc); + + return result; +} + +/** + * We have a request to handle a TLS calculation from a child. + **/ +static int handle_static_tls_req(ldcs_process_data_t *procdata, ldcs_message_t *msg, node_peer_t from) +{ + int result; + static_tls_info_t *info = NULL; + + result = static_tls_info_decode(msg->data, msg->header.len, &info); + if (result == -1) { + err_printf("Could not decode TLS request message\n"); + return -1; + } + debug_printf("Received TLS calculation request from network for %s\n", info->executable); + debug_printf2("Execution environment for tls calculation is LD_LIBRARY_PATH=%s ; LD_PRELOAD=%s ; CWD=%s\n", + info->ld_library_path, info->ld_preload, info->cwd); + + result = handle_tls_request(procdata, info, from); + if (result == -1) { + static_tls_info_free(info); + err_printf("Could not handle TLS request message\n"); + return -1; + } + + static_tls_info_free(info); + return 0; +} + +/** + * We have a TLS calculation response from the network. + */ +static int handle_static_tls_resp(ldcs_process_data_t *procdata, ldcs_message_t *msg) +{ + int result; + static_tls_info_t *tlsinfo; + ssize_t tls_size, tls_alignment; + char *buffer; + char *tlskey; + + tls_size = *((size_t *) msg->data); + tls_alignment = *((size_t *) (msg->data + sizeof(ssize_t))); + buffer = msg->data + 2*sizeof(ssize_t); + result = static_tls_info_decode(buffer, msg->header.len - 2*sizeof(ssize_t), &tlsinfo); + if (result == -1) { + err_printf("Error decoding TLS result packet\n"); + return -1; + } + + debug_printf("Received TLS calculation response for %s of size %ld and alignment %ld\n", tlsinfo->executable, tls_size, tls_alignment); + static_tls_info_add(tlsinfo, tls_size, tls_alignment); + + debug_printf2("Execution environment for tls response is LD_LIBRARY_PATH=%s ; LD_PRELOAD=%s ; CWD=%s\n", + tlsinfo->ld_library_path, tlsinfo->ld_preload, tlsinfo->cwd); + + tlskey = static_tls_info_to_idstr(tlsinfo); + + result = handle_tls_process_result(procdata, tlsinfo, tlskey, tls_size, tls_alignment); + if (result == -1) { + err_printf("Could not handle processing TLS response\n"); + static_tls_info_free(tlsinfo); + free(tlskey); + return -1; + } + + static_tls_info_free(tlsinfo); + free(tlskey); + return 0; +} + /** * If all of our clients are exited, and all of our child servers have * sent an exit_ready, then send an exit_ready to our parent diff --git a/src/server/auditserver/ldcs_audit_server_process.c b/src/server/auditserver/ldcs_audit_server_process.c index dae89e26..246d931c 100644 --- a/src/server/auditserver/ldcs_audit_server_process.c +++ b/src/server/auditserver/ldcs_audit_server_process.c @@ -168,6 +168,8 @@ int ldcs_audit_server_process(spindle_args_t *args) ldcs_process_data.completed_lstat_requests = new_requestor_list(); ldcs_process_data.pending_ldso_requests = new_requestor_list(); ldcs_process_data.completed_ldso_requests = new_requestor_list(); + ldcs_process_data.pending_tls_requests = new_requestor_list(); + ldcs_process_data.completed_tls_requests = new_requestor_list(); ldcs_process_data.handling_bundle = 0; ldcs_process_data.exit_note_done = 0; ldcs_process_data.exit_on_client_close = 0; diff --git a/src/server/auditserver/ldcs_audit_server_process.h b/src/server/auditserver/ldcs_audit_server_process.h index d798a5dd..f6a22222 100644 --- a/src/server/auditserver/ldcs_audit_server_process.h +++ b/src/server/auditserver/ldcs_audit_server_process.h @@ -25,6 +25,7 @@ extern "C" { #include "spindle_launch.h" #include "stat_cache.h" #include "force_exit.h" +#include "static_tls.h" typedef void* requestor_list_t; @@ -94,6 +95,7 @@ struct ldcs_client_struct int is_loader; int is_dso; int numa_node; + static_tls_info_t *tls_info; char query_filename[MAX_PATH_LEN+1]; /* hash 1st key */ char query_dirname[MAX_PATH_LEN+1]; /* hast 2nd key */ char query_globalpath[MAX_PATH_LEN+2]; /* path to file in global fs (dirname+filename) */ @@ -199,6 +201,8 @@ struct ldcs_process_data_struct requestor_list_t completed_lstat_requests; requestor_list_t pending_ldso_requests; requestor_list_t completed_ldso_requests; + requestor_list_t pending_tls_requests; + requestor_list_t completed_tls_requests; crash_site_entry_t *crash_sites; int crash_sites_count; diff --git a/src/server/auditserver/ldcs_audit_server_server_cb.c b/src/server/auditserver/ldcs_audit_server_server_cb.c index b1d7f4fe..547cf883 100644 --- a/src/server/auditserver/ldcs_audit_server_server_cb.c +++ b/src/server/auditserver/ldcs_audit_server_server_cb.c @@ -65,6 +65,7 @@ int _ldcs_server_CB ( int infd, int serverid, void *data ) { ldcs_process_data->client_table[nc].lrank = ldcs_process_data->client_counter; ldcs_process_data->client_table[nc].query_localpath = NULL; ldcs_process_data->client_table[nc].query_is_numa_replicated = 0; + ldcs_process_data->client_table[nc].tls_info = NULL; ldcs_process_data->client_table[nc].crash_exe = NULL; ldcs_process_data->client_table[nc].crash_corepath = NULL; ldcs_process_data->client_table_used++; diff --git a/src/server/comlib/Makefile.am b/src/server/comlib/Makefile.am index 2731931f..b5d8f388 100644 --- a/src/server/comlib/Makefile.am +++ b/src/server/comlib/Makefile.am @@ -1,6 +1,6 @@ noinst_LTLIBRARIES = -AM_CPPFLAGS = -I$(top_srcdir)/../logging -I$(top_srcdir)/../include -I$(top_srcdir)/auditserver -I$(top_srcdir)/cache +AM_CPPFLAGS = -I$(top_srcdir)/../logging -I$(top_srcdir)/../include -I$(top_srcdir)/auditserver -I$(top_srcdir)/cache -I$(top_srcdir)/../utils BASE_SRCS = ldcs_api_util.c ldcs_api_listen.c ldcs_api_wrapper.c diff --git a/src/server/comlib/Makefile.in b/src/server/comlib/Makefile.in index b3c072ff..7a2217a6 100644 --- a/src/server/comlib/Makefile.in +++ b/src/server/comlib/Makefile.in @@ -383,7 +383,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ noinst_LTLIBRARIES = libserver_pipe.la libserver_socket.la \ libserver_biter.la $(am__append_1) -AM_CPPFLAGS = -I$(top_srcdir)/../logging -I$(top_srcdir)/../include -I$(top_srcdir)/auditserver -I$(top_srcdir)/cache +AM_CPPFLAGS = -I$(top_srcdir)/../logging -I$(top_srcdir)/../include -I$(top_srcdir)/auditserver -I$(top_srcdir)/cache -I$(top_srcdir)/../utils BASE_SRCS = ldcs_api_util.c ldcs_api_listen.c ldcs_api_wrapper.c libserver_pipe_la_CPPFLAGS = $(AM_CPPFLAGS) -Dcomm=pipe libserver_pipe_la_SOURCES = ldcs_api_pipe.c ldcs_api_pipe_notify.c $(BASE_SRCS) diff --git a/src/server/comlib/ldcs_api_biter.c b/src/server/comlib/ldcs_api_biter.c index 6520be4d..5ce44c9a 100644 --- a/src/server/comlib/ldcs_api_biter.c +++ b/src/server/comlib/ldcs_api_biter.c @@ -290,3 +290,9 @@ int ldcs_recv_msg_static_biter(int connid, ldcs_message_t *msg, ldcs_read_block_ return 0; } + +int ldcs_recv_msg_dynamic_biter(int connid, ldcs_message_t *msg, ldcs_read_block_t block) +{ + assert(0); + return -1; +} diff --git a/src/server/comlib/ldcs_api_pipe.c b/src/server/comlib/ldcs_api_pipe.c index 6b49f296..ca233788 100644 --- a/src/server/comlib/ldcs_api_pipe.c +++ b/src/server/comlib/ldcs_api_pipe.c @@ -325,11 +325,17 @@ ldcs_message_t * ldcs_recv_msg_pipe(int fd, ldcs_read_block_t block ) { return(msg); } -int ldcs_recv_msg_static_pipe(int fd, ldcs_message_t *msg, ldcs_read_block_t block) { +//1MB +#define MAX_MSG_SIZE 1048576 + +int ldcs_recv_msg_pipe_internal(int fd, ldcs_message_t *msg, ldcs_read_block_t block, int alloc_buffer) { size_t n; int rc=0; msg->header.type=LDCS_MSG_UNKNOWN; msg->header.len=0; + static char *buffer = NULL; + static size_t buffer_size = 4096; + if ((fd<0) || (fd>fdlist_pipe_size) ) _error("wrong fd"); n = _ldcs_read_pipe(fdlist_pipe[fd].in_fd,&msg->header,sizeof(msg->header), block); @@ -342,6 +348,19 @@ int ldcs_recv_msg_static_pipe(int fd, ldcs_message_t *msg, ldcs_read_block_t blo return(rc); } + if (msg->header.len > MAX_MSG_SIZE) { + err_printf("Message size %lu was greater than MAX_MSG_SIZE. Likely malformed.\n", msg->header.len); + return -1; + } + if (alloc_buffer) { + if (!buffer || msg->header.len > buffer_size) { + buffer_size = msg->header.len > buffer_size ? msg->header.len : buffer_size; + buffer = (char *) realloc(buffer, buffer_size); + } + memset(buffer, 0, buffer_size); + msg->data = buffer; + } + if(msg->header.len>0) { n = _ldcs_read_pipe(fdlist_pipe[fd].in_fd,msg->data,msg->header.len, LDCS_READ_BLOCK); if (n == 0) @@ -365,6 +384,14 @@ int ldcs_recv_msg_static_pipe(int fd, ldcs_message_t *msg, ldcs_read_block_t blo return(rc); } +int ldcs_recv_msg_static_pipe(int fd, ldcs_message_t *msg, ldcs_read_block_t block) { + return ldcs_recv_msg_pipe_internal(fd, msg, block, 0); +} + +int ldcs_recv_msg_dynamic_pipe(int fd, ldcs_message_t *msg, ldcs_read_block_t block) { + return ldcs_recv_msg_pipe_internal(fd, msg, block, 1); +} + size_t _ldcs_read_pipe(int fd, void *data, int bytes, ldcs_read_block_t block ) { int left; diff --git a/src/server/comlib/ldcs_api_socket.c b/src/server/comlib/ldcs_api_socket.c index 33b8d761..c0e44717 100644 --- a/src/server/comlib/ldcs_api_socket.c +++ b/src/server/comlib/ldcs_api_socket.c @@ -23,6 +23,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include +#include #include "ldcs_api.h" #include "spindle_launch.h" @@ -335,6 +336,12 @@ int ldcs_recv_msg_static_socket(int fd, ldcs_message_t *msg, ldcs_read_block_t return(0); } +int ldcs_recv_msg_dynamic_socket(int fd, ldcs_message_t *msg, ldcs_read_block_t block) +{ + assert(0); + return -1; +} + int ldcs_get_aux_fd_socket() { return -1; diff --git a/src/server/comlib/ldcs_api_util.c b/src/server/comlib/ldcs_api_util.c index fb023d61..345a8d67 100644 --- a/src/server/comlib/ldcs_api_util.c +++ b/src/server/comlib/ldcs_api_util.c @@ -95,6 +95,10 @@ char* _message_type_to_str (ldcs_message_ids_t type) { STR_CASE(LDCS_MSG_CHOSEN_CACHEPATH); STR_CASE(LDCS_MSG_CRASH_REPORT); STR_CASE(LDCS_MSG_CRASH_RESPONSE); + STR_CASE(LDCS_MSG_CLIENT_STATICTLS); + STR_CASE(LDCS_MSG_CLIENT_STATICTLS_RESP); + STR_CASE(LDCS_MSG_STATICTLS); + STR_CASE(LDCS_MSG_STATICTLS_RESP); STR_CASE(LDCS_MSG_CRASH_LOG); STR_CASE(LDCS_MSG_CRASH_EXE); STR_CASE(LDCS_MSG_CRASH_COREPATH); diff --git a/src/server/comlib/ldcs_api_wrapper.c b/src/server/comlib/ldcs_api_wrapper.c index 4b5a66a1..ed3bef6f 100644 --- a/src/server/comlib/ldcs_api_wrapper.c +++ b/src/server/comlib/ldcs_api_wrapper.c @@ -46,6 +46,7 @@ extern int RENAME(ldcs_send_msg) (int fd, ldcs_message_t *msg); extern int RENAME(ldcs_get_fd)(int fd); extern int RENAME(ldcs_get_aux_fd)(); extern int RENAME(ldcs_recv_msg_static)(int connid, ldcs_message_t *msg, ldcs_read_block_t block); +extern int RENAME(ldcs_recv_msg_dynamic)(int connid, ldcs_message_t *msg, ldcs_read_block_t block); extern int RENAME(ldcs_socket_id_to_nc)(int id, int fd, ldcs_process_data_t *process_data); int ldcs_create_server(char* location, number_t number) @@ -88,6 +89,11 @@ int ldcs_recv_msg_static(int connid, ldcs_message_t *msg, ldcs_read_block_t bloc return RENAME(ldcs_recv_msg_static)(connid, msg, block); } +int ldcs_recv_msg_dynamic(int connid, ldcs_message_t *msg, ldcs_read_block_t block) +{ + return RENAME(ldcs_recv_msg_dynamic)(connid, msg, block); +} + int ldcs_get_aux_fd() { return RENAME(ldcs_get_aux_fd)(); diff --git a/src/server/config.h.in b/src/server/config.h.in index 87e6242d..9f5f6389 100644 --- a/src/server/config.h.in +++ b/src/server/config.h.in @@ -171,6 +171,9 @@ /* The default port for Spindle */ #undef SPINDLE_PORT +/* Defined if GLIBC has static TLS allocation bug */ +#undef STATIC_TLS_ALLOC_BUG + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS diff --git a/src/server/configure b/src/server/configure index e6e08c67..713b1158 100755 --- a/src/server/configure +++ b/src/server/configure @@ -841,6 +841,7 @@ with_localstorage with_cachepaths with_cachepath with_commpaths +with_commpath with_default_local_prefix with_testrm with_rm @@ -1573,12 +1574,13 @@ Optional Packages: Number of TCP/IP ports to scan for Spindle server communication --with-localstorage=DIR (obsolete) - Use --with-cachepaths and --with-commpath instead. + Use --with-cachepaths and --with-commpaths instead. --with-cachepaths=DIR Colon-separated list of potential back-end cache directories -, - --with-compaths=DIR Colon-separated list of candidate paths for back-end + --with-cachepath=DIR Synonym for --with-cachepaths + --with-commpaths=DIR Colon-separated list of candidate paths for back-end communication and housekeeping + --with-commpath=DIR Synonym for --with-commpaths --with-default-local-prefix=DIRS Colon-seperated list of directories that Spindle will not cache files out of @@ -16447,7 +16449,7 @@ fi # Check whether --with-localstorage was given. if test "${with_localstorage+set}" = set; then : - withval=$with_localstorage; as_fn_error $? "requested obsolete option --with-localstorage. Use --with-cachepaths and --with-commpath instead." "$LINENO" 5 + withval=$with_localstorage; as_fn_error $? "requested obsolete option --with-localstorage. Use --with-cachepaths and --with-commpaths instead." "$LINENO" 5 fi @@ -16461,7 +16463,7 @@ fi # Check whether --with-cachepath was given. if test "${with_cachepath+set}" = set; then : - withval=$with_cachepath; as_fn_error $? "use --with-cachepaths=DIRS (plural) instead of --with-cachepath=DIR to specify one or more cache paths" "$LINENO" 5 + withval=$with_cachepath; CACHEPATHS=${withval} fi @@ -16473,6 +16475,12 @@ else fi +# Check whether --with-commpath was given. +if test "${with_commpath+set}" = set; then : + withval=$with_commpath; COMMPATHS=${withval} +fi + + # Check whether --with-default-local-prefix was given. if test "${with_default_local_prefix+set}" = set; then : withval=$with_default_local_prefix; SPINDLE_LOCAL_PREFIX=${withval} @@ -16620,13 +16628,13 @@ _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for locale tls fault glibc bug" >&5 $as_echo_n "checking for locale tls fault glibc bug... " >&6; } if ${SPINDLE_SOURCE_ROOT}/scripts/locale_tls_fault/tls_locale_fault.sh ${SPINDLE_SOURCE_ROOT}/scripts/locale_tls_fault ${SPINDLE_BUILD_ROOT}/locale_tls_fault $CC; then - LOCALE_FAULT_BUG=0 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -else LOCALE_FAULT_BUG=1 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } +else + LOCALE_FAULT_BUG=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi cat >>confdefs.h <<_ACEOF @@ -16634,6 +16642,22 @@ cat >>confdefs.h <<_ACEOF _ACEOF +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for static tls glibc bug" >&5 +$as_echo_n "checking for static tls glibc bug... " >&6; } +if ${SPINDLE_SOURCE_ROOT}/scripts/static_tls_test/run_test.sh ${CC} "${CFLAGS} -g" ${SPINDLE_SOURCE_ROOT} ${SPINDLE_BUILD_ROOT}; then + STATIC_TLS_BUG=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + STATIC_TLS_BUG=1 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi + +cat >>confdefs.h <<_ACEOF +#define STATIC_TLS_ALLOC_BUG $STATIC_TLS_BUG +_ACEOF + #OS Detection # Check whether --enable-bluegene was given. diff --git a/src/utils/client_libraries.h b/src/utils/client_libraries.h new file mode 100644 index 00000000..2ff5be30 --- /dev/null +++ b/src/utils/client_libraries.h @@ -0,0 +1,47 @@ +/* +This file is part of Spindle. For copyright information see the COPYRIGHT +file in the top level directory, or at +https://github.com/hpc/Spindle/blob/master/COPYRIGHT + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License (as published by the Free Software +Foundation) version 2.1 dated February 1999. This program 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 terms +and conditions of the GNU Lesser General Public License for more details. You should +have received a copy of the GNU Lesser General Public License along with this +program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#if !defined(CLIENT_LIBRARIES_H_) +#define CLIENT_LIBRARIES_H_ + +#include "config.h" + +#if !defined(PROGLIBDIR) +#error Expected to be built with proglib defined +#endif + +char libstr_socket_subaudit[] = PROGLIBDIR "/libspindle_subaudit_socket.so"; +char libstr_pipe_subaudit[] = PROGLIBDIR "/libspindle_subaudit_pipe.so"; +char libstr_biter_subaudit[] = PROGLIBDIR "/libspindle_subaudit_biter.so"; + +char libstr_socket_audit[] = PROGLIBDIR "/libspindle_audit_socket.so"; +char libstr_pipe_audit[] = PROGLIBDIR "/libspindle_audit_pipe.so"; +char libstr_biter_audit[] = PROGLIBDIR "/libspindle_audit_biter.so"; + +#if defined(COMM_SOCKET) +static char *default_audit_libstr = libstr_socket_audit; +static char *default_subaudit_libstr = libstr_socket_subaudit; +#elif defined(COMM_PIPES) +static char *default_audit_libstr = libstr_pipe_audit; +static char *default_subaudit_libstr = libstr_pipe_subaudit; +#elif defined(COMM_BITER) +static char *default_audit_libstr = libstr_biter_audit; +static char *default_subaudit_libstr = libstr_biter_subaudit; +#else +#error Unknown connection type +#endif + +#endif \ No newline at end of file diff --git a/src/utils/static_tls.c b/src/utils/static_tls.c new file mode 100644 index 00000000..a150e93e --- /dev/null +++ b/src/utils/static_tls.c @@ -0,0 +1,207 @@ +/* +This file is part of Spindle. For copyright information see the COPYRIGHT +file in the top level directory, or at +https://github.com/hpc/Spindle/blob/master/COPYRIGHT + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License (as published by the Free Software +Foundation) version 2.1 dated February 1999. This program 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 terms +and conditions of the GNU Lesser General Public License for more details. You should +have received a copy of the GNU Lesser General Public License along with this +program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include "static_tls.h" +#include "spindle_debug.h" + +static int strcmp_w_null(const char *a, const char *b) +{ + return strcmp(a ? a : "", b ? b : ""); +} +int static_tls_info_equal(const static_tls_info_t *info_a, const static_tls_info_t *info_b) +{ + return (strcmp_w_null(info_a->executable, info_b->executable) == 0) && + (strcmp_w_null(info_a->ld_library_path, info_b->ld_library_path) == 0) && + (strcmp_w_null(info_a->ld_preload, info_b->ld_preload) == 0) && + (strcmp_w_null(info_a->cwd, info_b->cwd) == 0) && + (strcmp_w_null(info_a->path_component, info_b->path_component) == 0) ? 1 : 0; +} + +int static_tls_info_encode_size_needed(const char *executable, const char *ld_library_path, const char *ld_preload, const char *cwd, const char *path_component) +{ + return (int) (sizeof(int)*5 + + (executable ? strlen(executable) + 1 : 0) + + (ld_library_path ? strlen(ld_library_path) + 1 : 0) + + (ld_preload ? strlen(ld_preload) + 1 : 0) + + (cwd ? strlen(cwd) + 1 : 0) + + (path_component ? strlen(path_component) + 1 : 0) + 2); +} + +int static_tls_info_encode_size_needed2(const static_tls_info_t *info) +{ + return static_tls_info_encode_size_needed(info->executable, info->ld_library_path, info->ld_preload, info->cwd, info->path_component); +} + +int static_tls_info_encode(const char *executable, const char *ld_library_path, const char *ld_preload, const char *cwd, const char *path_component, char *buffer, int buffer_in_size, int *buffer_out_size) +{ + int executable_len, library_len, preload_len, cwd_len, path_component_len; + int len, cur = 0; + + executable_len = executable ? strlen(executable) + 1 : 0; + library_len = ld_library_path ? strlen(ld_library_path) + 1 : 0; + preload_len = ld_preload ? strlen(ld_preload) + 1 : 0; + cwd_len = cwd ? strlen(cwd) + 1 : 0; + path_component_len = path_component ? strlen(path_component) + 1 : 0; + + len = sizeof(int)*5 + executable_len + library_len + preload_len + cwd_len + path_component_len + 1; + debug_printf3("buffer_in_size = %d; len = %d\n", buffer_in_size, len); + assert(len <= buffer_in_size); + + memcpy(buffer+cur, &executable_len, sizeof(executable_len)); + cur += sizeof(executable_len); + + memcpy(buffer+cur, &library_len, sizeof(library_len)); + cur += sizeof(library_len); + + memcpy(buffer+cur, &preload_len, sizeof(preload_len)); + cur += sizeof(preload_len); + + memcpy(buffer+cur, &cwd_len, sizeof(cwd_len)); + cur += sizeof(cwd_len); + + memcpy(buffer+cur, &path_component_len, sizeof(path_component_len)); + cur += sizeof(path_component_len); + + if (executable) { + memcpy(buffer+cur, executable, executable_len); + cur += executable_len; + } + + if (ld_library_path) { + memcpy(buffer+cur, ld_library_path, library_len); + cur += library_len; + } + if (ld_preload) { + memcpy(buffer+cur, ld_preload, preload_len); + cur += preload_len; + } + if (cwd) { + memcpy(buffer+cur, cwd, cwd_len); + cur += cwd_len; + } + if (path_component) { + memcpy(buffer+cur, path_component, path_component_len); + cur += path_component_len; + } + buffer[cur++] = '\0'; + + debug_printf3("Encoded static tls info for %s into size %d\n", executable, cur); + *buffer_out_size = cur; + return 0; +} + +int static_tls_info_encode2(const static_tls_info_t *info, char *buffer, int buffer_in_size, int *buffer_out_size) +{ + return static_tls_info_encode(info->executable, info->ld_library_path, info->ld_preload, info->cwd, info->path_component, buffer, buffer_in_size, buffer_out_size); +} + +int static_tls_info_decode(char *buffer, int buffer_len, static_tls_info_t **info) +{ + int executable_len, library_len, preload_len, cwd_len, path_component_len; + int cur = 0; + static_tls_info_t *newinfo; + + debug_printf3("Asked to decode static tls info of size %d\n", buffer_len); + + *info = NULL; + if (buffer_len < sizeof(int) * 5) + return -1; + + memcpy(&executable_len, buffer + cur, sizeof(executable_len)); + cur += sizeof(executable_len); + memcpy(&library_len, buffer + cur, sizeof(library_len)); + cur += sizeof(library_len); + memcpy(&preload_len, buffer + cur, sizeof(preload_len)); + cur += sizeof(preload_len); + memcpy(&cwd_len, buffer + cur, sizeof(cwd_len)); + cur += sizeof(cwd_len); + memcpy(&path_component_len, buffer + cur, sizeof(path_component_len)); + cur += sizeof(path_component_len); + + if (buffer_len < cur + executable_len + library_len + preload_len + cwd_len + path_component_len) + return -1; + + newinfo = (static_tls_info_t *) malloc(sizeof(static_tls_info_t)); + + newinfo->executable = executable_len ? strdup(buffer + cur) : NULL; + cur += executable_len; + newinfo->ld_library_path = library_len ? strdup(buffer + cur) : NULL; + cur += library_len; + newinfo->ld_preload = preload_len ? strdup(buffer + cur) : NULL; + cur += preload_len; + newinfo->cwd = cwd_len ? strdup(buffer + cur) : NULL; + cur += cwd_len; + newinfo->path_component = path_component_len ? strdup(buffer + cur) : NULL; + cur += path_component_len; + + *info = newinfo; + debug_printf3("buffer_in_size = %d\n", buffer_len); + return 0; +} + +void static_tls_info_free(static_tls_info_t *info) { + if (info->executable) + free(info->executable); + if (info->ld_library_path) + free(info->ld_library_path); + if (info->ld_preload) + free(info->ld_preload); + if (info->cwd) + free(info->cwd); + if (info->path_component) + free(info->path_component); + free(info); +} + +char *static_tls_info_to_idstr(static_tls_info_t *info) +{ + char *s, *executable, *ld_library, *ld_preload, *cwd, *path_component; + size_t size, executable_size, ld_library_size, ld_preload_size, cwd_size, path_component_size; + + executable = info->executable ? info->executable : "NONE"; + ld_library = info->ld_library_path ? info->ld_library_path : "NONE"; + ld_preload = info->ld_preload ? info->ld_preload : "NONE"; + cwd = info->cwd ? info->cwd : "NONE"; + path_component = info->path_component ? info->path_component : "NONE"; + + executable_size = info->executable ? strlen(info->executable) : 0; + ld_library_size = info->ld_library_path ? strlen(info->ld_library_path) : 0; + ld_preload_size = info->ld_preload ? strlen(info->ld_preload) : 0; + cwd_size = info->cwd ? strlen(info->cwd) : 0; + path_component_size = info->path_component ? strlen(info->path_component) : 0; + + size = strlen(executable) + strlen(ld_library) + strlen(ld_preload) + strlen(cwd) + strlen(path_component) + 10 + 16*5; + s = (char *) malloc(size); + s[0] = '\0'; + snprintf(s, size, "%s|%s|%s|%s|%s|%lu|%lu|%lu|%lu|%lu", executable, ld_library, ld_preload, cwd, path_component, executable_size, ld_library_size, ld_preload_size, cwd_size, path_component_size); + return s; +} + +static_tls_info_t *static_tls_info_dup(static_tls_info_t *info) +{ + static_tls_info_t *newinfo; + newinfo = (static_tls_info_t *) malloc(sizeof(static_tls_info_t)); + newinfo->executable = info->executable ? strdup(info->executable) : NULL; + newinfo->ld_library_path = info->ld_library_path ? strdup(info->ld_library_path) : NULL; + newinfo->ld_preload = info->ld_preload ? strdup(info->ld_preload) : NULL; + newinfo->cwd = info->cwd ? strdup(info->cwd) : NULL; + newinfo->path_component = info->path_component ? strdup(info->path_component) : NULL; + return newinfo; +} diff --git a/src/utils/static_tls.h b/src/utils/static_tls.h new file mode 100644 index 00000000..dcc20cc3 --- /dev/null +++ b/src/utils/static_tls.h @@ -0,0 +1,38 @@ +/* +This file is part of Spindle. For copyright information see the COPYRIGHT +file in the top level directory, or at +https://github.com/hpc/Spindle/blob/master/COPYRIGHT + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License (as published by the Free Software +Foundation) version 2.1 dated February 1999. This program 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 terms +and conditions of the GNU Lesser General Public License for more details. You should +have received a copy of the GNU Lesser General Public License along with this +program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#if !defined(STATIC_TLS_H_) +#define STATIC_TLS_H_ + +typedef struct { + char *executable; + char *ld_library_path; + char *ld_preload; + char *cwd; + char *path_component; +} static_tls_info_t; + +int static_tls_info_equal(const static_tls_info_t *info_a, const static_tls_info_t *info_b); +int static_tls_info_encode_size_needed(const char *executable, const char *ld_library_path, const char *ld_preload, const char *cwd, const char *path_component); +int static_tls_info_encode_size_needed2(const static_tls_info_t *info); +int static_tls_info_encode(const char *executable, const char *ld_library_path, const char *ld_preload, const char *cwd, const char *path_component, char *buffer, int buffer_in_size, int *buffer_out_size); +int static_tls_info_encode2(const static_tls_info_t *info, char *buffer, int buffer_in_size, int *buffer_out_size); +int static_tls_info_decode(char *buffer, int buffer_len, static_tls_info_t **info); +static_tls_info_t *static_tls_info_dup(static_tls_info_t *info); +void static_tls_info_free(static_tls_info_t *info); +char *static_tls_info_to_idstr(static_tls_info_t *info); + +#endif \ No newline at end of file diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am index 1ce88385..19a04129 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 +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 BUILT_SOURCES += crash_test crash_test_fixedaddr crash_test_pie libcrashfuncs.so libcrashctor.so libcrashfixed.so run_crash_tests.sh @@ -28,11 +28,11 @@ test_driver_libsLDFLAGS = -Wl,-E -L$(top_builddir)/testsuite $(MPI_CLDFLAGS) -L$ REGLIB_SRC = $(srcdir)/registerlib.c LD_FUNCDICT = -L$(top_builddir)/testsuite -lfuncdict -test_driver: $(test_driverSOURCES) $(REGLIB_SRC) libtestoutput.so libfuncdict.so - $(AM_V_CCLD) $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(MPICC) -o $@ $(test_driverSOURCES) $(REGLIB_SRC) -DSO_NAME=$@ $(test_driverCFLAGS) $(test_driverLDFLAGS) $(test_driverLDADD) +test_driver: $(test_driverSOURCES) $(REGLIB_SRC) libtestoutput.so libfuncdict.so libbigtls1048576.so libbigtls204800.so libbigtls1024.so + $(AM_V_CCLD) $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(MPICC) -o $@ $(test_driverSOURCES) $(REGLIB_SRC) -DSO_NAME=$@ $(test_driverCFLAGS) $(test_driverLDFLAGS) $(test_driverLDADD) -lbigtls1048576 -lbigtls204800 -lbigtls1024 -test_driver_libs: $(test_driverSOURCES) $(REGLIB_SRC) libtestoutput.so libfuncdict.so libtest10.so libtest11.so libtest12.so libtest13.so libtest14.so libtest15.so libtest16.so libtest17.so libtest18.so libtest19.so libtest20.so libtest100.so libtest500.so libtest1000.so libtest2000.so libtest4000.so libtest6000.so libtest8000.so libtest10000.so 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 libdepA.so libcxxexceptA.so libdepB.so libdepC.so libcxxexceptB.so origin_dir/liboriginlib.so - $(AM_V_CCLD) $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(MPICC) -o $@ $(test_driver_libsSOURCES) $(REGLIB_SRC) -DSO_NAME=$@ -DUSE_NEEDED $(test_driver_libsCFLAGS) $(test_driver_libsLDFLAGS) $(test_driver_libsLDADD) +test_driver_libs: $(test_driverSOURCES) $(REGLIB_SRC) libtestoutput.so libfuncdict.so libtest10.so libtest11.so libtest12.so libtest13.so libtest14.so libtest15.so libtest16.so libtest17.so libtest18.so libtest19.so libtest20.so libtest100.so libtest500.so libtest1000.so libtest2000.so libtest4000.so libtest6000.so libtest8000.so libtest10000.so 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 libdepA.so libcxxexceptA.so libdepB.so libdepC.so libcxxexceptB.so origin_dir/liboriginlib.so libbigtls1048576.so libbigtls204800.so libbigtls1024.so + $(AM_V_CCLD) $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(MPICC) -o $@ $(test_driver_libsSOURCES) $(REGLIB_SRC) -DSO_NAME=$@ -DUSE_NEEDED $(test_driver_libsCFLAGS) $(test_driver_libsLDFLAGS) $(test_driver_libsLDADD) -lbigtls1048576 -lbigtls204800 -lbigtls1024 libtest10.c: libgenerator $(AM_V_GEN)./libgenerator libtest10.c 10 t10 @@ -385,6 +385,15 @@ badlink.py: alias/aliastest.py: $(AM_V_GEN)mkdir -p alias/real1/real2 ; echo "fail" > alias/aliastest.py ; echo "pass" > alias/real1/aliastest.py ; ln -s real1/real2 alias/lnk +libbigtls1024.so: bigtls.c + $(AM_V_CCLD)$(CC) -o $@ -fPIC -shared $(CFLAGS) -Wall $< -DTLS_SIZE=1024 + +libbigtls204800.so: bigtls.c + $(AM_V_CCLD)$(CC) -o $@ -fPIC -shared $(CFLAGS) -Wall $< -DTLS_SIZE=204800 + +libbigtls1048576.so: bigtls.c + $(AM_V_CCLD)$(CC) -o $@ -fPIC -shared $(CFLAGS) -Wall $< -DTLS_SIZE=1048576 + spindle_deactivated.sh: spindle_deactivated_template.sh $(AM_V_GEN)cp $< $@; chmod 700 $@ @@ -470,4 +479,5 @@ exec_shell_expected_output: $(srcdir)/exec_shell_expected_output_template exec_shell: $(srcdir)/exec_shell.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 +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 + diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index f3402c0a..6b53101c 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -359,6 +359,7 @@ BUILT_SOURCES = libtest10.so libtest11.so libtest12.so libtest13.so \ 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 \ crash_test crash_test_fixedaddr crash_test_pie \ libcrashfuncs.so libcrashctor.so libcrashfixed.so \ run_crash_tests.sh @@ -406,7 +407,7 @@ CLEANFILES = libtest10.c libtest11.c libtest12.c libtest13.c \ 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 + run_crash_tests.sh libbigtls204800.so libbigtls1048576.so all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am @@ -712,11 +713,11 @@ uninstall-am: .PRECIOUS: Makefile -test_driver: $(test_driverSOURCES) $(REGLIB_SRC) libtestoutput.so libfuncdict.so - $(AM_V_CCLD) $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(MPICC) -o $@ $(test_driverSOURCES) $(REGLIB_SRC) -DSO_NAME=$@ $(test_driverCFLAGS) $(test_driverLDFLAGS) $(test_driverLDADD) +test_driver: $(test_driverSOURCES) $(REGLIB_SRC) libtestoutput.so libfuncdict.so libbigtls1048576.so libbigtls204800.so libbigtls1024.so + $(AM_V_CCLD) $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(MPICC) -o $@ $(test_driverSOURCES) $(REGLIB_SRC) -DSO_NAME=$@ $(test_driverCFLAGS) $(test_driverLDFLAGS) $(test_driverLDADD) -lbigtls1048576 -lbigtls204800 -lbigtls1024 -test_driver_libs: $(test_driverSOURCES) $(REGLIB_SRC) libtestoutput.so libfuncdict.so libtest10.so libtest11.so libtest12.so libtest13.so libtest14.so libtest15.so libtest16.so libtest17.so libtest18.so libtest19.so libtest20.so libtest100.so libtest500.so libtest1000.so libtest2000.so libtest4000.so libtest6000.so libtest8000.so libtest10000.so 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 libdepA.so libcxxexceptA.so libdepB.so libdepC.so libcxxexceptB.so origin_dir/liboriginlib.so - $(AM_V_CCLD) $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(MPICC) -o $@ $(test_driver_libsSOURCES) $(REGLIB_SRC) -DSO_NAME=$@ -DUSE_NEEDED $(test_driver_libsCFLAGS) $(test_driver_libsLDFLAGS) $(test_driver_libsLDADD) +test_driver_libs: $(test_driverSOURCES) $(REGLIB_SRC) libtestoutput.so libfuncdict.so libtest10.so libtest11.so libtest12.so libtest13.so libtest14.so libtest15.so libtest16.so libtest17.so libtest18.so libtest19.so libtest20.so libtest100.so libtest500.so libtest1000.so libtest2000.so libtest4000.so libtest6000.so libtest8000.so libtest10000.so 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 libdepA.so libcxxexceptA.so libdepB.so libdepC.so libcxxexceptB.so origin_dir/liboriginlib.so libbigtls1048576.so libbigtls204800.so libbigtls1024.so + $(AM_V_CCLD) $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(MPICC) -o $@ $(test_driver_libsSOURCES) $(REGLIB_SRC) -DSO_NAME=$@ -DUSE_NEEDED $(test_driver_libsCFLAGS) $(test_driver_libsLDFLAGS) $(test_driver_libsLDADD) -lbigtls1048576 -lbigtls204800 -lbigtls1024 libtest10.c: libgenerator $(AM_V_GEN)./libgenerator libtest10.c 10 t10 @@ -1069,6 +1070,15 @@ badlink.py: alias/aliastest.py: $(AM_V_GEN)mkdir -p alias/real1/real2 ; echo "fail" > alias/aliastest.py ; echo "pass" > alias/real1/aliastest.py ; ln -s real1/real2 alias/lnk +libbigtls1024.so: bigtls.c + $(AM_V_CCLD)$(CC) -o $@ -fPIC -shared $(CFLAGS) -Wall $< -DTLS_SIZE=1024 + +libbigtls204800.so: bigtls.c + $(AM_V_CCLD)$(CC) -o $@ -fPIC -shared $(CFLAGS) -Wall $< -DTLS_SIZE=204800 + +libbigtls1048576.so: bigtls.c + $(AM_V_CCLD)$(CC) -o $@ -fPIC -shared $(CFLAGS) -Wall $< -DTLS_SIZE=1048576 + spindle_deactivated.sh: spindle_deactivated_template.sh $(AM_V_GEN)cp $< $@; chmod 700 $@ diff --git a/testsuite/bigtls.c b/testsuite/bigtls.c new file mode 100644 index 00000000..a8bb08e0 --- /dev/null +++ b/testsuite/bigtls.c @@ -0,0 +1,36 @@ +/* +This file is part of Spindle. For copyright information see the COPYRIGHT +file in the top level directory, or at +https://github.com/hpc/Spindle/blob/master/COPYRIGHT + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License (as published by the Free Software +Foundation) version 2.1 dated February 1999. This program 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 terms +and conditions of the GNU Lesser General Public License for more details. You should +have received a copy of the GNU Lesser General Public License along with this +program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#if !defined(TLS_SIZE) +#error TLS_SIZE must be defined +#endif + +#define CAT2(X, Y) X ## Y +#define CAT(X, Y) CAT2(X, Y) +#define TLSNAME CAT(bigtls_, TLS_SIZE) +#define FNAME CAT(tlscalc_, TLS_SIZE) + +__thread unsigned char TLSNAME[TLS_SIZE] __attribute__((tls_model("initial-exec"), aligned(16))); + +unsigned char *FNAME() +{ + int i; + for (i = 0; i < TLS_SIZE; i++) { + TLSNAME[i] = (i % 256); + } + return TLSNAME; +} +