diff mbox series

Linux/x86: Support shadow stack pointer in setjmp/longjmp

Message ID 20171218162753.GA25026@gmail.com
State New
Headers show
Series Linux/x86: Support shadow stack pointer in setjmp/longjmp | expand

Commit Message

H.J. Lu Dec. 18, 2017, 4:27 p.m. UTC
Save and restore shadow stack pointer in setjmp and longjmp to support
shadow stack in Intel CET.  Use feature_1 in tcbhead_t to check if
shadow stack is enabled before saving and restoring shadow stack
pointer so that it works with the old smaller cancel_jmp_buf which
doesn't have space for shadow stack pointer.

This patch requires:

https://sourceware.org/ml/libc-alpha/2017-12/msg00552.html
https://sourceware.org/ml/libc-alpha/2017-12/msg00208.html

Any comments?

H.J.
---
2017-12-07  Igor Tsimbalist  <igor.v.tsimbalist@intel.com>
	    H.J. Lu  <hongjiu.lu@intel.com>

	* sysdeps/unix/sysv/linux/i386/____longjmp_chk.S: Include
	<jmp_buf-ssp.h>.  Restore shadow stack pointer if shadow
	stack is enabled.
	* sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S: Likewise.
	* sysdeps/unix/sysv/linux/i386/__longjmp.S: New file.
	* sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S: Likewise.
	* sysdeps/unix/sysv/linux/i386/bsd-setjmp.S: Likewise.
	* sysdeps/unix/sysv/linux/i386/setjmp.S: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/__longjmp.S: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/setjmp.S: Likewise.
---
 sysdeps/unix/sysv/linux/i386/____longjmp_chk.S   |  36 +++++-
 sysdeps/unix/sysv/linux/i386/__longjmp.S         | 141 +++++++++++++++++++++++
 sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S       |  72 ++++++++++++
 sysdeps/unix/sysv/linux/i386/bsd-setjmp.S        |  82 +++++++++++++
 sysdeps/unix/sysv/linux/i386/setjmp.S            |  73 ++++++++++++
 sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S |  35 ++++++
 sysdeps/unix/sysv/linux/x86_64/__longjmp.S       | 105 +++++++++++++++++
 sysdeps/unix/sysv/linux/x86_64/setjmp.S          |  82 +++++++++++++
 8 files changed, 625 insertions(+), 1 deletion(-)
 create mode 100644 sysdeps/unix/sysv/linux/i386/__longjmp.S
 create mode 100644 sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S
 create mode 100644 sysdeps/unix/sysv/linux/i386/bsd-setjmp.S
 create mode 100644 sysdeps/unix/sysv/linux/i386/setjmp.S
 create mode 100644 sysdeps/unix/sysv/linux/x86_64/__longjmp.S
 create mode 100644 sysdeps/unix/sysv/linux/x86_64/setjmp.S

Comments

Joseph Myers Dec. 18, 2017, 5:44 p.m. UTC | #1
On Mon, 18 Dec 2017, H.J. Lu wrote:

> 	* sysdeps/unix/sysv/linux/i386/__longjmp.S: New file.
> 	* sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/bsd-setjmp.S: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/setjmp.S: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/__longjmp.S: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/setjmp.S: Likewise.

Why are all these files Linux-specific?  ____longjmp_chk is Linux-specific 
because it does a sysaltstack syscall, but I don't see anything 
OS-specific in these files.  Why shouldn't shadow stack support be 
available for all OSes on these architectures?

Is support for the relevant instructions available in all binutils 
versions supported for building glibc?  If not, does __SHSTK__ being 
defined guarantee that GCC was built with a binutils version with the 
required support, or do we need additional configure checks for binutils 
support?
H.J. Lu Dec. 18, 2017, 6:08 p.m. UTC | #2
Resent to glibc.  Sorry if you got this email twice.

On Mon, Dec 18, 2017 at 9:54 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Mon, Dec 18, 2017 at 9:44 AM, Joseph Myers <joseph@codesourcery.com> wrote:
>> On Mon, 18 Dec 2017, H.J. Lu wrote:
>>
>>>       * sysdeps/unix/sysv/linux/i386/__longjmp.S: New file.
>>>       * sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S: Likewise.
>>>       * sysdeps/unix/sysv/linux/i386/bsd-setjmp.S: Likewise.
>>>       * sysdeps/unix/sysv/linux/i386/setjmp.S: Likewise.
>>>       * sysdeps/unix/sysv/linux/x86_64/__longjmp.S: Likewise.
>>>       * sysdeps/unix/sysv/linux/x86_64/setjmp.S: Likewise.
>>
>> Why are all these files Linux-specific?  ____longjmp_chk is Linux-specific
>> because it does a sysaltstack syscall, but I don't see anything
>> OS-specific in these files.  Why shouldn't shadow stack support be
>> available for all OSes on these architectures?
>
> Shadow stack support needs CET support in OS kernel.  We are updating
> Linux arch_prctl syscall to support CET.
>
>> Is support for the relevant instructions available in all binutils
>> versions supported for building glibc?  If not, does __SHSTK__ being
>> defined guarantee that GCC was built with a binutils version with the
>> required support, or do we need additional configure checks for binutils
>> support?
>
> We check if binutils and GCC support CET before we enable CET:
>
> https://sourceware.org/git/?p=glibc.git;a=commit;h=d977bdb7caa1a0795687b1ea88cd24183231a37e
>
> diff --git a/sysdeps/unix/sysv/linux/x86/configure.ac
> b/sysdeps/unix/sysv/linux/x86/configure.ac
> new file mode 100644
> index 0000000..7ef9fbe
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/configure.ac
> @@ -0,0 +1,48 @@
> +GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
> +# Local configure fragment for sysdeps/unix/sysv/linux/x86.
> +
> +if test x"$enable_cet" = xdefault || test x"$enable_cet" = xyes; then
> +  # Check if CET can be enabled.
> +  AC_CACHE_CHECK(whether CET can be enabled,
> + libc_cv_x86_cet_available, [dnl
> +cat > conftest.c <<EOF
> +#if !defined __IBT__ || !defined __SHSTK__
> +# error CET isn't available.
> +#endif
> +EOF
> + if AC_TRY_COMMAND(${CC-cc} -c $CFLAGS -fcf-protection -mcet -include
> cet.h conftest.c 1>&AS_MESSAGE_LOG_FD); then
> +    libc_cv_x86_cet_available=yes
> + else
> +    libc_cv_x86_cet_available=no
> + fi
> + rm -rf conftest*])
> +  if test $libc_cv_x86_cet_available = yes; then
> +    enable_cet=yes
> +  else
> +    if test x"$enable_cet" = xdefault; then
> +      enable_cet=no
> +    else
> +      AC_MSG_ERROR([$CC doesn't support CET])
> +    fi
> +  fi
> +fi
> +if test $enable_cet = yes; then
> +  # Check if assembler supports CET.
> +  AC_CACHE_CHECK(whether $AS supports CET,
> + libc_cv_x86_cet_as, [dnl
> +cat > conftest.s <<EOF
> + incsspd %ecx
> +EOF
> + if AC_TRY_COMMAND(${CC-cc} -c $CFLAGS conftest.s -o conftest.o
> 1>&AS_MESSAGE_LOG_FD); then
> +    libc_cv_x86_cet_as=yes
> + else
> +    libc_cv_x86_cet_as=no
> + fi
> + rm -rf conftest*])
> +  if test $libc_cv_x86_cet_as = no; then
> +    AC_MSG_ERROR([$AS doesn't support CET])
> +  fi
> +  AC_DEFINE(ENABLE_CET, 1,
> +     [Enable Intel Control-flow Enforcement Technology (CET)])
> +fi
> +LIBC_CONFIG_VAR([enable-cet], [$enable_cet])
> --
>
> H.J.
Joseph Myers Dec. 18, 2017, 6:25 p.m. UTC | #3
On Mon, 18 Dec 2017, H.J. Lu wrote:

> Resent to glibc.  Sorry if you got this email twice.
> 
> On Mon, Dec 18, 2017 at 9:54 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> > On Mon, Dec 18, 2017 at 9:44 AM, Joseph Myers <joseph@codesourcery.com> wrote:
> >> On Mon, 18 Dec 2017, H.J. Lu wrote:
> >>
> >>>       * sysdeps/unix/sysv/linux/i386/__longjmp.S: New file.
> >>>       * sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S: Likewise.
> >>>       * sysdeps/unix/sysv/linux/i386/bsd-setjmp.S: Likewise.
> >>>       * sysdeps/unix/sysv/linux/i386/setjmp.S: Likewise.
> >>>       * sysdeps/unix/sysv/linux/x86_64/__longjmp.S: Likewise.
> >>>       * sysdeps/unix/sysv/linux/x86_64/setjmp.S: Likewise.
> >>
> >> Why are all these files Linux-specific?  ____longjmp_chk is Linux-specific
> >> because it does a sysaltstack syscall, but I don't see anything
> >> OS-specific in these files.  Why shouldn't shadow stack support be
> >> available for all OSes on these architectures?
> >
> > Shadow stack support needs CET support in OS kernel.  We are updating
> > Linux arch_prctl syscall to support CET.

But none of those files you're adding above use prctl.  I'd expect exactly 
the same code you have there to be applicable to all OSes with CET 
support, even if some other parts of the CET support in glibc are 
genuinely OS-specific.  Unless there is something genuinely OS-specific in 
this code that would be inappropriate for another OS with CET support?

Under what circumstances will __SHSTK__ be defined?  If it's only with 
non-default GCC configure options or options used to build glibc, or only 
when GCC is configured for Linux target, then I'd expect such __SHSTK__ 
conditionals to be OK in OS-independent __longjmp etc. implementations.  
The only case where having it in OS-independent code would be problematic 
would be if __SHSTK__ can get defined by default when building for another 
OS, and thereby introduce dependencies on pieces that are missing for 
other OSes.  And even then, __SHSTK__ could be replaced by another 
conditional for "glibc OS-specific support is present".

> >> Is support for the relevant instructions available in all binutils
> >> versions supported for building glibc?  If not, does __SHSTK__ being
> >> defined guarantee that GCC was built with a binutils version with the
> >> required support, or do we need additional configure checks for binutils
> >> support?
> >
> > We check if binutils and GCC support CET before we enable CET:
> >
> > https://sourceware.org/git/?p=glibc.git;a=commit;h=d977bdb7caa1a0795687b1ea88cd24183231a37e

That doesn't seem to be one of the patches you listed as a dependency of 
this one.  Does that not matter because __SHSTK__ can never be defined 
when building glibc unless that other patch is in glibc?
H.J. Lu Dec. 18, 2017, 8:22 p.m. UTC | #4
On Mon, Dec 18, 2017 at 10:25 AM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Mon, 18 Dec 2017, H.J. Lu wrote:
>
>> Resent to glibc.  Sorry if you got this email twice.
>>
>> On Mon, Dec 18, 2017 at 9:54 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> > On Mon, Dec 18, 2017 at 9:44 AM, Joseph Myers <joseph@codesourcery.com> wrote:
>> >> On Mon, 18 Dec 2017, H.J. Lu wrote:
>> >>
>> >>>       * sysdeps/unix/sysv/linux/i386/__longjmp.S: New file.
>> >>>       * sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S: Likewise.
>> >>>       * sysdeps/unix/sysv/linux/i386/bsd-setjmp.S: Likewise.
>> >>>       * sysdeps/unix/sysv/linux/i386/setjmp.S: Likewise.
>> >>>       * sysdeps/unix/sysv/linux/x86_64/__longjmp.S: Likewise.
>> >>>       * sysdeps/unix/sysv/linux/x86_64/setjmp.S: Likewise.
>> >>
>> >> Why are all these files Linux-specific?  ____longjmp_chk is Linux-specific
>> >> because it does a sysaltstack syscall, but I don't see anything
>> >> OS-specific in these files.  Why shouldn't shadow stack support be
>> >> available for all OSes on these architectures?
>> >
>> > Shadow stack support needs CET support in OS kernel.  We are updating
>> > Linux arch_prctl syscall to support CET.
>
> But none of those files you're adding above use prctl.  I'd expect exactly
> the same code you have there to be applicable to all OSes with CET
> support, even if some other parts of the CET support in glibc are
> genuinely OS-specific.  Unless there is something genuinely OS-specific in
> this code that would be inappropriate for another OS with CET support?

You need to make room in jmpbuf for shadow stack pointer, like

sysdeps/unix/sysv/linux/x86/setjmpP.h

> Under what circumstances will __SHSTK__ be defined?  If it's only with
> non-default GCC configure options or options used to build glibc, or only
> when GCC is configured for Linux target, then I'd expect such __SHSTK__
> conditionals to be OK in OS-independent __longjmp etc. implementations.

See above.

> The only case where having it in OS-independent code would be problematic
> would be if __SHSTK__ can get defined by default when building for another
> OS, and thereby introduce dependencies on pieces that are missing for
> other OSes.  And even then, __SHSTK__ could be replaced by another
> conditional for "glibc OS-specific support is present".

CET will be enabled automatically on Linux/x86 if both GCC and binutils
support CET.  When CET is enabled, __SHSTK__  is defined by GCC.

>> >> Is support for the relevant instructions available in all binutils
>> >> versions supported for building glibc?  If not, does __SHSTK__ being
>> >> defined guarantee that GCC was built with a binutils version with the
>> >> required support, or do we need additional configure checks for binutils
>> >> support?
>> >
>> > We check if binutils and GCC support CET before we enable CET:
>> >
>> > https://sourceware.org/git/?p=glibc.git;a=commit;h=d977bdb7caa1a0795687b1ea88cd24183231a37e
>
> That doesn't seem to be one of the patches you listed as a dependency of
> this one.  Does that not matter because __SHSTK__ can never be defined
> when building glibc unless that other patch is in glibc?

I submitted the setjmp patch to show how backward binary compatibility
is preserved.   Yes, setjmp is unchanged if we aren't building glibc with
CET enabled, which will be done in a separate patch.
H.J. Lu Dec. 19, 2017, 4:41 p.m. UTC | #5
On Mon, Dec 18, 2017 at 12:22 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Mon, Dec 18, 2017 at 10:25 AM, Joseph Myers <joseph@codesourcery.com> wrote:
>> On Mon, 18 Dec 2017, H.J. Lu wrote:
>>
>>> Resent to glibc.  Sorry if you got this email twice.
>>>
>>> On Mon, Dec 18, 2017 at 9:54 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>> > On Mon, Dec 18, 2017 at 9:44 AM, Joseph Myers <joseph@codesourcery.com> wrote:
>>> >> On Mon, 18 Dec 2017, H.J. Lu wrote:
>>> >>
>>> >>>       * sysdeps/unix/sysv/linux/i386/__longjmp.S: New file.
>>> >>>       * sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S: Likewise.
>>> >>>       * sysdeps/unix/sysv/linux/i386/bsd-setjmp.S: Likewise.
>>> >>>       * sysdeps/unix/sysv/linux/i386/setjmp.S: Likewise.
>>> >>>       * sysdeps/unix/sysv/linux/x86_64/__longjmp.S: Likewise.
>>> >>>       * sysdeps/unix/sysv/linux/x86_64/setjmp.S: Likewise.
>>> >>
>>> >> Why are all these files Linux-specific?  ____longjmp_chk is Linux-specific
>>> >> because it does a sysaltstack syscall, but I don't see anything
>>> >> OS-specific in these files.  Why shouldn't shadow stack support be
>>> >> available for all OSes on these architectures?
>>> >
>>> > Shadow stack support needs CET support in OS kernel.  We are updating
>>> > Linux arch_prctl syscall to support CET.
>>
>> But none of those files you're adding above use prctl.  I'd expect exactly
>> the same code you have there to be applicable to all OSes with CET
>> support, even if some other parts of the CET support in glibc are
>> genuinely OS-specific.  Unless there is something genuinely OS-specific in
>> this code that would be inappropriate for another OS with CET support?
>
> You need to make room in jmpbuf for shadow stack pointer, like
>
> sysdeps/unix/sysv/linux/x86/setjmpP.h
>
>> Under what circumstances will __SHSTK__ be defined?  If it's only with
>> non-default GCC configure options or options used to build glibc, or only
>> when GCC is configured for Linux target, then I'd expect such __SHSTK__
>> conditionals to be OK in OS-independent __longjmp etc. implementations.
>
> See above.
>
>> The only case where having it in OS-independent code would be problematic
>> would be if __SHSTK__ can get defined by default when building for another
>> OS, and thereby introduce dependencies on pieces that are missing for
>> other OSes.  And even then, __SHSTK__ could be replaced by another
>> conditional for "glibc OS-specific support is present".
>
> CET will be enabled automatically on Linux/x86 if both GCC and binutils
> support CET.  When CET is enabled, __SHSTK__  is defined by GCC.
>
>>> >> Is support for the relevant instructions available in all binutils
>>> >> versions supported for building glibc?  If not, does __SHSTK__ being
>>> >> defined guarantee that GCC was built with a binutils version with the
>>> >> required support, or do we need additional configure checks for binutils
>>> >> support?
>>> >
>>> > We check if binutils and GCC support CET before we enable CET:
>>> >
>>> > https://sourceware.org/git/?p=glibc.git;a=commit;h=d977bdb7caa1a0795687b1ea88cd24183231a37e
>>
>> That doesn't seem to be one of the patches you listed as a dependency of
>> this one.  Does that not matter because __SHSTK__ can never be defined
>> when building glibc unless that other patch is in glibc?
>
> I submitted the setjmp patch to show how backward binary compatibility
> is preserved.   Yes, setjmp is unchanged if we aren't building glibc with
> CET enabled, which will be done in a separate patch.
>

As I mentioned, we need room in jmp_buf to save and restore shadow stack
pointer in setjmp/longjmp.  Since only Linux/x86 jmp_buf has a space for
shadow stack pointer, this setjmp/longjmp patch is only for Linux/x86.

I am checking it in today.
Zack Weinberg Dec. 19, 2017, 6:18 p.m. UTC | #6
On Tue, Dec 19, 2017 at 8:41 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>> That doesn't seem to be one of the patches you listed as a dependency of
>>> this one.  Does that not matter because __SHSTK__ can never be defined
>>> when building glibc unless that other patch is in glibc?
>>
>> I submitted the setjmp patch to show how backward binary compatibility
>> is preserved.   Yes, setjmp is unchanged if we aren't building glibc with
>> CET enabled, which will be done in a separate patch.
>>
>
> As I mentioned, we need room in jmp_buf to save and restore shadow stack
> pointer in setjmp/longjmp.  Since only Linux/x86 jmp_buf has a space for
> shadow stack pointer, this setjmp/longjmp patch is only for Linux/x86.
>
> I am checking it in today.

I don't think you have consensus. You haven't answered most of
Joseph's questions, and it is not clear to me whether Florian
considers his objection resolved.  This is not a high-priority bugfix.
Please stop trying to rush it in.

zw
H.J. Lu Dec. 19, 2017, 6:25 p.m. UTC | #7
On Tue, Dec 19, 2017 at 10:18 AM, Zack Weinberg <zackw@panix.com> wrote:
> On Tue, Dec 19, 2017 at 8:41 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>>> That doesn't seem to be one of the patches you listed as a dependency of
>>>> this one.  Does that not matter because __SHSTK__ can never be defined
>>>> when building glibc unless that other patch is in glibc?
>>>
>>> I submitted the setjmp patch to show how backward binary compatibility
>>> is preserved.   Yes, setjmp is unchanged if we aren't building glibc with
>>> CET enabled, which will be done in a separate patch.
>>>
>>
>> As I mentioned, we need room in jmp_buf to save and restore shadow stack
>> pointer in setjmp/longjmp.  Since only Linux/x86 jmp_buf has a space for
>> shadow stack pointer, this setjmp/longjmp patch is only for Linux/x86.
>>
>> I am checking it in today.
>
> I don't think you have consensus. You haven't answered most of
> Joseph's questions, and it is not clear to me whether Florian
> considers his objection resolved.  This is not a high-priority bugfix.

I have answered all questions.   Please show one question which I haven't
answered.

> Please stop trying to rush it in.
>
> zw
Joseph Myers Dec. 19, 2017, 6:26 p.m. UTC | #8
On Tue, 19 Dec 2017, Zack Weinberg wrote:

> On Tue, Dec 19, 2017 at 8:41 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> >>> That doesn't seem to be one of the patches you listed as a dependency of
> >>> this one.  Does that not matter because __SHSTK__ can never be defined
> >>> when building glibc unless that other patch is in glibc?
> >>
> >> I submitted the setjmp patch to show how backward binary compatibility
> >> is preserved.   Yes, setjmp is unchanged if we aren't building glibc with
> >> CET enabled, which will be done in a separate patch.
> >>
> >
> > As I mentioned, we need room in jmp_buf to save and restore shadow stack
> > pointer in setjmp/longjmp.  Since only Linux/x86 jmp_buf has a space for
> > shadow stack pointer, this setjmp/longjmp patch is only for Linux/x86.
> >
> > I am checking it in today.
> 
> I don't think you have consensus. You haven't answered most of

HJ, I think you're persistently showing problems with judging consensus, 
and henceforth should *only* commit patches that at least one maintainer 
has explicitly approved in the exact form in which you wish to commit 
them, rather than trying to judge a patch to have consensus without such 
an explicit approval.

> Joseph's questions, and it is not clear to me whether Florian
> considers his objection resolved.  This is not a high-priority bugfix.

Furthermore, the points about missing kernel interfaces and the many 
FIXMEs in the substantive CET patch strongly suggest the main feature this 
is meant to enable will not be ready for 2.27.
Joseph Myers Dec. 19, 2017, 6:33 p.m. UTC | #9
On Tue, 19 Dec 2017, H.J. Lu wrote:

> > I don't think you have consensus. You haven't answered most of
> > Joseph's questions, and it is not clear to me whether Florian
> > considers his objection resolved.  This is not a high-priority bugfix.
> 
> I have answered all questions.   Please show one question which I haven't
> answered.

I don't think you've adequately justified having OS-specific versions of 
all the setjmp/longjmp files, as opposed to having e.g. defined __SHSTK__ 
&& defined SHADOW_STACK_POINTER_OFFSET && defined FEATURE_1_OFFSET 
conditionals in the OS-independent files (which looks more like the actual 
condition that should be relevant here).
H.J. Lu Dec. 19, 2017, 6:36 p.m. UTC | #10
On Tue, Dec 19, 2017 at 10:33 AM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Tue, 19 Dec 2017, H.J. Lu wrote:
>
>> > I don't think you have consensus. You haven't answered most of
>> > Joseph's questions, and it is not clear to me whether Florian
>> > considers his objection resolved.  This is not a high-priority bugfix.
>>
>> I have answered all questions.   Please show one question which I haven't
>> answered.
>
> I don't think you've adequately justified having OS-specific versions of
> all the setjmp/longjmp files, as opposed to having e.g. defined __SHSTK__
> && defined SHADOW_STACK_POINTER_OFFSET && defined FEATURE_1_OFFSET
> conditionals in the OS-independent files (which looks more like the actual
> condition that should be relevant here).
>

OK, let's punt it for glibc 2.28.
diff mbox series

Patch

diff --git a/sysdeps/unix/sysv/linux/i386/____longjmp_chk.S b/sysdeps/unix/sysv/linux/i386/____longjmp_chk.S
index 2e4427abc8..3c2d94e52b 100644
--- a/sysdeps/unix/sysv/linux/i386/____longjmp_chk.S
+++ b/sysdeps/unix/sysv/linux/i386/____longjmp_chk.S
@@ -19,7 +19,7 @@ 
 #include <jmpbuf-offsets.h>
 #include <asm-syntax.h>
 #include <stap-probe.h>
-
+#include <jmp_buf-ssp.h>
 
 	.section .rodata.str1.1,"aMS",@progbits,1
 	.type	longjmp_msg,@object
@@ -46,6 +46,40 @@  longjmp_msg:
 ENTRY (____longjmp_chk)
 	movl	4(%esp), %ecx	/* User's jmp_buf in %ecx.  */
 
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl   $(1 << 1), %gs:FEATURE_1_OFFSET
+	jz      .Lnoadj
+# endif
+	/* Check and adjust the Shadow-Stack-Pointer.  */
+	xorl	%edx, %edx
+	/* Get the current ssp.  */
+	rdsspd	%edx
+	/* And compare it with the saved ssp value.  */
+	subl	SHADOW_STACK_POINTER_OFFSET(%ecx), %edx
+	je	.Lnoadj
+	/* Count the number of frames to adjust and adjust it
+	   with incssp instruction.  The instruction can adjust
+	   the ssp by [0..255] value only thus use a loop if
+	   the number of frames is bigger than 255.  */
+	negl	%edx
+	shrl	$2, %edx
+	/* NB: We saved Shadow-Stack-Pointer of setjmp.  Since we are
+	       restoring Shadow-Stack-Pointer of setjmp's caller, we
+	       need to unwind shadow stack by one more frame.  */
+	addl	$1, %edx
+	cmpl	$255, %edx
+	jbe	.Lonetime
+.Loopadj:
+	incsspd	%edx
+	subl	$255, %edx
+	cmpl	$255, %edx
+	ja	.Loopadj
+.Lonetime:
+	incsspd	%edx
+.Lnoadj:
+#endif
 	/* Save the return address now.  */
 	movl	(JB_PC*4)(%ecx), %edx
 	/* Get the stack pointer.  */
diff --git a/sysdeps/unix/sysv/linux/i386/__longjmp.S b/sysdeps/unix/sysv/linux/i386/__longjmp.S
new file mode 100644
index 0000000000..20eeced02e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/__longjmp.S
@@ -0,0 +1,141 @@ 
+/* longjmp for Linux/i386 with shadow stack support.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <asm-syntax.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+	.text
+ENTRY (__longjmp)
+#ifdef PTR_DEMANGLE
+	movl 4(%esp), %eax	/* User's jmp_buf in %eax.  */
+
+# ifdef __SHSTK__
+#  if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl $(1 << 1), %gs:FEATURE_1_OFFSET
+	jz .Lnoadj
+#  endif
+	/* Check and adjust the Shadow-Stack-Pointer.  */
+	xorl %edx, %edx
+	/* Get the current ssp.  */
+	rdsspd %edx
+	/* And compare it with the saved ssp value.  */
+	subl SHADOW_STACK_POINTER_OFFSET(%eax), %edx
+	je .Lnoadj
+	/* Count the number of frames to adjust and adjust it
+	   with incssp instruction.  The instruction can adjust
+	   the ssp by [0..255] value only thus use a loop if
+	   the number of frames is bigger than 255.  */
+	negl %edx
+	shrl $2, %edx
+	/* NB: We saved Shadow-Stack-Pointer of setjmp.  Since we are
+	       restoring Shadow-Stack-Pointer of setjmp's caller, we
+	       need to unwind shadow stack by one more frame.  */
+	addl $1, %edx
+	cmpl $255, %edx
+	jbe .Lonetime
+.Loopadj:
+	incsspd %edx
+	subl $255, %edx
+	cmpl $255, %edx
+	ja .Loopadj
+.Lonetime:
+	incsspd %edx
+.Lnoadj:
+# endif
+	/* Save the return address now.  */
+	movl (JB_PC*4)(%eax), %edx
+	/* Get the stack pointer.  */
+	movl (JB_SP*4)(%eax), %ecx
+	PTR_DEMANGLE (%edx)
+	PTR_DEMANGLE (%ecx)
+	LIBC_PROBE (longjmp, 3, 4@%eax, -4@8(%esp), 4@%edx)
+	cfi_def_cfa(%eax, 0)
+	cfi_register(%eip, %edx)
+	cfi_register(%esp, %ecx)
+	cfi_offset(%ebx, JB_BX*4)
+	cfi_offset(%esi, JB_SI*4)
+	cfi_offset(%edi, JB_DI*4)
+	cfi_offset(%ebp, JB_BP*4)
+	/* Restore registers.  */
+	movl (JB_BX*4)(%eax), %ebx
+	movl (JB_SI*4)(%eax), %esi
+	movl (JB_DI*4)(%eax), %edi
+	movl (JB_BP*4)(%eax), %ebp
+	cfi_restore(%ebx)
+	cfi_restore(%esi)
+	cfi_restore(%edi)
+	cfi_restore(%ebp)
+
+	LIBC_PROBE (longjmp_target, 3, 4@%eax, -4@8(%esp), 4@%edx)
+	movl 8(%esp), %eax	/* Second argument is return value.  */
+	movl %ecx, %esp
+#else
+	movl 4(%esp), %ecx	/* User's jmp_buf in %ecx.  */
+	movl 8(%esp), %eax	/* Second argument is return value.  */
+# ifdef __SHSTK__
+#  if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl $(1 << 1), %gs:FEATURE_1_OFFSET
+	jz .Lnoadj
+#  endif
+	/* Check and adjust the Shadow-Stack-Pointer.  */
+	xorl %edx, %edx
+	/* Get the current ssp.  */
+	rdsspd	%edx
+	/* And compare it with the saved ssp value.  */
+	subl SHADOW_STACK_POINTER_OFFSET(%ecx), %edx
+	je .Lnoadj
+	/* Count the number of frames to adjust and adjust it
+	   with incssp instruction.  The instruction can adjust
+	   the ssp by [0..255] value only thus use a loop if
+	   the number of frames is bigger than 255.  */
+	negl %edx
+	shrl $2, %edx
+	/* NB: We saved Shadow-Stack-Pointer of setjmp.  Since we are
+	       restoring Shadow-Stack-Pointer of setjmp's caller, we
+	       need to unwind shadow stack by one more frame.  */
+	addl $1, %edx
+	cmpl $255, %edx
+	jbe .Lonetime
+.Loopadj:
+	incsspd %edx
+	subl $255, %edx
+	cmpl $255, %edx
+	ja .Loopadj
+.Lonetime:
+	incsspd %edx
+.Lnoadj:
+# endif
+	/* Save the return address now.  */
+	movl (JB_PC*4)(%ecx), %edx
+	LIBC_PROBE (longjmp, 3, 4@%ecx, -4@%eax, 4@%edx)
+	/* Restore registers.  */
+	movl (JB_BX*4)(%ecx), %ebx
+	movl (JB_SI*4)(%ecx), %esi
+	movl (JB_DI*4)(%ecx), %edi
+	movl (JB_BP*4)(%ecx), %ebp
+	movl (JB_SP*4)(%ecx), %esp
+	LIBC_PROBE (longjmp_target, 3, 4@%ecx, -4@%ecx, 4@%edx)
+#endif
+	/* Jump to saved PC.  */
+	jmp *%edx
+END (__longjmp)
diff --git a/sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S b/sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S
new file mode 100644
index 0000000000..9cdd969397
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/bsd-_setjmp.S
@@ -0,0 +1,72 @@ 
+/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'.  Linux/i386 version
+   with shadow stack support.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 0)'.
+   We cannot do it in C because it must be a tail-call, so frame-unwinding
+   in setjmp doesn't clobber the state restored by longjmp.  */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+#define PARMS	4		/* no space for saved regs */
+#define JMPBUF	PARMS
+#define SIGMSK	JMPBUF+4
+
+ENTRY (_setjmp)
+
+	xorl %eax, %eax
+	movl JMPBUF(%esp), %edx
+
+	/* Save registers.  */
+	movl %ebx, (JB_BX*4)(%edx)
+	movl %esi, (JB_SI*4)(%edx)
+	movl %edi, (JB_DI*4)(%edx)
+	leal JMPBUF(%esp), %ecx	/* Save SP as it will be after we return.  */
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
+	movl %ecx, (JB_SP*4)(%edx)
+	movl 0(%esp), %ecx	/* Save PC we are returning to now.  */
+	LIBC_PROBE (setjmp, 3, 4@%edx, -4@$0, 4@%ecx)
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
+	movl %ecx, (JB_PC*4)(%edx)
+	movl %ebp, (JB_BP*4)(%edx) /* Save caller's frame pointer.  */
+
+	movl %eax, JB_SIZE(%edx) /* No signal mask set.  */
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl $(1 << 1), %gs:FEATURE_1_OFFSET
+	jz .Lskip_ssp
+# endif
+	/* Get the current Shadow-Stack-Pointer and save it.  */
+	xorl %ecx, %ecx
+	rdsspd %ecx
+	movl %ecx, SHADOW_STACK_POINTER_OFFSET(%edx)
+# if IS_IN (libc) && defined SHARED
+.Lskip_ssp:
+# endif
+#endif
+	ret
+END (_setjmp)
+libc_hidden_def (_setjmp)
diff --git a/sysdeps/unix/sysv/linux/i386/bsd-setjmp.S b/sysdeps/unix/sysv/linux/i386/bsd-setjmp.S
new file mode 100644
index 0000000000..a66a5a1050
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/bsd-setjmp.S
@@ -0,0 +1,82 @@ 
+/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'.  Linux/i386 version
+   with shadow stack support.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 1)'.
+   We cannot do it in C because it must be a tail-call, so frame-unwinding
+   in setjmp doesn't clobber the state restored by longjmp.  */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+#define PARMS  4		/* no space for saved regs */
+#define JMPBUF PARMS
+#define SIGMSK JMPBUF+4
+
+ENTRY (setjmp)
+	/* Note that we have to use a non-exported symbol in the next
+	   jump since otherwise gas will emit it as a jump through the
+	   PLT which is what we cannot use here.  */
+
+	movl JMPBUF(%esp), %eax
+
+	/* Save registers.  */
+	movl %ebx, (JB_BX*4)(%eax)
+	movl %esi, (JB_SI*4)(%eax)
+	movl %edi, (JB_DI*4)(%eax)
+	leal JMPBUF(%esp), %ecx	/* Save SP as it will be after we return.  */
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
+	movl %ecx, (JB_SP*4)(%eax)
+	movl 0(%esp), %ecx	/* Save PC we are returning to now.  */
+	LIBC_PROBE (setjmp, 3, 4@%eax, -4@$1, 4@%ecx)
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
+	movl %ecx, (JB_PC*4)(%eax)
+	movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer.  */
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl $(1 << 1), %gs:FEATURE_1_OFFSET
+	jz .Lskip_ssp
+# endif
+	/* Get the current Shadow-Stack-Pointer and save it.  */
+	xorl %ecx, %ecx
+	rdsspd %ecx
+	movl %ecx, SHADOW_STACK_POINTER_OFFSET(%eax)
+# if IS_IN (libc) && defined SHARED
+.Lskip_ssp:
+# endif
+#endif
+
+	/* Call __sigjmp_save.  */
+	pushl $1
+	cfi_adjust_cfa_offset (4)
+	pushl 8(%esp)
+	cfi_adjust_cfa_offset (4)
+	call __sigjmp_save
+	popl %ecx
+	cfi_adjust_cfa_offset (-4)
+	popl %edx
+	cfi_adjust_cfa_offset (-4)
+	ret
+END (setjmp)
diff --git a/sysdeps/unix/sysv/linux/i386/setjmp.S b/sysdeps/unix/sysv/linux/i386/setjmp.S
new file mode 100644
index 0000000000..d7f0ade257
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/setjmp.S
@@ -0,0 +1,73 @@ 
+/* setjmp for Linux/i386 with shadow stack support.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <asm-syntax.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+#define PARMS	4		/* no space for saved regs */
+#define JMPBUF	PARMS
+#define SIGMSK	JMPBUF+4
+
+ENTRY (__sigsetjmp)
+
+	movl JMPBUF(%esp), %eax
+
+	/* Save registers.  */
+	movl %ebx, (JB_BX*4)(%eax)
+	movl %esi, (JB_SI*4)(%eax)
+	movl %edi, (JB_DI*4)(%eax)
+	leal JMPBUF(%esp), %ecx	/* Save SP as it will be after we return.  */
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
+	movl %ecx, (JB_SP*4)(%eax)
+	movl 0(%esp), %ecx	/* Save PC we are returning to now.  */
+	LIBC_PROBE (setjmp, 3, 4@%eax, -4@SIGMSK(%esp), 4@%ecx)
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
+	movl %ecx, (JB_PC*4)(%eax)
+	movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer.  */
+
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl $(1 << 1), %gs:FEATURE_1_OFFSET
+	jz .Lskip_ssp
+# endif
+	/* Get the current Shadow-Stack-Pointer and save it.  */
+	xorl %ecx, %ecx
+	rdsspd %ecx
+	movl %ecx, SHADOW_STACK_POINTER_OFFSET(%eax)
+# if IS_IN (libc) && defined SHARED
+.Lskip_ssp:
+# endif
+#endif
+#if IS_IN (rtld)
+	/* In ld.so we never save the signal mask.  */
+	xorl %eax, %eax
+	ret
+#else
+	/* Make a tail call to __sigjmp_save; it takes the same args.  */
+	jmp __sigjmp_save
+#endif
+END (__sigsetjmp)
+hidden_def (__sigsetjmp)
diff --git a/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S b/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
index 2955c56a56..ee4664d916 100644
--- a/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
+++ b/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
@@ -21,6 +21,7 @@ 
 #include <stap-probe.h>
 
 #include <sigaltstack-offsets.h>
+#include <jmp_buf-ssp.h>
 
 	.section .rodata.str1.1,"aMS",@progbits,1
 	.type	longjmp_msg,@object
@@ -105,6 +106,40 @@  ENTRY(____longjmp_chk)
 	cfi_restore (%rsi)
 
 .Lok:
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl	$(1 << 1), %fs:FEATURE_1_OFFSET
+	jz	.Lnoadj
+# endif
+	/* Check and adjust the Shadow-Stack-Pointer.  */
+	xorq	%rax, %rax
+	/* Get the current ssp.  */
+	rdsspq	%rax
+	/* And compare it with the saved ssp value.  */
+	subq	SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
+	je	.Lnoadj
+	/* Count the number of frames to adjust and adjust it
+	   with incssp instruction.  The instruction can adjust
+	   the ssp by [0..255] value only thus use a loop if
+	   the number of frames is bigger than 255.  */
+	negq	%rax
+	shrq	$3, %rax
+	/* NB: We saved Shadow-Stack-Pointer of setjmp.  Since we are
+	       restoring Shadow-Stack-Pointer of setjmp's caller, we
+	       need to unwind shadow stack by one more frame.  */
+	addq	$1, %rax
+	cmpq	$255, %rax
+	jbe	.Lonetime
+.Loopadj:
+	incsspq	%rax
+	subq	$255, %rax
+	cmpq	$255, %rax
+	ja	.Loopadj
+.Lonetime:
+	incsspq	%rax
+.Lnoadj:
+#endif
 	LIBC_PROBE (longjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RDX_LP)
 	/* We add unwind information for the target here.  */
 	cfi_def_cfa(%rdi, 0)
diff --git a/sysdeps/unix/sysv/linux/x86_64/__longjmp.S b/sysdeps/unix/sysv/linux/x86_64/__longjmp.S
new file mode 100644
index 0000000000..f92aa93431
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/__longjmp.S
@@ -0,0 +1,105 @@ 
+/* longjmp for Linux/x86-64 with shadow stack support.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <jmp_buf-ssp.h>
+#include <asm-syntax.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+/* Jump to the position specified by ENV, causing the
+   setjmp call there to return VAL, or 1 if VAL is 0.
+   void __longjmp (__jmp_buf env, int val).  */
+	.text
+ENTRY(__longjmp)
+	/* Restore registers.  */
+	mov (JB_RSP*8)(%rdi),%R8_LP
+	mov (JB_RBP*8)(%rdi),%R9_LP
+	mov (JB_PC*8)(%rdi),%RDX_LP
+#ifdef PTR_DEMANGLE
+	PTR_DEMANGLE (%R8_LP)
+	PTR_DEMANGLE (%R9_LP)
+	PTR_DEMANGLE (%RDX_LP)
+# ifdef __ILP32__
+	/* We ignored the high bits of the %rbp value because only the low
+	   bits are mangled.  But we cannot presume that %rbp is being used
+	   as a pointer and truncate it, so recover the high bits.  */
+	movl (JB_RBP*8 + 4)(%rdi), %eax
+	shlq $32, %rax
+	orq %rax, %r9
+# endif
+#endif
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl $(1 << 1), %fs:FEATURE_1_OFFSET
+	jz .Lnoadj
+# endif
+	/* Check and adjust the Shadow-Stack-Pointer.  */
+	xorl %eax, %eax
+	/* Get the current ssp.  */
+	rdsspq %rax
+	/* And compare it with the saved ssp value.  */
+	subq SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
+	je .Lnoadj
+	/* Count the number of frames to adjust and adjust it
+	   with incssp instruction.  The instruction can adjust
+	   the ssp by [0..255] value only thus use a loop if
+	   the number of frames is bigger than 255.  */
+	negq %rax
+	shrq $3, %rax
+	/* NB: We saved Shadow-Stack-Pointer of setjmp.  Since we are
+	       restoring Shadow-Stack-Pointer of setjmp's caller, we
+	       need to unwind shadow stack by one more frame.  */
+	addq $1, %rax
+	cmpq $255, %rax
+	jbe .Lonetime
+.Loopadj:
+	incsspq %rax
+	subq $255, %rax
+	cmpq $255, %rax
+	ja .Loopadj
+.Lonetime:
+	incsspq %rax
+.Lnoadj:
+#endif
+	LIBC_PROBE (longjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RDX_LP)
+	/* We add unwind information for the target here.  */
+	cfi_def_cfa(%rdi, 0)
+	cfi_register(%rsp,%r8)
+	cfi_register(%rbp,%r9)
+	cfi_register(%rip,%rdx)
+	cfi_offset(%rbx,JB_RBX*8)
+	cfi_offset(%r12,JB_R12*8)
+	cfi_offset(%r13,JB_R13*8)
+	cfi_offset(%r14,JB_R14*8)
+	cfi_offset(%r15,JB_R15*8)
+	movq (JB_RBX*8)(%rdi),%rbx
+	movq (JB_R12*8)(%rdi),%r12
+	movq (JB_R13*8)(%rdi),%r13
+	movq (JB_R14*8)(%rdi),%r14
+	movq (JB_R15*8)(%rdi),%r15
+	/* Set return value for setjmp.  */
+	mov %esi, %eax
+	mov %R8_LP,%RSP_LP
+	movq %r9,%rbp
+	LIBC_PROBE (longjmp_target, 3,
+		    LP_SIZE@%RDI_LP, -4@%eax, LP_SIZE@%RDX_LP)
+	jmpq *%rdx
+END (__longjmp)
diff --git a/sysdeps/unix/sysv/linux/x86_64/setjmp.S b/sysdeps/unix/sysv/linux/x86_64/setjmp.S
new file mode 100644
index 0000000000..0f03d23bb8
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/setjmp.S
@@ -0,0 +1,82 @@ 
+/* setjmp for Linux/x86-64 with shadow stack support.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <jmp_buf-ssp.h>
+#include <asm-syntax.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+ENTRY (__sigsetjmp)
+	/* Save registers.  */
+	movq %rbx, (JB_RBX*8)(%rdi)
+#ifdef PTR_MANGLE
+# ifdef __ILP32__
+	/* Save the high bits of %rbp first, since PTR_MANGLE will
+	   only handle the low bits but we cannot presume %rbp is
+	   being used as a pointer and truncate it.  Here we write all
+	   of %rbp, but the low bits will be overwritten below.  */
+	movq %rbp, (JB_RBP*8)(%rdi)
+# endif
+	mov %RBP_LP, %RAX_LP
+	PTR_MANGLE (%RAX_LP)
+	mov %RAX_LP, (JB_RBP*8)(%rdi)
+#else
+	movq %rbp, (JB_RBP*8)(%rdi)
+#endif
+	movq %r12, (JB_R12*8)(%rdi)
+	movq %r13, (JB_R13*8)(%rdi)
+	movq %r14, (JB_R14*8)(%rdi)
+	movq %r15, (JB_R15*8)(%rdi)
+	lea 8(%rsp), %RDX_LP	/* Save SP as it will be after we return.  */
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%RDX_LP)
+#endif
+	movq %rdx, (JB_RSP*8)(%rdi)
+	mov (%rsp), %RAX_LP	/* Save PC we are returning to now.  */
+	LIBC_PROBE (setjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RAX_LP)
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%RAX_LP)
+#endif
+	movq %rax, (JB_PC*8)(%rdi)
+
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+	/* Check if Shadow Stack is enabled.  */
+	testl $(1 << 1), %fs:FEATURE_1_OFFSET
+	jz .Lskip_ssp
+# endif
+	/* Get the current Shadow-Stack-Pointer and save it.  */
+	xorl %eax, %eax
+	rdsspq %rax
+	movq %rax, SHADOW_STACK_POINTER_OFFSET(%rdi)
+# if IS_IN (libc) && defined SHARED
+.Lskip_ssp:
+# endif
+#endif
+#if IS_IN (rtld)
+	/* In ld.so we never save the signal mask.  */
+	xorl %eax, %eax
+	retq
+#else
+	/* Make a tail call to __sigjmp_save; it takes the same args.  */
+	jmp __sigjmp_save
+#endif
+END (__sigsetjmp)
+hidden_def (__sigsetjmp)