From: H.J. Lu Date: Thu, 26 Jul 2018 14:48:55 +0000 (+0000) Subject: libsanitizer: Mark REAL(swapcontext) with indirect_return attribute on x86 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c83b4b824214039fea696083e6a888aa7c9063ce;p=gcc.git libsanitizer: Mark REAL(swapcontext) with indirect_return attribute on x86 Cherry-pick compiler-rt revision 337603: When shadow stack from Intel CET is enabled, the first instruction of all indirect branch targets must be a special instruction, ENDBR. lib/asan/asan_interceptors.cc has ... int res = REAL(swapcontext)(oucp, ucp); ... REAL(swapcontext) is a function pointer to swapcontext in libc. Since swapcontext may return via indirect branch on x86 when shadow stack is enabled, as in this case, int res = REAL(swapcontext)(oucp, ucp); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This function may be returned via an indirect branch. Here compiler must insert ENDBR after call, like call *bar(%rip) endbr64 I opened an LLVM bug: https://bugs.llvm.org/show_bug.cgi?id=38207 to add the indirect_return attribute so that it can be used to inform compiler to insert ENDBR after REAL(swapcontext) call. We mark REAL(swapcontext) with the indirect_return attribute if it is available. This fixed: https://bugs.llvm.org/show_bug.cgi?id=38249 Reviewed By: eugenis Differential Revision: https://reviews.llvm.org/D49608 PR target/86560 * asan/asan_interceptors.cc (swapcontext) Cherry-pick compiler-rt revision 337603. * sanitizer_common/sanitizer_internal_defs.h (__has_attribute): Likewise. From-SVN: r263009 --- diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index 80c3c0298dd..8e984f8b2e4 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,3 +1,11 @@ +2018-07-25 H.J. Lu + + PR target/86560 + * asan/asan_interceptors.cc (swapcontext) Cherry-pick + compiler-rt revision 337603. + * sanitizer_common/sanitizer_internal_defs.h (__has_attribute): + Likewise. + 2018-07-05 Jakub Jelinek Revert diff --git a/libsanitizer/asan/asan_interceptors.cc b/libsanitizer/asan/asan_interceptors.cc index a8f4b72723f..552cf9347af 100644 --- a/libsanitizer/asan/asan_interceptors.cc +++ b/libsanitizer/asan/asan_interceptors.cc @@ -267,7 +267,15 @@ INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, uptr stack, ssize; ReadContextStack(ucp, &stack, &ssize); ClearShadowMemoryForContextStack(stack, ssize); +#if __has_attribute(__indirect_return__) && \ + (defined(__x86_64__) || defined(__i386__)) + int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *) + __attribute__((__indirect_return__)) + = REAL(swapcontext); + int res = real_swapcontext(oucp, ucp); +#else int res = REAL(swapcontext)(oucp, ucp); +#endif // swapcontext technically does not return, but program may swap context to // "oucp" later, that would look as if swapcontext() returned 0. // We need to clear shadow for ucp once again, as it may be in arbitrary diff --git a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h index edd6a21c122..4413a88bea0 100644 --- a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h +++ b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h @@ -104,6 +104,11 @@ # define __has_feature(x) 0 #endif +// Older GCCs do not understand __has_attribute. +#if !defined(__has_attribute) +# define __has_attribute(x) 0 +#endif + // For portability reasons we do not include stddef.h, stdint.h or any other // system header, but we do need some basic types that are not defined // in a portable way by the language itself.