From 029e5b4f3c27e608780e3501ee5bacc92e46aa77 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Mon, 23 Dec 2024 17:16:00 -0500 Subject: [PATCH] Work around llvm-symbolizer LD_LIBRARY_PATH issue On some platforms llvm-symbolizer is linked against libcurl, which depends on the krb5 libraries. When the test suite runs programs with LD_LIBRARY_PATH pointed at asan-compiled krb5 libraries, llvm-symbolizer will encounter a dynamic linker error at startup, interfering with the display of stack traces. In k5test.py, when the build enables asan, wrap the platform's symbolizer in a script that unsets LD_LIBRARY_PATH (or similar) and then runs the real llvm-symbolizer. --- .github/workflows/build.yml | 7 +---- src/Makefile.in | 2 ++ src/util/k5test.py | 51 +++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2d166f5df0..8d7d02e74d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,13 +13,8 @@ jobs: matrix: name: [linux-clang, linux-clang-openssl, linux-gcc] include: - # llvm-symbolizer fails on Ubuntu 24.04 until we - # can avoid using LD_LIBRARY_PATH in the test - # suite. This causes test suite failures due to - # SIGPIPE exits from test programs. See - # https://github.com/llvm/llvm-project/issues/120915 - name: linux-clang - os: ubuntu-22.04 + os: ubuntu-latest compiler: clang makevars: CPPFLAGS=-Werror configureopts: --enable-asan diff --git a/src/Makefile.in b/src/Makefile.in index 352fb98887..e2286c5eed 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -515,11 +515,13 @@ testrealm: runenv.py # environment variable settings to propagate to Python-based tests +ASAN = @ASAN@ pyrunenv.vals: Makefile $(RUN_SETUP); \ for i in $(RUN_VARS); do \ eval echo 'env['\\\'$$i\\\''] = '\\\'\$$$$i\\\'; \ done > $@ + echo "asan = '$(ASAN)'" >> $@ echo "tls_impl = '$(TLS_IMPL)'" >> $@ echo "have_sasl = '$(HAVE_SASL)'" >> $@ echo "have_spake_openssl = '$(HAVE_SPAKE_OPENSSL)'" >> $@ diff --git a/src/util/k5test.py b/src/util/k5test.py index f3e0045c2e..d22cb5c804 100644 --- a/src/util/k5test.py +++ b/src/util/k5test.py @@ -392,6 +392,7 @@ command-line flags. These are documented in the --help output. import atexit import fcntl +import glob import optparse import os import shlex @@ -564,6 +565,31 @@ def _find_srctop(): return os.path.abspath(root) +# Look for the system LLVM symbolizer, matching the logic the asan +# runtime would use as closely as possible. +def _find_symbolizer(): + if sys.platform == 'darwin': + f = which('atos') + if f is not None: + return f + + f = which('llvm-symbolizer') + if f is not None: + return f + + # Debian-derived systems have versioned symbolizer names. If any + # exist, pick one of them. + l = glob.glob('/usr/bin/llvm-symbolizer-*') + if l: + return l[0] + + f = which('addr2line') + if f is not None: + return f + + return None + + # Parse command line arguments, setting global option variables. Also # sets the global variable args to the positional arguments, which may # be used by the test script. @@ -952,6 +978,7 @@ class K5Realm(object): if get_creds and create_kdb and create_user and start_kdc: self.kinit(self.user_princ, password('user')) self.klist(self.user_princ) + self._setup_symbolizer() def _create_empty_dir(self): dir = self.testdir @@ -1038,6 +1065,30 @@ class K5Realm(object): env['GSS_MECH_CONFIG'] = self.gss_mech_config return env + # The krb5 libraries may be included in the dependency chain of + # llvm-symbolizer, which is invoked by asan when displaying stack + # traces. If they are, asan-compiled krb5 libraries in + # LD_LIBRARY_PATH (or similar) will cause a dynamic linker error + # for the symbolizer at startup. Work around this problem by + # wrapping the symbolizer in a script that unsets the dynamic + # linker variables before calling the real symbolizer. + def _setup_symbolizer(self): + if runenv.asan != 'yes': + return + if 'ASAN_SYMBOLIZER_PATH' in self.env: + return + symbolizer_path = _find_symbolizer() + if symbolizer_path is None: + return + wrapper_path = os.path.join(self.testdir, 'llvm-symbolizer') + with open(wrapper_path, 'w') as f: + f.write('#!/bin/sh\n') + for v in runenv.env: + f.write('unset %s\n' % v) + f.write('exec %s "$@"\n' % symbolizer_path) + os.chmod(wrapper_path, 0o755) + self.env['ASAN_SYMBOLIZER_PATH'] = wrapper_path + def run(self, args, env=None, **keywords): if env is None: env = self.env -- 2.47.2