Open zackw opened 3 years ago
I've also hit this issue as python might call it:
(gdb) bt
#0 0x0000000000000000 in ()
#1 0x00007ffff764f90f in __interceptor_crypt_r(char*, char*, void*) (key=0x7ffff41606a0 "", salt=0x7fffdca47560 "$6$xw6c2VXM1jXmR3Ci", data=0x7fffffff2f48) at ../../../../libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:9598
#2 0x00007fffdcae51da in crypt_crypt_impl.constprop () at /usr/lib64/python3.9/lib-dynload/_crypt.cpython-39-x86_64-linux-gnu.so
#3 0x00007fffdcae5333 in crypt_crypt () at /usr/lib64/python3.9/lib-dynload/_crypt.cpython-39-x86_64-linux-gnu.so
#4 0x00007ffff738f85c in cfunction_vectorcall_FASTCALL () at /lib64/libpython3.9.so.1.0
#5 0x00007ffff7386bee in _PyEval_EvalFrameDefault () at /lib64/libpython3.9.so.1.0
I think the interceptors are not really valid because the functions are not defined by dependencies of libasan
, so dlsym
with RTLD_NEXT
cannot reliably find them.
Many distributions have moved to libxcrypt by now, and therefore can get a properly asan-instrumented libcrypt. The interceptors should probably no longer be included on GNU/Linux (or even plain Linux).
I submitted a patch to LLVM: https://reviews.llvm.org/D144073
@fweimer-rh Note that the interceptors for crypt and crypt_r are pickier about invalid function call arguments: quoting https://github.com/besser82/libxcrypt/commit/3aa82ccd3a3fecea7e6a9d0f9c85c56e2e04bb78#diff-964ef584f48a9f4feeae999451131ce52adc204e4f36e48fc00fdcffc3e4f85fR212
Our crypt() functions return NULL / a failure token, with errno set to EINVAL, when either the setting or the phrase argument is NULL. ASan's interceptors for crypt() instead crash the program when either argument is NULL -- this is arguably a better choice, but for compatibility's sake we can't change what our functions do. There is no way to disable interception of specific functions as far as I can tell. Therefore, these tests are skipped when compiled with ASan.
If you have any ideas for how libxcrypt could be modified to allow applications to opt into the pickier behavior, perhaps by using one or more of -fsanitize=address
, -fsanitize=undefined
, -D_FORTIFY_SOURCE
, please make suggestions (in the form of either a new issue or a PR) over at https://github.com/besser82/libxcrypt .
I'm one of the developers of libxcrypt, which is a drop-in replacement for Glibc's
libcrypt
offering modern password-hashing algorithms. It implements, among other things, the functionscrypt
andcrypt_r
. In CI, we run our own testsuite with ASan enabled to weed out bugs.In sufficiently recent versions of the libsanitizer shipped with GCC (version 10.2 is new enough; I don't know when this was added), there are interceptors for
crypt
andcrypt_r
. When we compile our own testsuite with-fsanitize=address
, these interpose on the calls from our test programs to our implementations within our libcrypt.{a,so}. That's abstractly the Right Thing, but it doesn't work: we reach, for instance,__interceptor_crypt_r
with the function pointer__interception::real_crypt_r
(_ZN14__interception12real_crypt_rE
) not yet having been initialized, so the program tries to call address 0 and crashes. (Debugger transcript at end of message.)Is there something we ought to be doing in our code to make
__interception::real_crypt_r
get initialized, or is this a plain sanitizer bug?Debugger transcript. libxcrypt was configured with
CC='gcc -fsanitize=undefined,address' --disable-shared
, after whichmake check
compiles everything fine and reports a whole bunch of failures due to jumps to address 0, one of them being thespecial-char-salt
testcase.