libsanitizer: Mark REAL(swapcontext) with indirect_return attribute on x86
authorH.J. Lu <hongjiu.lu@intel.com>
Thu, 26 Jul 2018 14:48:55 +0000 (14:48 +0000)
committerH.J. Lu <hjl@gcc.gnu.org>
Thu, 26 Jul 2018 14:48:55 +0000 (07:48 -0700)
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

libsanitizer/ChangeLog
libsanitizer/asan/asan_interceptors.cc
libsanitizer/sanitizer_common/sanitizer_internal_defs.h

index 80c3c0298dd4df957461ad9894ce77185ad497fb..8e984f8b2e41d8cb3e6b216e356b7eb04d24f844 100644 (file)
@@ -1,3 +1,11 @@
+2018-07-25  H.J. Lu  <hongjiu.lu@intel.com>
+
+       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  <jakub@redhat.com>
 
        Revert
index a8f4b72723fe8eb13e4422ce10e8586df9ffe876..552cf9347af531c35b55407de800bd141aa491d1 100644 (file)
@@ -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
index edd6a21c1221cf3d8ddb6c066670dd0acd38e693..4413a88bea012637751637e826d5d6b8539f3410 100644 (file)
 # 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.