Open mpolacek opened 1 year ago
The problem seems to be that i686 libasan doesn't intercept some libpthread functions it should, likely these (thanks to Jakub Jelinek):
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_attr_getaffinity_np);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_attr_getguardsize); \
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_attr_getstacksize); \
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_attr_getstack);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_attr_getstacksize); \
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_barrierattr_getpshared);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_condattr_getclock);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_condattr_getpshared);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_getaffinity_np);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_getcpuclockid);
sanitizer_common_interceptors.inc:#define INIT_PTHREAD_GETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_getname_np);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprioceiling);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprotocol);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getpshared);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust_np);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_gettype);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getkind_np);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getpshared);
sanitizer_common_interceptors.inc:#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
sanitizer_common_interceptors.inc:#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
sanitizer_common_interceptors.inc:#define INIT_PTHREAD_SIGMASK COMMON_INTERCEPT_FUNCTION(pthread_sigmask);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(sem_destroy); \
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(sem_getvalue); \
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(sem_init); \
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(sem_open); \
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(sem_post); \
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(sem_timedwait); \
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(sem_trywait); \
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(sem_unlink);
sanitizer_common_interceptors.inc: COMMON_INTERCEPT_FUNCTION(sem_wait); \
$ readelf -Ws /lib/libc.so.6 > /tmp/4; for i in `grep '[^@]@[^@]' /tmp/4 | awk '{print $NF}' | sort -u | sed '/GLIBC_PRIVATE/d;s/@.*//;/^__pthread/d' | grep '\(pthread\|sem\)_'`; do grep -q $i@@ /tmp/4 && grep -q COMMON_INTERCEPT_FUNCTION'('$i')' sanitizer_common/* && echo $i; done | sort -u
pthread_attr_getaffinity_np
pthread_attr_getguardsize
pthread_attr_getstack
pthread_attr_getstacksize
pthread_barrierattr_getpshared
pthread_condattr_getclock
pthread_condattr_getpshared
pthread_getaffinity_np
pthread_getcpuclockid
pthread_getname_np
pthread_mutexattr_getprioceiling
pthread_mutexattr_getprotocol
pthread_mutexattr_getpshared
pthread_mutexattr_getrobust
pthread_mutexattr_gettype
pthread_rwlockattr_getkind_np
pthread_rwlockattr_getpshared
pthread_setname_np
pthread_sigmask
sem_destroy
sem_getvalue
sem_init
sem_open
sem_post
sem_timedwait
sem_trywait
sem_unlink
sem_wait
is what I've used. For some symbols even on x86_64 I can't see how the interception can currently work, say
pthread_attr_getaffinity_np
had just 2 arguments in 2.3.3 and only got 3 in 2.3.4, so when dlsym resolves to the oldest one,
it will just crash. Note, for x86_64 running the above command with /lib64/
instead of /lib
results in similar list, but for some symbols it isn't that urgent, e.g. some GLIBC_2.34 symbols are just the same as 2.3.4 ones and the newer symver was probably added just because it now handles some new flags or something similar.
I'm seeing a similar issue using Ubuntu 22.04 with gcc-12 and clang-17 packages when using asan on multilib (32-bit builds). sem_timedwait will never wakeup. 32-bit builds without asan are fine and building natively for x86_64 with asan also works.
Couple traces showing mix of old and new:
frame #0: 0xf7fc5129 [vdso]`__kernel_vsyscall + 9
frame #1: 0xf7a23366 libc.so.6`__libc_do_syscall at libc-do-syscall.S:41
frame #2: 0xf7990e81 libc.so.6`__futex_abstimed_wait_common at futex-internal.c:40:12
frame #3: 0xf7990e40 libc.so.6`__futex_abstimed_wait_common(futex_word=0xf6a043a4, expected=1, clockid=<unavailable>, abstime=0xf72e8cbc, private=0, cancel=true) at futex-internal.c:99:11
frame #4: 0xf7990fff libc.so.6`__GI___futex_abstimed_wait_cancelable64(futex_word=<unavailable>, expected=<unavailable>, clockid=<unavailable>, abstime=<no summary available>, private=<no summary available>) at futex-internal.c:139:10 [artificial]
frame #5: 0xf799d031 libc.so.6`do_futex_wait(sem=<unavailable>, abstime=<unavailable>, clockid=<unavailable>) at sem_waitcommon.c:116:9
frame #6: 0xf799d0d9 libc.so.6`__new_sem_wait_slow64(sem=0xf6a043a4, abstime=0xf72e8cbc, clockid=<unavailable>) at sem_waitcommon.c:284:14
frame #7: 0xf799d213 libc.so.6`___sem_timedwait [inlined] ___sem_timedwait64(abstime=0xf72e8cbc, sem=0xf6a043a4) at sem_timedwait.c:40:12
frame #8: 0xf799d208 libc.so.6`___sem_timedwait [inlined] ___sem_timedwait64(abstime=0xf72e8cbc, sem=0xf6a043a4) at sem_timedwait.c:26:1
frame #9: 0xf799d208 libc.so.6`___sem_timedwait(sem=0xf6a043a4, abstime=0xf7230890) at sem_timedwait.c:55:10
frame #10: 0x56aee191 ut_orca_mt`__interceptor_sem_timedwait + 145
and:
* frame #0: 0xf7fc5129 [vdso]`__kernel_vsyscall + 9
frame #1: 0xf7a8249c libc.so.6`__old_sem_wait(sem=0xf6a04054) at sem_wait.c:65:13
frame #2: 0x56aee0b2 ut_orca_mt`__interceptor_sem_wait + 50
See also this other report on SO: https://stackoverflow.com/questions/75005217/linux-32bit-compiled-sem-timedwait-example-with-small-mod-fails-on-64-bit-wh
The following program hangs with
-m32
, but not without:(and therefore the same happens with gcc)