From patchwork Wed Jul 18 17:35:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Lu, Hongjiu" X-Patchwork-Id: 28465 Received: (qmail 87530 invoked by alias); 18 Jul 2018 17:37:03 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 87427 invoked by uid 89); 18 Jul 2018 17:37:01 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, NO_DNS_FOR_FROM autolearn=ham version=3.3.2 spammy=manipulate X-HELO: mga03.intel.com Date: Wed, 18 Jul 2018 10:35:58 -0700 From: "H.J. Lu" To: GNU C Library Subject: [PATCH] ucontext.h: Add __INDIRECT_RETURN Message-ID: <20180718173558.GA18109@intel.com> Reply-To: "H.J. Lu" MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.10.0 (2018-05-17) On x86, swapcontext returns via indirect branch when shadow stack is enabled. Add __INDIRECT_RETURN to swapcontext to mark it return via indirect branch. When shadow stack is enabled, __INDIRECT_RETURN is defined with indirect_return attribute, which has been added to GCC 9. Otherwise __INDIRECT_RETURN is defined with returns_twice attribute. When shadow stack is enabled, remove always_inline attribute from prepare_test_buffer in string/tst-xbzero-opt.c to avoid: tst-xbzero-opt.c: In function ‘prepare_test_buffer’: tst-xbzero-opt.c:105:1: error: function ‘prepare_test_buffer’ can never be inlined because it uses setjmp prepare_test_buffer (unsigned char *buf) if indirect_return attribute isn't available. OK for master branch? H.J. --- * stdlib/ucontext.h (__INDIRECT_RETURN): New. Define as empty if not defined. (swapcontext): Add __INDIRECT_RETURN. * string/tst-xbzero-opt.c (ALWAYS_INLINE): New. (prepare_test_buffer): Use it. * sysdeps/unix/sysv/linux/x86/sys/ucontext.h (__INDIRECT_RETURN): New. Defined with indirect_return attribute or returns_twice attribute when shadow stack is enabled. --- stdlib/ucontext.h | 7 ++++++- string/tst-xbzero-opt.c | 10 +++++++++- sysdeps/unix/sysv/linux/x86/sys/ucontext.h | 11 +++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/stdlib/ucontext.h b/stdlib/ucontext.h index eec7611631..0f29c38d71 100644 --- a/stdlib/ucontext.h +++ b/stdlib/ucontext.h @@ -25,6 +25,10 @@ /* Get machine dependent definition of data structures. */ #include +#ifndef __INDIRECT_RETURN +# define __INDIRECT_RETURN +#endif + __BEGIN_DECLS /* Get user context and store it in variable pointed to by UCP. */ @@ -36,7 +40,8 @@ extern int setcontext (const ucontext_t *__ucp) __THROWNL; /* Save current context in context variable pointed to by OUCP and set context from variable pointed to by UCP. */ extern int swapcontext (ucontext_t *__restrict __oucp, - const ucontext_t *__restrict __ucp) __THROWNL; + const ucontext_t *__restrict __ucp) + __THROWNL __INDIRECT_RETURN; /* Manipulate user context UCP to continue with calling functions FUNC and the ARGC-1 parameters following ARGC when the context is used diff --git a/string/tst-xbzero-opt.c b/string/tst-xbzero-opt.c index cf7041f37a..d49ddef9ae 100644 --- a/string/tst-xbzero-opt.c +++ b/string/tst-xbzero-opt.c @@ -100,7 +100,15 @@ static ucontext_t uc_main, uc_co; /* Always check the test buffer immediately after filling it; this makes externally visible side effects depend on the buffer existing and having been filled in. */ -static inline __attribute__ ((always_inline)) void +#if defined __CET__ && !__GNUC_PREREQ (9, 0) +/* Note: swapcontext returns via indirect branch when SHSTK is enabled. + Without indirect_return attribute in GCC 9, swapcontext is marked + with returns_twice attribute, which prevents always_inline to work. */ +# define ALWAYS_INLINE +#else +# define ALWAYS_INLINE __attribute__ ((always_inline)) +#endif +static inline ALWAYS_INLINE void prepare_test_buffer (unsigned char *buf) { for (unsigned int i = 0; i < PATTERN_REPS; i++) diff --git a/sysdeps/unix/sysv/linux/x86/sys/ucontext.h b/sysdeps/unix/sysv/linux/x86/sys/ucontext.h index afb7c181bf..0b2b1e4804 100644 --- a/sysdeps/unix/sysv/linux/x86/sys/ucontext.h +++ b/sysdeps/unix/sysv/linux/x86/sys/ucontext.h @@ -24,6 +24,17 @@ #include #include +#ifndef __INDIRECT_RETURN +# if defined __CET__ && (__CET__ & 2) != 0 +/* Note: Functions returned via indirect branch returns once. Without + indirect_return attribute in GCC 9, use returns_twice attribute. */ +# if __GNUC_PREREQ (9, 0) +# define __INDIRECT_RETURN __attribute__ ((__indirect_return__)) +# else +# define __INDIRECT_RETURN __attribute__ ((__returns_twice__)) +# endif +# endif +#endif #ifdef __USE_MISC # define __ctx(fld) fld