ucontext.h: Add __INDIRECT_RETURN
Commit Message
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(-)
Comments
On Wed, 18 Jul 2018, H.J. Lu wrote:
> +#ifndef __INDIRECT_RETURN
> +# define __INDIRECT_RETURN
> +#endif
This default definition is missing a comment to define the semantics of
this macro. And please avoid this #ifndef convention. Rather, the normal
glibc convention would be to have e.g. a bits/indirect-return.h installed
header, with a default version with an empty definition and a comment
documenting the semantics, and a separate x86 version.
* H. J. Lu:
> +#ifndef __INDIRECT_RETURN
> +# if defined __CET__ && (__CET__ & 2) != 0
> +/* Note: Functions returned via indirect branch returns once. Without
The grammar seems to be a bit off here.
> + 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
Do you expect distributions to backport support for the
indirect_return attribute into GCC 8? Then this will not work.
On Wed, Jul 18, 2018 at 2:06 PM, Florian Weimer <fw@deneb.enyo.de> wrote:
> * H. J. Lu:
>
>> +#ifndef __INDIRECT_RETURN
>> +# if defined __CET__ && (__CET__ & 2) != 0
>> +/* Note: Functions returned via indirect branch returns once. Without
>
> The grammar seems to be a bit off here.
>
>> + 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
>
> Do you expect distributions to backport support for the
> indirect_return attribute into GCC 8? Then this will not work.
I am running into another swapcontext issue:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86560
I need to change indirect_return to function type attribute to support
function pointer:
https://gcc.gnu.org/ml/gcc-patches/2018-07/msg01007.html
I am planning to backport both patches to GCC 8 branch. When that
happens, we can change __GNUC_PREREQ (9, 0) to __GNUC_PREREQ (8, x).
Do you have a better solution?
@@ -25,6 +25,10 @@
/* Get machine dependent definition of data structures. */
#include <sys/ucontext.h>
+#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
@@ -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++)
@@ -24,6 +24,17 @@
#include <bits/types/sigset_t.h>
#include <bits/types/stack_t.h>
+#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