Repository navigation
Description
The adios2 E4S test failure is triggered by Spack's padding of library paths with a large number of slashes. libadios2_core.so.2.12.1 has, among other dependencies,
NEEDED //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////spack/opt/spack/linux-x86_64_v3/sqlite-3.53.1-zijikuhr4e5fgqqrd23672jmlpvsxya7/lib/libsqlite3.soThe conditions for the crash seem to be both that a library has a long name and that libc is loaded ahead of it. This can be reproduced with a simple example in the serial CI container:
spindleuser@spindlenode:~$ cat libfoo.c
int get_foo(void) {
return 42;
}
spindleuser@spindlenode:~$ cat test.c
#include <stdio.h>
int get_foo(void);
int main(void) {
int x = get_foo();
printf("x = %d\n", x);
return 0;
}spindleuser@spindlenode:~$ gcc -g -o libfoo.so libfoo.c -shared -fPIC
spindleuser@spindlenode:~$ gcc -g -o test test.c -Wl,--no-as-needed -lc "$(printf '/%.0s' {1..200})"${PWD}/libfoo.so
spindleuser@spindlenode:~$ readelf -d ./test | grep NEEDED
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////home/spindleuser/libfoo.so]
spindleuser@spindlenode:~$ ./test
x = 42
spindleuser@spindlenode:~$ spindle --level=off ./test
x = 42
spindleuser@spindlenode:~$ spindle --level=low ./test
x = 42
spindleuser@spindlenode:~$ spindle --level=medium ./test
spindleuser@spindlenode:~$ ls core.*
core.test.333libc has to come before the library to reproduce the problem. If it comes after, there is no crash:
spindleuser@spindlenode:~$ gcc -g -o test_libc_after test.c -Wl,--no-as-needed "$(printf '/%.0s' {1..200})"${PWD}/libfoo.so -lc
spindleuser@spindlenode:~$ spindle --level=medium ./test_libc_after
x = 42
spindleuser@spindlenode:~$ spindle --level=high ./test_libc_after
x = 42The backtrace is:
#0 0x0000000000028330 in ?? ()
#1 0x000076ea6b80ff59 in ptmalloc_init () at ./malloc/arena.c:300
#2 0x000076ea6b813965 in ptmalloc_init () at ./malloc/arena.c:264
#3 __GI___libc_malloc (bytes=bytes@entry=229) at ./malloc/malloc.c:3302
#4 0x000076ea6bc99f38 in patch_on_linkactivity (lmap=lmap@entry=0x76ea6b979580) at /home/spindleuser/Spindle/src/client/subaudit/../auditclient/patch_linkmap.c:69
#5 0x000076ea6bc98fc7 in spindle_la_objopen (map=0x76ea6b979580, lmid=<optimized out>, cookie=<optimized out>) at /home/spindleuser/Spindle/src/client/auditclient/auditclient.c:58
#6 0x000076ea6bcf3c0c in _dl_audit_objopen (l=l@entry=0x76ea6b979580, nsid=nsid@entry=0) at ./elf/dl-audit.c:87
#7 0x000076ea6bce1988 in _dl_map_object_from_fd (name=name@entry=0x76ea6b97fe20 "/tmp/commpath/cachepath/spindle.201730c4a8acde67/home/spindleuser/1-spindlens-file-libfoo.so", origname=origname@entry=0x62106851a518 '/' <repeats 200 times>..., fd=-1,
fbp=fbp@entry=0x7ffc1d6dfe90, realname=<optimized out>, loader=loader@entry=0x76ea6bd122e0, l_type=<optimized out>, mode=<optimized out>, stack_endp=<optimized out>, nsid=<optimized out>) at ./elf/dl-load.c:1515
#8 0x000076ea6bce2529 in _dl_map_object (loader=<optimized out>, name=0x76ea6b97fe20 "/tmp/commpath/cachepath/spindle.201730c4a8acde67/home/spindleuser/1-spindlens-file-libfoo.so", type=1, trace_mode=<optimized out>, mode=0, nsid=<optimized out>)
at ./elf/dl-load.c:2268
#9 0x000076ea6bcdba2d in openaux (a=a@entry=0x7ffc1d6e0460) at ./elf/dl-deps.c:64
#10 0x000076ea6bcda51c in __GI__dl_catch_exception (exception=exception@entry=0x7ffc1d6e0440, operate=operate@entry=0x76ea6bcdb9f0 <openaux>, args=args@entry=0x7ffc1d6e0460) at ./elf/dl-catch.c:237
#11 0x000076ea6bcdbe67 in _dl_map_object_deps (map=map@entry=0x76ea6bd122e0, preloads=preloads@entry=0x0, npreloads=<optimized out>, trace_mode=<optimized out>, open_mode=open_mode@entry=0) at ./elf/dl-deps.c:232
#12 0x000076ea6bcfb41c in dl_main (phdr=<optimized out>, phnum=<optimized out>, user_entry=<optimized out>, auxv=<optimized out>) at ./elf/rtld.c:1965
#13 0x000076ea6bcf7f46 in _dl_sysdep_start (start_argptr=start_argptr@entry=0x7ffc1d6e0ca0, dl_main=dl_main@entry=0x76ea6bcf9af0 <dl_main>) at ../sysdeps/unix/sysv/linux/dl-sysdep.c:140
#14 0x000076ea6bcf975e in _dl_start_final (arg=0x7ffc1d6e0ca0) at ./elf/rtld.c:494
#15 _dl_start (arg=0x7ffc1d6e0ca0) at ./elf/rtld.c:581
#16 0x000076ea6bcf8548 in _start () from /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
#17 0x0000000000000001 in ?? ()
#18 0x00007ffc1d6e261c in ?? ()
#19 0x0000000000000000 in ?? ()The relevant code is:
Spindle/src/client/auditclient/patch_linkmap.c
Lines 47 to 83 in 4638b9d
| void patch_on_linkactivity(struct link_map *lmap) | |
| { | |
| size_t len; | |
| char *oname; | |
| if (!last_rewritten_name || !last_orig_name) | |
| return; | |
| if (lmap->l_name == last_rewritten_name || | |
| lmap->l_name == ldso_path || | |
| strcmp(lmap->l_name, last_rewritten_name) == 0 || | |
| strcmp(lmap->l_name, ldso_path) == 0) | |
| { | |
| debug_printf3("Replacing name %s with name %s\n", lmap->l_name, last_orig_name); | |
| if (strlen(lmap->l_name) >= strlen(last_orig_name)) { | |
| strcpy(lmap->l_name, last_orig_name); | |
| } | |
| else { | |
| malloc_sig_t app_malloc = get_libc_malloc(); | |
| if (app_malloc) { | |
| len = strlen(last_orig_name) + 2; | |
| oname = (char *) app_malloc(len); | |
| if (oname) { | |
| strncpy(oname, last_orig_name, len); | |
| lmap->l_name = oname; | |
| } | |
| } | |
| } | |
| } | |
| else { | |
| debug_printf3("Did not replace name %s with name %s\n", lmap->l_name ? : "NULL", last_orig_name ? : "NULL"); | |
| } | |
| spindle_free(last_orig_name); | |
| last_rewritten_name = NULL; | |
| last_orig_name = NULL; | |
| } |
For the non-crashing case where libc comes after the long-name library, get_libc_malloc() returns NULL and the malloc is skipped. Where libc comes before the long-name library get_libc_malloc() returns the address to libc's malloc and new memory for a copy of last_orig_name is allocated, and there is a crash inside malloc.
While this also involves using the libc malloc, this is different than what is seen in #226 as no alternate malloc implementation is used here — both Spindle and the application are using the libc malloc.
Activity