On Fri, Jul 20, 2018 at 1:11 PM, H.J. Lu <hongjiu...@intel.com> wrote: > 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 > > OK for trunk? > > H.J. > --- > PR target/86560 > * asan/asan_interceptors.cc (swapcontext): Call REAL(swapcontext) > with indirect_return attribute on x86 if indirect_return attribute > is available. > * sanitizer_common/sanitizer_internal_defs.h (__has_attribute): > New. > --- > libsanitizer/asan/asan_interceptors.cc | 8 ++++++++ > libsanitizer/sanitizer_common/sanitizer_internal_defs.h | 5 +++++ > 2 files changed, 13 insertions(+) > > 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. > -- > 2.17.1 >
Any objections? -- H.J.