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.

Reply via email to