From a8c0fd7ffde4cf161372f2fb561840d3cfc5ad14 Mon Sep 17 00:00:00 2001 From: Matthew LeGendre Date: Wed, 26 Aug 2026 10:24:43 -0700 Subject: [PATCH 1/5] Add test for TLS issue This adds a large library as a dependency to the testsuite, which triggers the spindle issues around too-large TLS causing application exits. --- testsuite/Makefile.am | 22 ++++++++++++++++------ testsuite/Makefile.in | 20 +++++++++++++++----- testsuite/bigtls.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 testsuite/bigtls.c 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; +} + From 92afcac80c4b9340d8098f5574dadac032449c51 Mon Sep 17 00:00:00 2001 From: Matthew LeGendre Date: Wed, 26 Aug 2026 10:23:42 -0700 Subject: [PATCH 2/5] Fix issue with apps exiting at startup because of insufficient TLS GLIBC has a bug where IE TLS is allocated at audit library startup rather than application startup, which happens before application libraries are identified and loaded. This can leave the app with insufficient IE TLS. This works around the issue by manually doing the IE TLS calculation at exec() time, then using the GLIBC_TUNABLES environment variable to set the TLS size to a sufficient level for the application. The IE TLS calculation is done on a single node and communicated to clients via the spindle network. Co-Authored-By: Claude --- .gitignore | 1 + config.h.in | 3 + configure | 24 +- configure.common.ac | 15 +- scripts/static_tls_test/app.c | 24 + scripts/static_tls_test/minaudit.c | 6 + scripts/static_tls_test/run_test.sh | 18 + scripts/static_tls_test/statictls.c | 17 + src/client/auditclient/auditclient_common.c | 1 + src/client/auditclient/fixlocale.c | 2 +- src/client/beboot/Makefile.am | 2 +- src/client/beboot/Makefile.in | 26 +- src/client/beboot/spindle_bootstrap.c | 49 +- src/client/client/Makefile.am | 3 +- src/client/client/Makefile.in | 9 + src/client/client/exec_util.c | 299 ++++++- src/client/client/exec_util.h | 4 +- src/client/client/intercept_exec.c | 69 +- src/client/client_comlib/Makefile.am | 2 +- src/client/client_comlib/Makefile.in | 2 +- src/client/client_comlib/client_api.c | 46 +- src/client/client_comlib/client_api.h | 1 + src/client/config.h.in | 3 + src/client/configure | 24 +- src/cobo/handshake.c | 2 +- src/fe/config.h.in | 3 + src/fe/configure | 24 +- src/fe/startup/config_mgr.cc | 12 +- src/fe/startup/config_mgr.h | 4 +- src/include/ldcs_api.h | 5 +- src/include/spindle_launch.h | 1 + src/server/auditserver/Makefile.am | 6 +- src/server/auditserver/Makefile.in | 24 +- .../auditserver/filemngt_calc_static_tls.c | 827 ++++++++++++++++++ .../auditserver/filemngt_calc_static_tls.h | 28 + .../auditserver/ldcs_audit_server_filemngt.c | 1 + .../auditserver/ldcs_audit_server_handlers.c | 379 ++++++++ .../auditserver/ldcs_audit_server_process.c | 2 + .../auditserver/ldcs_audit_server_process.h | 4 + .../auditserver/ldcs_audit_server_server_cb.c | 1 + src/server/comlib/Makefile.am | 2 +- src/server/comlib/Makefile.in | 2 +- src/server/comlib/ldcs_api_util.c | 4 + src/server/config.h.in | 3 + src/server/configure | 24 +- src/utils/client_libraries.h | 47 + src/utils/static_tls.c | 207 +++++ src/utils/static_tls.h | 38 + 48 files changed, 2173 insertions(+), 127 deletions(-) create mode 100644 scripts/static_tls_test/app.c create mode 100644 scripts/static_tls_test/minaudit.c create mode 100755 scripts/static_tls_test/run_test.sh create mode 100644 scripts/static_tls_test/statictls.c create mode 100644 src/server/auditserver/filemngt_calc_static_tls.c create mode 100644 src/server/auditserver/filemngt_calc_static_tls.h create mode 100644 src/utils/client_libraries.h create mode 100644 src/utils/static_tls.c create mode 100644 src/utils/static_tls.h 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..933848e6 100755 --- a/configure +++ b/configure @@ -16848,13 +16848,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 +16862,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} "${CCFLAGS}" ${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..7e328d5c 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} "${CCFLAGS}" ${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..6bee3789 --- /dev/null +++ b/scripts/static_tls_test/run_test.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +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 -lstatictls -lpthread -Wl,-rpath,$BINDIR $SRCDIR/app.c +$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 47085b75..85b7e8f1 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 d45c5c95..ab81c316 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 \ @@ -178,6 +179,7 @@ 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_fmt.Plo \ $(top_builddir)/crash_handler/$(DEPDIR)/crash_handler.Plo \ $(top_builddir)/crash_handler/$(DEPDIR)/crash_io.Plo \ @@ -391,6 +393,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 \ @@ -466,6 +469,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) @@ -510,6 +516,7 @@ 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_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 @@ -772,6 +779,7 @@ 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_fmt.Plo -rm -f $(top_builddir)/crash_handler/$(DEPDIR)/crash_handler.Plo -rm -f $(top_builddir)/crash_handler/$(DEPDIR)/crash_io.Plo @@ -841,6 +849,7 @@ 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_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 86c8ffc7..3ad7eafd 100644 --- a/src/client/client_comlib/client_api.c +++ b/src/client/client_comlib/client_api.c @@ -32,13 +32,13 @@ #include "ldcs_api.h" #include "client_api.h" #include "client_heap.h" +#include "static_tls.h" static struct lock_t comm_lock; #define COMM_LOCK do { if (lock(&comm_lock) == -1) return -1; } while (0) #define COMM_UNLOCK unlock(&comm_lock) - int send_cachepath_query( int fd, char **chosen_realized_cachepath, char **chosen_parsed_cachepath){ int rc = 0; ldcs_message_t message; @@ -507,6 +507,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 63f92c7a..a13a5b93 100644 --- a/src/client/client_comlib/client_api.h +++ b/src/client/client_comlib/client_api.h @@ -43,6 +43,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..2956e584 100755 --- a/src/client/configure +++ b/src/client/configure @@ -12773,13 +12773,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 +12787,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} "${CCFLAGS}" ${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..a71bbddf 100755 --- a/src/fe/configure +++ b/src/fe/configure @@ -16623,13 +16623,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 +16637,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} "${CCFLAGS}" ${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 1d6e1889..8a033cf3 100644 --- a/src/fe/startup/config_mgr.cc +++ b/src/fe/startup/config_mgr.cc @@ -158,6 +158,12 @@ using namespace std; #define PYTHON_PREFIX_DEFAULT "" #endif +#if defined(STATIC_TLS_ALLOC_BUG) +#define DEFAULT_CALC_TLS "true" +#else +#define DEFAULT_CALC_TLS "false" +#endif + #if BINARY_PATCH_LDSO == 1 #define DEFAULT_PATCH_LDSO "true" #else @@ -310,7 +316,9 @@ void initOptionsList() { confRshCommand, "rsh-command", shortRSHCmd, groupMisc, cvString, {}, RSHCMD_STR, "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." } + "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." } } ); } @@ -1019,6 +1027,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); } } diff --git a/src/fe/startup/config_mgr.h b/src/fe/startup/config_mgr.h index ffebefc0..a5f72b23 100644 --- a/src/fe/startup/config_mgr.h +++ b/src/fe/startup/config_mgr.h @@ -69,7 +69,8 @@ enum SpindleConfigID { confEndSession, confRunSession, confPatchLdso, - confCrashDedup + confCrashDedup, + confCalcTLS }; enum CmdlineShortOptions { @@ -130,6 +131,7 @@ enum CmdlineShortOptions { shortPatchLdso = 299, shortCachePaths = 300, shortCrashDedup = 301, + shortCalcTLS = 302 }; enum CmdlineGroups { diff --git a/src/include/ldcs_api.h b/src/include/ldcs_api.h index 220eb349..a1042c24 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_UNKNOWN } ldcs_message_ids_t; @@ -111,7 +115,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 { diff --git a/src/include/spindle_launch.h b/src/include/spindle_launch.h index c2db2680..03e8247e 100644 --- a/src/include/spindle_launch.h +++ b/src/include/spindle_launch.h @@ -61,6 +61,7 @@ extern "C" { #define OPT_OFF (1 << 30) /* Turns spindle off, disabling everything */ #define OPT_PATCHLDSO (1 << 31) /* Enables patching of ld.so to intercept stat calls */ #define OPT_CRASH_HANDLER ((opt_t) 1 << 32) /* Enables crash handler with coredump deduplication */ +#define OPT_CALCTLS ((opt_t) 1 << 33) /* 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 8823ead6..05598b18 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_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_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 cede46ff..0414b9d2 100644 --- a/src/server/auditserver/Makefile.in +++ b/src/server/auditserver/Makefile.in @@ -126,7 +126,9 @@ am_libserverbase_la_OBJECTS = ldcs_audit_server_client_cb.lo \ ldcs_audit_server_crash_handler.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@) @@ -144,7 +146,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_filemngt.Plo \ @@ -378,10 +383,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_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_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 @@ -446,6 +451,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) @@ -459,7 +467,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 @@ -664,7 +674,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 @@ -725,7 +737,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_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 ebfdef13..1e2db0c4 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 ); /** @@ -1902,6 +1913,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); @@ -2003,6 +2016,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); default: err_printf("Received unexpected message from node: %d\n", (int) msg->header.type); assert(0); @@ -3084,6 +3101,368 @@ 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; + + 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; + + //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; + } + } + } + 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); + + static_tls_info_free(client->tls_info); + client->tls_info = NULL; + + 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 8cd7b936..fb50a3e6 100644 --- a/src/server/auditserver/ldcs_audit_server_process.c +++ b/src/server/auditserver/ldcs_audit_server_process.c @@ -167,6 +167,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 4a1734ae..3b905c25 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) */ @@ -183,6 +185,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 42981e14..5611de6f 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_used++; ldcs_process_data->client_counter++; ldcs_process_data->clients_live++; 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_util.c b/src/server/comlib/ldcs_api_util.c index e9c6cb89..812f3bd8 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_UNKNOWN); } return "unknown"; 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..56597034 100755 --- a/src/server/configure +++ b/src/server/configure @@ -16620,13 +16620,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 +16634,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} "${CCFLAGS}" ${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 From 7142af798f053f9960019733e7b2f254fb2b53f6 Mon Sep 17 00:00:00 2001 From: Matthew LeGendre Date: Mon, 28 Sep 2026 13:08:48 -0700 Subject: [PATCH 3/5] Allow clients to send messages to servers that are more than 4096 bytes. Adds dynamic sizing to message recieves from clients. The server will now maintain one buffer of size equal to the largest message received, dynamically growing it if needed for larger messages. Since we don't process multiple messages at once, this should remain safe and keep us from needing to manage message buffer cleanup. This feature was only added to ldcs_api_pipe.c under the assumption we need to cleanup/delete the biter and socket mechanisms. --- src/include/ldcs_api.h | 1 + .../auditserver/ldcs_audit_server_client_cb.c | 8 ++--- src/server/comlib/ldcs_api_biter.c | 6 ++++ src/server/comlib/ldcs_api_pipe.c | 29 ++++++++++++++++++- src/server/comlib/ldcs_api_socket.c | 7 +++++ src/server/comlib/ldcs_api_wrapper.c | 6 ++++ 6 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/include/ldcs_api.h b/src/include/ldcs_api.h index a1042c24..cfa57a6b 100644 --- a/src/include/ldcs_api.h +++ b/src/include/ldcs_api.h @@ -134,6 +134,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/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/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_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)(); From 68e175086cce686702d0689fbda5eb46a087ecdf Mon Sep 17 00:00:00 2001 From: Matthew LeGendre Date: Mon, 28 Sep 2026 13:39:54 -0700 Subject: [PATCH 4/5] Fix build and configure issues in TLS static calculations Fixes an issue where STATIC_TLS_ALLOC_BUG was being treated as either defined or undefined, when it should be treated as 1 or 0. Also fix issue in the static_tls/runtest.sh script that detects whether we have the GLIBC bug present. On Ubuntu, the libraries that the test adds need to be specified after the source file when building. Also fix issue with CFLAGS being mis-passed to the static_tls/runtest.sh script. --- configure | 20 ++++++++++++++------ configure.common.ac | 2 +- scripts/static_tls_test/run_test.sh | 4 ++-- src/client/configure | 20 ++++++++++++++------ src/fe/configure | 20 ++++++++++++++------ src/fe/startup/config_mgr.cc | 2 +- src/server/configure | 20 ++++++++++++++------ 7 files changed, 60 insertions(+), 28 deletions(-) diff --git a/configure b/configure index 933848e6..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} @@ -16864,7 +16872,7 @@ _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} "${CCFLAGS}" ${SPINDLE_SOURCE_ROOT} ${SPINDLE_BUILD_ROOT}; then +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; } diff --git a/configure.common.ac b/configure.common.ac index 7e328d5c..88e33663 100644 --- a/configure.common.ac +++ b/configure.common.ac @@ -124,7 +124,7 @@ 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} "${CCFLAGS}" ${SPINDLE_SOURCE_ROOT} ${SPINDLE_BUILD_ROOT}; then +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 diff --git a/scripts/static_tls_test/run_test.sh b/scripts/static_tls_test/run_test.sh index 6bee3789..49f9c7e2 100755 --- a/scripts/static_tls_test/run_test.sh +++ b/scripts/static_tls_test/run_test.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash CC=$1 CFLAGS=$2 @@ -9,7 +9,7 @@ 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 -lstatictls -lpthread -Wl,-rpath,$BINDIR $SRCDIR/app.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 diff --git a/src/client/configure b/src/client/configure index 2956e584..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} @@ -12789,7 +12797,7 @@ _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} "${CCFLAGS}" ${SPINDLE_SOURCE_ROOT} ${SPINDLE_BUILD_ROOT}; then +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; } diff --git a/src/fe/configure b/src/fe/configure index a71bbddf..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} @@ -16639,7 +16647,7 @@ _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} "${CCFLAGS}" ${SPINDLE_SOURCE_ROOT} ${SPINDLE_BUILD_ROOT}; then +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; } diff --git a/src/fe/startup/config_mgr.cc b/src/fe/startup/config_mgr.cc index 8a033cf3..0cc26fb8 100644 --- a/src/fe/startup/config_mgr.cc +++ b/src/fe/startup/config_mgr.cc @@ -158,7 +158,7 @@ using namespace std; #define PYTHON_PREFIX_DEFAULT "" #endif -#if defined(STATIC_TLS_ALLOC_BUG) +#if defined(STATIC_TLS_ALLOC_BUG) && (STATIC_TLS_ALLOC_BUG!=0) #define DEFAULT_CALC_TLS "true" #else #define DEFAULT_CALC_TLS "false" diff --git a/src/server/configure b/src/server/configure index 56597034..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} @@ -16636,7 +16644,7 @@ _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} "${CCFLAGS}" ${SPINDLE_SOURCE_ROOT} ${SPINDLE_BUILD_ROOT}; then +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; } From a850bd342b00bf5230dfc0c8e9269bb898f9b598 Mon Sep 17 00:00:00 2001 From: Matthew LeGendre Date: Tue, 29 Sep 2026 11:51:00 -0700 Subject: [PATCH 5/5] Fix use after free crash in TLS info handling --- .../auditserver/ldcs_audit_server_handlers.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/server/auditserver/ldcs_audit_server_handlers.c b/src/server/auditserver/ldcs_audit_server_handlers.c index 545b3f91..c7e73e6b 100644 --- a/src/server/auditserver/ldcs_audit_server_handlers.c +++ b/src/server/auditserver/ldcs_audit_server_handlers.c @@ -3327,6 +3327,8 @@ static int handle_tls_process_result(ldcs_process_data_t *procdata, static_tls_i 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 @@ -3354,6 +3356,8 @@ static int handle_tls_process_result(ldcs_process_data_t *procdata, static_tls_i 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; @@ -3361,17 +3365,29 @@ static int handle_tls_process_result(ldcs_process_data_t *procdata, static_tls_i 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. **/ @@ -3396,9 +3412,6 @@ static int handle_send_client_static_tls_resp(ldcs_process_data_t *procdata, int procdata->server_stat.clientmsg.time += (ldcs_get_time() - client->query_arrival_time); handle_close_client_query(procdata, nc); - static_tls_info_free(client->tls_info); - client->tls_info = NULL; - return result; }