diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index c0e5563ac6f..e60f31bbc46 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,3 +1,15 @@ +2017-02-11 Jakub Jelinek + + PR sanitizer/79341 + * configure.tgt (s390*-*-linux*): Don't disable libsanitizer on + s390-linux 31-bit. + * sanitizer_common/sanitizer_internal_defs.h: Cherry-pick upstream + r294793. + * sanitizer_common/sanitizer_common_interceptors.inc: Cherry-pick + upstream r294790. + * sanitizer_common/sanitizer_linux_s390.cc: Cherry-pick upstream + r294799. + 2017-02-03 Maxim Ostapenko PR sanitizer/78663 diff --git a/libsanitizer/configure.tgt b/libsanitizer/configure.tgt index e648051aab8..82e8a5513c5 100644 --- a/libsanitizer/configure.tgt +++ b/libsanitizer/configure.tgt @@ -40,9 +40,6 @@ case "${target}" in sparc*-*-linux*) ;; s390*-*-linux*) - if test x$ac_cv_sizeof_void_p = x4; then - UNSUPPORTED=1 - fi ;; arm*-*-linux*) ;; diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc index 38390ed9621..0970eda5ee6 100644 --- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc +++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc @@ -4550,11 +4550,15 @@ void *__tls_get_addr_opt(void *arg); // descriptor offset as an argument instead of a pointer. GOT address // is passed in r12, so it's necessary to write it in assembly. This is // the function used by the compiler. -#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr_internal) +extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg)); +#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset) +DEFINE_REAL(uptr, __tls_get_offset, void *arg) +extern "C" uptr __tls_get_offset(void *arg); +extern "C" uptr __interceptor___tls_get_offset(void *arg); INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg); - uptr res = REAL(__tls_get_addr_internal)(arg); + uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset)); uptr tp = reinterpret_cast(__builtin_thread_pointer()); void *ptr = reinterpret_cast(res + tp); uptr tls_begin, tls_end; @@ -4566,32 +4570,43 @@ INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) { } return res; } -// We need a protected symbol aliasing the above, so that we can jump +// We need a hidden symbol aliasing the above, so that we can jump // directly to it from the assembly below. extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"), - visibility("protected"))) -uptr __interceptor___tls_get_addr_internal_protected(void *arg); + visibility("hidden"))) +uptr __tls_get_addr_hidden(void *arg); // Now carefully intercept __tls_get_offset. asm( ".text\n" - ".global __tls_get_offset\n" - "__tls_get_offset:\n" // The __intercept_ version has to exist, so that gen_dynamic_list.py // exports our symbol. + ".weak __tls_get_offset\n" + ".type __tls_get_offset, @function\n" + "__tls_get_offset:\n" ".global __interceptor___tls_get_offset\n" + ".type __interceptor___tls_get_offset, @function\n" "__interceptor___tls_get_offset:\n" #ifdef __s390x__ "la %r2, 0(%r2,%r12)\n" - "jg __interceptor___tls_get_addr_internal_protected\n" + "jg __tls_get_addr_hidden\n" #else "basr %r3,0\n" "0: la %r2,0(%r2,%r12)\n" "l %r4,1f-0b(%r3)\n" "b 0(%r4,%r3)\n" - "1: .long __interceptor___tls_get_addr_internal_protected - 0b\n" + "1: .long __tls_get_addr_hidden - 0b\n" #endif - ".type __tls_get_offset, @function\n" - ".size __tls_get_offset, .-__tls_get_offset\n" + ".size __interceptor___tls_get_offset, .-__interceptor___tls_get_offset\n" +// Assembly wrapper to call REAL(__tls_get_offset)(arg) + ".type __tls_get_offset_wrapper, @function\n" + "__tls_get_offset_wrapper:\n" +#ifdef __s390x__ + "sgr %r2,%r12\n" +#else + "sr %r2,%r12\n" +#endif + "br %r3\n" + ".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n" ); #endif // SANITIZER_S390 #else diff --git a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h index b9c906669de..676ade143d8 100644 --- a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h +++ b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h @@ -287,7 +287,12 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond, enum LinkerInitialized { LINKER_INITIALIZED = 0 }; #if !defined(_MSC_VER) || defined(__clang__) -# define GET_CALLER_PC() (uptr)__builtin_return_address(0) +# if SANITIZER_S390_31 +# define GET_CALLER_PC() \ + (uptr)__builtin_extract_return_addr(__builtin_return_address(0)) +# else +# define GET_CALLER_PC() (uptr)__builtin_return_address(0) +# endif # define GET_CURRENT_FRAME() (uptr)__builtin_frame_address(0) inline void Trap() { __builtin_trap(); diff --git a/libsanitizer/sanitizer_common/sanitizer_linux_s390.cc b/libsanitizer/sanitizer_common/sanitizer_linux_s390.cc index c7d647528ab..3faaa1c26ac 100644 --- a/libsanitizer/sanitizer_common/sanitizer_linux_s390.cc +++ b/libsanitizer/sanitizer_common/sanitizer_linux_s390.cc @@ -134,6 +134,18 @@ static bool FixedCVE_2016_2143() { if (ptr[0] == '.') patch = internal_simple_strtoll(ptr+1, &ptr, 10); if (major < 3) { + if (major == 2 && minor == 6 && patch == 32 && ptr[0] == '-' && + internal_strstr(ptr, ".el6")) { + // Check RHEL6 + int r1 = internal_simple_strtoll(ptr+1, &ptr, 10); + if (r1 >= 657) // 2.6.32-657.el6 or later + return true; + if (r1 == 642 && ptr[0] == '.') { + int r2 = internal_simple_strtoll(ptr+1, &ptr, 10); + if (r2 >= 9) // 2.6.32-642.9.1.el6 or later + return true; + } + } // <3.0 is bad. return false; } else if (major == 3) { @@ -143,6 +155,18 @@ static bool FixedCVE_2016_2143() { // 3.12.58+ is OK. if (minor == 12 && patch >= 58) return true; + if (minor == 10 && patch == 0 && ptr[0] == '-' && + internal_strstr(ptr, ".el7")) { + // Check RHEL7 + int r1 = internal_simple_strtoll(ptr+1, &ptr, 10); + if (r1 >= 426) // 3.10.0-426.el7 or later + return true; + if (r1 == 327 && ptr[0] == '.') { + int r2 = internal_simple_strtoll(ptr+1, &ptr, 10); + if (r2 >= 27) // 3.10.0-327.27.1.el7 or later + return true; + } + } // Otherwise, bad. return false; } else if (major == 4) {