V2: [PATCH 02/24] x86: Support shadow stack pointer in setjmp/longjmp
Commit Message
On Thu, Jul 12, 2018 at 02:13:21PM -0400, Carlos O'Donell wrote:
> On 06/13/2018 11:31 AM, H.J. Lu wrote:
> > 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 comment can't be accurate. For the older smaller cancel_jmp_buf
> we found another way to solve this because you just don't restore the
> shadowstack since we're jumping out through the unwinder. So we only
> need this logically for setjmp/longjmp and *context functions?
>
> In general this is OK, I'd like to see a v2:
>
> - New accurate commit message.
> - Replace (1 << 1) with meaningful macro constants that help a future
> reader identify which FEATURE_1 flag we're looking at.
>
Done.
...
> >
> > +# ifdef SHADOW_STACK_POINTER_OFFSET
> > +# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
> > + /* Check if Shadow Stack is enabled. */
> > + testl $(1 << 1), %gs:FEATURE_1_OFFSET
>
> Please replace all instances of "1" here with some kind of macro
> that actually defines which flag we're checking.
>
I updated [PATCH 01/24] to add X86_FEATURE_1_IBT and X86_FEATURE_1_SHSTK
in
https://sourceware.org/ml/libc-alpha/2018-07/msg00375.html
Here is the V2 patch. OK for master?
Thanks.
H.J.
----
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.
2017-12-07 Igor Tsimbalist <igor.v.tsimbalist@intel.com>
H.J. Lu <hongjiu.lu@intel.com>
* sysdeps/i386/__longjmp.S: Include <jmp_buf-ssp.h>.
(__longjmp): Restore shadow stack pointer if shadow stack is
enabled, SHADOW_STACK_POINTER_OFFSET is defined and __longjmp
isn't defined for __longjmp_cancel.
* sysdeps/i386/bsd-_setjmp.S: Include <jmp_buf-ssp.h>.
(_setjmp): Save shadow stack pointer if shadow stack is enabled
and SHADOW_STACK_POINTER_OFFSET is defined.
* sysdeps/i386/bsd-setjmp.S: Include <jmp_buf-ssp.h>.
(setjmp): Save shadow stack pointer if shadow stack is enabled
and SHADOW_STACK_POINTER_OFFSET is defined.
* sysdeps/i386/setjmp.S: Include <jmp_buf-ssp.h>.
(__sigsetjmp): Save shadow stack pointer if shadow stack is
enabled and SHADOW_STACK_POINTER_OFFSET is defined.
* sysdeps/unix/sysv/linux/i386/____longjmp_chk.S: Include
<jmp_buf-ssp.h>.
(____longjmp_chk): Restore shadow stack pointer if shadow stack
is enabled and SHADOW_STACK_POINTER_OFFSET is defined.
* sysdeps/unix/sysv/linux/x86/Makefile (gen-as-const-headers):
Remove jmp_buf-ssp.sym.
* sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S: Include
<jmp_buf-ssp.h>.
(____longjmp_chk): Restore shadow stack pointer if shadow stack
is enabled and SHADOW_STACK_POINTER_OFFSET is defined.
* sysdeps/x86/Makefile (gen-as-const-headers): Add
jmp_buf-ssp.sym.
* sysdeps/x86/jmp_buf-ssp.sym: New dummy file.
* sysdeps/x86_64/__longjmp.S: Include <jmp_buf-ssp.h>.
(__longjmp): Restore shadow stack pointer if shadow stack is
enabled, SHADOW_STACK_POINTER_OFFSET is defined and __longjmp
isn't defined for __longjmp_cancel.
* sysdeps/x86_64/setjmp.S: Include <jmp_buf-ssp.h>.
(__sigsetjmp): Save shadow stack pointer if shadow stack is
enabled and SHADOW_STACK_POINTER_OFFSET is defined.
---
sysdeps/i386/__longjmp.S | 73 +++++++++++++++++++
sysdeps/i386/bsd-_setjmp.S | 21 ++++++
sysdeps/i386/bsd-setjmp.S | 21 ++++++
sysdeps/i386/setjmp.S | 21 ++++++
.../unix/sysv/linux/i386/____longjmp_chk.S | 37 ++++++++++
sysdeps/unix/sysv/linux/x86/Makefile | 1 -
.../unix/sysv/linux/x86_64/____longjmp_chk.S | 38 ++++++++++
sysdeps/x86/Makefile | 1 +
sysdeps/x86/jmp_buf-ssp.sym | 1 +
sysdeps/x86_64/__longjmp.S | 44 +++++++++++
sysdeps/x86_64/setjmp.S | 21 ++++++
11 files changed, 278 insertions(+), 1 deletion(-)
create mode 100644 sysdeps/x86/jmp_buf-ssp.sym
Comments
On 07/13/2018 09:22 AM, H.J. Lu wrote:
> On Thu, Jul 12, 2018 at 02:13:21PM -0400, Carlos O'Donell wrote:
>> On 06/13/2018 11:31 AM, H.J. Lu wrote:
>>> 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 comment can't be accurate. For the older smaller cancel_jmp_buf
>> we found another way to solve this because you just don't restore the
>> shadowstack since we're jumping out through the unwinder. So we only
>> need this logically for setjmp/longjmp and *context functions?
>>
>> In general this is OK, I'd like to see a v2:
>>
>> - New accurate commit message.
>> - Replace (1 << 1) with meaningful macro constants that help a future
>> reader identify which FEATURE_1 flag we're looking at.
>>
>
> Done.
>
> ...
>>>
>>> +# ifdef SHADOW_STACK_POINTER_OFFSET
>>> +# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
>>> + /* Check if Shadow Stack is enabled. */
>>> + testl $(1 << 1), %gs:FEATURE_1_OFFSET
>>
>> Please replace all instances of "1" here with some kind of macro
>> that actually defines which flag we're checking.
>>
>
> I updated [PATCH 01/24] to add X86_FEATURE_1_IBT and X86_FEATURE_1_SHSTK
> in
>
> https://sourceware.org/ml/libc-alpha/2018-07/msg00375.html
>
> Here is the V2 patch. OK for master?
This is OK for master and 2.28.
Thanks for the update and cleanups.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
>
> H.J.
> ----
> 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.
>
> 2017-12-07 Igor Tsimbalist <igor.v.tsimbalist@intel.com>
> H.J. Lu <hongjiu.lu@intel.com>
>
> * sysdeps/i386/__longjmp.S: Include <jmp_buf-ssp.h>.
> (__longjmp): Restore shadow stack pointer if shadow stack is
> enabled, SHADOW_STACK_POINTER_OFFSET is defined and __longjmp
> isn't defined for __longjmp_cancel.
> * sysdeps/i386/bsd-_setjmp.S: Include <jmp_buf-ssp.h>.
> (_setjmp): Save shadow stack pointer if shadow stack is enabled
> and SHADOW_STACK_POINTER_OFFSET is defined.
> * sysdeps/i386/bsd-setjmp.S: Include <jmp_buf-ssp.h>.
> (setjmp): Save shadow stack pointer if shadow stack is enabled
> and SHADOW_STACK_POINTER_OFFSET is defined.
> * sysdeps/i386/setjmp.S: Include <jmp_buf-ssp.h>.
> (__sigsetjmp): Save shadow stack pointer if shadow stack is
> enabled and SHADOW_STACK_POINTER_OFFSET is defined.
> * sysdeps/unix/sysv/linux/i386/____longjmp_chk.S: Include
> <jmp_buf-ssp.h>.
> (____longjmp_chk): Restore shadow stack pointer if shadow stack
> is enabled and SHADOW_STACK_POINTER_OFFSET is defined.
> * sysdeps/unix/sysv/linux/x86/Makefile (gen-as-const-headers):
> Remove jmp_buf-ssp.sym.
> * sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S: Include
> <jmp_buf-ssp.h>.
> (____longjmp_chk): Restore shadow stack pointer if shadow stack
> is enabled and SHADOW_STACK_POINTER_OFFSET is defined.
> * sysdeps/x86/Makefile (gen-as-const-headers): Add
> jmp_buf-ssp.sym.
> * sysdeps/x86/jmp_buf-ssp.sym: New dummy file.
> * sysdeps/x86_64/__longjmp.S: Include <jmp_buf-ssp.h>.
> (__longjmp): Restore shadow stack pointer if shadow stack is
> enabled, SHADOW_STACK_POINTER_OFFSET is defined and __longjmp
> isn't defined for __longjmp_cancel.
> * sysdeps/x86_64/setjmp.S: Include <jmp_buf-ssp.h>.
> (__sigsetjmp): Save shadow stack pointer if shadow stack is
> enabled and SHADOW_STACK_POINTER_OFFSET is defined.
> ---
> sysdeps/i386/__longjmp.S | 73 +++++++++++++++++++
> sysdeps/i386/bsd-_setjmp.S | 21 ++++++
> sysdeps/i386/bsd-setjmp.S | 21 ++++++
> sysdeps/i386/setjmp.S | 21 ++++++
> .../unix/sysv/linux/i386/____longjmp_chk.S | 37 ++++++++++
> sysdeps/unix/sysv/linux/x86/Makefile | 1 -
> .../unix/sysv/linux/x86_64/____longjmp_chk.S | 38 ++++++++++
> sysdeps/x86/Makefile | 1 +
> sysdeps/x86/jmp_buf-ssp.sym | 1 +
> sysdeps/x86_64/__longjmp.S | 44 +++++++++++
> sysdeps/x86_64/setjmp.S | 21 ++++++
> 11 files changed, 278 insertions(+), 1 deletion(-)
> create mode 100644 sysdeps/x86/jmp_buf-ssp.sym
>
> diff --git a/sysdeps/i386/__longjmp.S b/sysdeps/i386/__longjmp.S
> index b38333bead..6e98ed538d 100644
> --- a/sysdeps/i386/__longjmp.S
> +++ b/sysdeps/i386/__longjmp.S
> @@ -18,14 +18,55 @@
>
> #include <sysdep.h>
> #include <jmpbuf-offsets.h>
> +#include <jmp_buf-ssp.h>
> #include <asm-syntax.h>
> #include <stap-probe.h>
>
> +/* Don't restore shadow stack register if
> + 1. Shadow stack isn't enabled. Or
> + 2. __longjmp is defined for __longjmp_cancel.
> + */
> +#if !SHSTK_ENABLED || defined __longjmp
> +# undef SHADOW_STACK_POINTER_OFFSET
> +#endif
> +
> .text
> ENTRY (__longjmp)
> #ifdef PTR_DEMANGLE
> movl 4(%esp), %eax /* User's jmp_buf in %eax. */
>
> +# ifdef SHADOW_STACK_POINTER_OFFSET
> +# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
> + /* Check if Shadow Stack is enabled. */
> + testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
> + jz L(skip_ssp)
> +# else
> + xorl %edx, %edx
> +# endif
> + /* Check and adjust the Shadow-Stack-Pointer. */
> + rdsspd %edx
> + /* And compare it with the saved ssp value. */
> + subl SHADOW_STACK_POINTER_OFFSET(%eax), %edx
> + je L(skip_ssp)
> + /* 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
> + movl $255, %ebx
> +L(loop):
> + cmpl %ebx, %edx
> + cmovb %edx, %ebx
> + incsspd %ebx
> + subl %ebx, %edx
> + ja L(loop)
> +L(skip_ssp):
> +# endif
> /* Save the return address now. */
> movl (JB_PC*4)(%eax), %edx
> /* Get the stack pointer. */
> @@ -56,6 +97,38 @@ ENTRY (__longjmp)
> #else
> movl 4(%esp), %ecx /* User's jmp_buf in %ecx. */
> movl 8(%esp), %eax /* Second argument is return value. */
> +# ifdef SHADOW_STACK_POINTER_OFFSET
> +# if IS_IN (libc) && defined SHARED
> + /* Check if Shadow Stack is enabled. */
> + testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
> + jz L(skip_ssp)
> +# 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 L(skip_ssp)
> + /* 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
> + movl $255, %ebx
> +L(loop):
> + cmpl %ebx, %edx
> + cmovb %edx, %ebx
> + incsspd %ebx
> + subl %ebx, %edx
> + ja L(loop)
> +L(skip_ssp):
> +# endif
> /* Save the return address now. */
> movl (JB_PC*4)(%ecx), %edx
> LIBC_PROBE (longjmp, 3, 4@%ecx, -4@%eax, 4@%edx)
> diff --git a/sysdeps/i386/bsd-_setjmp.S b/sysdeps/i386/bsd-_setjmp.S
> index a626cc6d22..db47df0ba1 100644
> --- a/sysdeps/i386/bsd-_setjmp.S
> +++ b/sysdeps/i386/bsd-_setjmp.S
> @@ -22,12 +22,18 @@
>
> #include <sysdep.h>
> #include <jmpbuf-offsets.h>
> +#include <jmp_buf-ssp.h>
> #include <stap-probe.h>
>
> #define PARMS 4 /* no space for saved regs */
> #define JMPBUF PARMS
> #define SIGMSK JMPBUF+4
>
> +/* Don't save shadow stack register if shadow stack isn't enabled. */
> +#if !SHSTK_ENABLED
> +# undef SHADOW_STACK_POINTER_OFFSET
> +#endif
> +
> ENTRY (_setjmp)
>
> xorl %eax, %eax
> @@ -51,6 +57,21 @@ ENTRY (_setjmp)
> movl %ebp, (JB_BP*4)(%edx) /* Save caller's frame pointer. */
>
> movl %eax, JB_SIZE(%edx) /* No signal mask set. */
> +#ifdef SHADOW_STACK_POINTER_OFFSET
> +# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
> + /* Check if Shadow Stack is enabled. */
> + testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
> + jz L(skip_ssp)
> +# else
> + xorl %ecx, %ecx
> +# endif
> + /* Get the current Shadow-Stack-Pointer and save it. */
> + rdsspd %ecx
> + movl %ecx, SHADOW_STACK_POINTER_OFFSET(%edx)
> +# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
> +L(skip_ssp):
> +# endif
> +#endif
> ret
> END (_setjmp)
> libc_hidden_def (_setjmp)
> diff --git a/sysdeps/i386/bsd-setjmp.S b/sysdeps/i386/bsd-setjmp.S
> index 2da8b73c49..1290d0d82b 100644
> --- a/sysdeps/i386/bsd-setjmp.S
> +++ b/sysdeps/i386/bsd-setjmp.S
> @@ -22,12 +22,18 @@
>
> #include <sysdep.h>
> #include <jmpbuf-offsets.h>
> +#include <jmp_buf-ssp.h>
> #include <stap-probe.h>
>
> #define PARMS 4 /* no space for saved regs */
> #define JMPBUF PARMS
> #define SIGMSK JMPBUF+4
>
> +/* Don't save shadow stack register if shadow stack isn't enabled. */
> +#if !SHSTK_ENABLED
> +# undef SHADOW_STACK_POINTER_OFFSET
> +#endif
> +
> 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
> @@ -51,6 +57,21 @@ ENTRY (setjmp)
> #endif
> movl %ecx, (JB_PC*4)(%eax)
> movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer. */
> +#ifdef SHADOW_STACK_POINTER_OFFSET
> +# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
> + /* Check if Shadow Stack is enabled. */
> + testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
> + jz L(skip_ssp)
> +# else
> + xorl %ecx, %ecx
> +# endif
> + /* Get the current Shadow-Stack-Pointer and save it. */
> + rdsspd %ecx
> + movl %ecx, SHADOW_STACK_POINTER_OFFSET(%eax)
> +# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
> +L(skip_ssp):
> +# endif
> +#endif
>
> /* Call __sigjmp_save. */
> pushl $1
> diff --git a/sysdeps/i386/setjmp.S b/sysdeps/i386/setjmp.S
> index 6a08701717..889337b8ae 100644
> --- a/sysdeps/i386/setjmp.S
> +++ b/sysdeps/i386/setjmp.S
> @@ -18,6 +18,7 @@
>
> #include <sysdep.h>
> #include <jmpbuf-offsets.h>
> +#include <jmp_buf-ssp.h>
> #include <asm-syntax.h>
> #include <stap-probe.h>
>
> @@ -25,6 +26,11 @@
> #define JMPBUF PARMS
> #define SIGMSK JMPBUF+4
>
> +/* Don't save shadow stack register if shadow stack isn't enabled. */
> +#if !SHSTK_ENABLED
> +# undef SHADOW_STACK_POINTER_OFFSET
> +#endif
> +
> ENTRY (__sigsetjmp)
>
> movl JMPBUF(%esp), %eax
> @@ -46,6 +52,21 @@ ENTRY (__sigsetjmp)
> movl %ecx, (JB_PC*4)(%eax)
> movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer. */
>
> +#ifdef SHADOW_STACK_POINTER_OFFSET
> +# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
> + /* Check if Shadow Stack is enabled. */
> + testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
> + jz L(skip_ssp)
> +# else
> + xorl %ecx, %ecx
> +# endif
> + /* Get the current Shadow-Stack-Pointer and save it. */
> + rdsspd %ecx
> + movl %ecx, SHADOW_STACK_POINTER_OFFSET(%eax)
> +# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
> +L(skip_ssp):
> +# endif
> +#endif
> #if IS_IN (rtld)
> /* In ld.so we never save the signal mask. */
> xorl %eax, %eax
> diff --git a/sysdeps/unix/sysv/linux/i386/____longjmp_chk.S b/sysdeps/unix/sysv/linux/i386/____longjmp_chk.S
> index 3452433112..a7640d9892 100644
> --- a/sysdeps/unix/sysv/linux/i386/____longjmp_chk.S
> +++ b/sysdeps/unix/sysv/linux/i386/____longjmp_chk.S
> @@ -17,9 +17,14 @@
>
> #include <sysdep.h>
> #include <jmpbuf-offsets.h>
> +#include <jmp_buf-ssp.h>
> #include <asm-syntax.h>
> #include <stap-probe.h>
>
> +/* Don't restore shadow stack register if shadow stack isn't enabled. */
> +#if !SHSTK_ENABLED
> +# undef SHADOW_STACK_POINTER_OFFSET
> +#endif
>
> .section .rodata.str1.1,"aMS",@progbits,1
> .type longjmp_msg,@object
> @@ -46,6 +51,38 @@ longjmp_msg:
> ENTRY (____longjmp_chk)
> movl 4(%esp), %ecx /* User's jmp_buf in %ecx. */
>
> +#ifdef SHADOW_STACK_POINTER_OFFSET
> +# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
> + /* Check if Shadow Stack is enabled. */
> + testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
> + jz L(skip_ssp)
> +# else
> + xorl %edx, %edx
> +# endif
> + /* Check and adjust the Shadow-Stack-Pointer. */
> + rdsspd %edx
> + /* And compare it with the saved ssp value. */
> + subl SHADOW_STACK_POINTER_OFFSET(%ecx), %edx
> + je L(skip_ssp)
> + /* 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
> + movl $255, %ebx
> +L(loop):
> + cmpl %ebx, %edx
> + cmovb %edx, %ebx
> + incsspd %ebx
> + subl %ebx, %edx
> + ja L(loop)
> +L(skip_ssp):
> +#endif
> /* Save the return address now. */
> movl (JB_PC*4)(%ecx), %edx
> /* Get the stack pointer. */
> diff --git a/sysdeps/unix/sysv/linux/x86/Makefile b/sysdeps/unix/sysv/linux/x86/Makefile
> index c55a43e58d..111ff9ff58 100644
> --- a/sysdeps/unix/sysv/linux/x86/Makefile
> +++ b/sysdeps/unix/sysv/linux/x86/Makefile
> @@ -21,6 +21,5 @@ sysdep_routines += dl-vdso
> endif
>
> ifeq ($(subdir),setjmp)
> -gen-as-const-headers += jmp_buf-ssp.sym
> tests += tst-saved_mask-1
> endif
> diff --git a/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S b/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
> index 8a9f2e1a3c..7eb26fafca 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
> +++ b/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
> @@ -20,7 +20,13 @@
> #include <asm-syntax.h>
> #include <stap-probe.h>
>
> +/* Don't restore shadow stack register if shadow stack isn't enabled. */
> +#if !SHSTK_ENABLED
> +# undef SHADOW_STACK_POINTER_OFFSET
> +#endif
> +
> #include <sigaltstack-offsets.h>
> +#include <jmp_buf-ssp.h>
>
> .section .rodata.str1.1,"aMS",@progbits,1
> .type longjmp_msg,@object
> @@ -105,6 +111,38 @@ ENTRY(____longjmp_chk)
> cfi_restore (%rsi)
>
> .Lok:
> +#ifdef SHADOW_STACK_POINTER_OFFSET
> +# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
> + /* Check if Shadow Stack is enabled. */
> + testl $X86_FEATURE_1_SHSTK, %fs:FEATURE_1_OFFSET
> + jz L(skip_ssp)
> +# else
> + xorl %eax, %eax
> +# endif
> + /* Check and adjust the Shadow-Stack-Pointer. */
> + rdsspq %rax
> + /* And compare it with the saved ssp value. */
> + subq SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
> + je L(skip_ssp)
> + /* 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
> + movl $255, %ebx
> +L(loop):
> + cmpq %rbx, %rax
> + cmovb %rax, %rbx
> + incsspq %rbx
> + subq %rbx, %rax
> + ja L(loop)
> +L(skip_ssp):
> +#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/x86/Makefile b/sysdeps/x86/Makefile
> index d25d6f0ae4..65292f4032 100644
> --- a/sysdeps/x86/Makefile
> +++ b/sysdeps/x86/Makefile
> @@ -10,5 +10,6 @@ tests-static += tst-get-cpu-features-static
> endif
>
> ifeq ($(subdir),setjmp)
> +gen-as-const-headers += jmp_buf-ssp.sym
> sysdep_routines += __longjmp_cancel
> endif
> diff --git a/sysdeps/x86/jmp_buf-ssp.sym b/sysdeps/x86/jmp_buf-ssp.sym
> new file mode 100644
> index 0000000000..1aaaedc9ec
> --- /dev/null
> +++ b/sysdeps/x86/jmp_buf-ssp.sym
> @@ -0,0 +1 @@
> +-- FIXME: Define SHADOW_STACK_POINTER_OFFSET to support shadow stack.
> diff --git a/sysdeps/x86_64/__longjmp.S b/sysdeps/x86_64/__longjmp.S
> index a487e0efd0..d7d123e4bc 100644
> --- a/sysdeps/x86_64/__longjmp.S
> +++ b/sysdeps/x86_64/__longjmp.S
> @@ -17,9 +17,18 @@
>
> #include <sysdep.h>
> #include <jmpbuf-offsets.h>
> +#include <jmp_buf-ssp.h>
> #include <asm-syntax.h>
> #include <stap-probe.h>
>
> +/* Don't restore shadow stack register if
> + 1. Shadow stack isn't enabled. Or
> + 2. __longjmp is defined for __longjmp_cancel.
> + */
> +#if !SHSTK_ENABLED || defined __longjmp
> +# undef SHADOW_STACK_POINTER_OFFSET
> +#endif
> +
> /* 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). */
> @@ -41,6 +50,41 @@ ENTRY(__longjmp)
> shlq $32, %rax
> orq %rax, %r9
> # endif
> +#endif
> +#ifdef SHADOW_STACK_POINTER_OFFSET
> +# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
> + /* Check if Shadow Stack is enabled. */
> + testl $X86_FEATURE_1_SHSTK, %fs:FEATURE_1_OFFSET
> + jz L(skip_ssp)
> +# else
> + xorl %eax, %eax
> +# endif
> + /* Check and adjust the Shadow-Stack-Pointer. */
> + /* Get the current ssp. */
> + rdsspq %rax
> + /* And compare it with the saved ssp value. */
> + subq SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
> + je L(skip_ssp)
> + /* 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
> +
> + movl $255, %ebx
> +L(loop):
> + cmpq %rbx, %rax
> + cmovb %rax, %rbx
> + incsspq %rbx
> + subq %rbx, %rax
> + ja L(loop)
> +
> +L(skip_ssp):
> #endif
> LIBC_PROBE (longjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RDX_LP)
> /* We add unwind information for the target here. */
> diff --git a/sysdeps/x86_64/setjmp.S b/sysdeps/x86_64/setjmp.S
> index e0a648e3e4..78a8bf4644 100644
> --- a/sysdeps/x86_64/setjmp.S
> +++ b/sysdeps/x86_64/setjmp.S
> @@ -18,9 +18,15 @@
>
> #include <sysdep.h>
> #include <jmpbuf-offsets.h>
> +#include <jmp_buf-ssp.h>
> #include <asm-syntax.h>
> #include <stap-probe.h>
>
> +/* Don't save shadow stack register if shadow stack isn't enabled. */
> +#if !SHSTK_ENABLED
> +# undef SHADOW_STACK_POINTER_OFFSET
> +#endif
> +
> ENTRY (__sigsetjmp)
> /* Save registers. */
> movq %rbx, (JB_RBX*8)(%rdi)
> @@ -54,6 +60,21 @@ ENTRY (__sigsetjmp)
> #endif
> movq %rax, (JB_PC*8)(%rdi)
>
> +#ifdef SHADOW_STACK_POINTER_OFFSET
> +# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
> + /* Check if Shadow Stack is enabled. */
> + testl $X86_FEATURE_1_SHSTK, %fs:FEATURE_1_OFFSET
> + jz L(skip_ssp)
> +# else
> + xorl %eax, %eax
> +# endif
> + /* Get the current Shadow-Stack-Pointer and save it. */
> + rdsspq %rax
> + movq %rax, SHADOW_STACK_POINTER_OFFSET(%rdi)
> +# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
> +L(skip_ssp):
> +# endif
> +#endif
> #if IS_IN (rtld)
> /* In ld.so we never save the signal mask. */
> xorl %eax, %eax
>
* H. J. Lu:
> + /* Get the current ssp. */
> + rdsspd %edx
This moves the required binutils version past current Debian's 2.28.
I know we recently increased the minimum make version recently, but
binutils 2.28 is still quite new, I think.
Could we list the bytes for the instruction explicitly instead?
On Sat, Jul 14, 2018 at 12:57 PM, Florian Weimer <fw@deneb.enyo.de> wrote:
> * H. J. Lu:
>
>> + /* Get the current ssp. */
>> + rdsspd %edx
>
> This moves the required binutils version past current Debian's 2.28.
>
> I know we recently increased the minimum make version recently, but
> binutils 2.28 is still quite new, I think.
>
> Could we list the bytes for the instruction explicitly instead?
The next patch:
https://sourceware.org/ml/libc-alpha/2018-07/msg00266.html
has sysdeps/x86/configure.ac:
if 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 __CET__ || __CET__ != 3
# error CET isn't available.
#endif
EOF
if AC_TRY_COMMAND(${CC-cc} -c $CFLAGS -fcf-protection -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
fi
LIBC_CONFIG_VAR([enable-cet], [$enable_cet])
You need GCC 8 and binutils with CET to enable CET. If you have an
older binutils or
GCC, you will get a configure error when --enable-cet is used.
* H. J. Lu:
> On Sat, Jul 14, 2018 at 12:57 PM, Florian Weimer <fw@deneb.enyo.de> wrote:
>> * H. J. Lu:
>>
>>> + /* Get the current ssp. */
>>> + rdsspd %edx
>>
>> This moves the required binutils version past current Debian's 2.28.
>>
>> I know we recently increased the minimum make version recently, but
>> binutils 2.28 is still quite new, I think.
>>
>> Could we list the bytes for the instruction explicitly instead?
>
> The next patch:
>
> https://sourceware.org/ml/libc-alpha/2018-07/msg00266.html
>
> has sysdeps/x86/configure.ac:
We currently have this (as of commit
faaee1f07ed25b2779bfd935ffb29f431b80d6d3):
==> sysdeps/unix/sysv/linux/x86/jmp_buf-ssp.sym <==
#include <setjmpP.h>
#undef __saved_mask
--
SHADOW_STACK_POINTER_OFFSET offsetof(struct __jmp_buf_tag, __saved_mask.__saved.__shadow_stack_pointer)
==> sysdeps/x86/jmp_buf-ssp.sym <==
-- FIXME: Define SHADOW_STACK_POINTER_OFFSET to support shadow stack.
So SHADOW_STACK_POINTER_OFFSET is defined unconditionally. I don't
see how the quoted patch changes that.
Making sure that rdssp is only assembled with --enable-cet looks like
the right solution, but you need something like #if ENABLE_CET, and
not depend on SHADOW_STACK_POINTER_OFFSET being defined.
On Sat, Jul 14, 2018 at 4:07 PM, Florian Weimer <fw@deneb.enyo.de> wrote:
> * H. J. Lu:
>
>> On Sat, Jul 14, 2018 at 12:57 PM, Florian Weimer <fw@deneb.enyo.de> wrote:
>>> * H. J. Lu:
>>>
>>>> + /* Get the current ssp. */
>>>> + rdsspd %edx
>>>
>>> This moves the required binutils version past current Debian's 2.28.
>>>
>>> I know we recently increased the minimum make version recently, but
>>> binutils 2.28 is still quite new, I think.
>>>
>>> Could we list the bytes for the instruction explicitly instead?
>>
>> The next patch:
>>
>> https://sourceware.org/ml/libc-alpha/2018-07/msg00266.html
>>
>> has sysdeps/x86/configure.ac:
>
> We currently have this (as of commit
> faaee1f07ed25b2779bfd935ffb29f431b80d6d3):
>
> ==> sysdeps/unix/sysv/linux/x86/jmp_buf-ssp.sym <==
> #include <setjmpP.h>
> #undef __saved_mask
>
> --
> SHADOW_STACK_POINTER_OFFSET offsetof(struct __jmp_buf_tag, __saved_mask.__saved.__shadow_stack_pointer)
>
> ==> sysdeps/x86/jmp_buf-ssp.sym <==
> -- FIXME: Define SHADOW_STACK_POINTER_OFFSET to support shadow stack.
>
> So SHADOW_STACK_POINTER_OFFSET is defined unconditionally. I don't
> see how the quoted patch changes that.
>
> Making sure that rdssp is only assembled with --enable-cet looks like
> the right solution, but you need something like #if ENABLE_CET, and
> not depend on SHADOW_STACK_POINTER_OFFSET being defined.
Take sysdeps/x86_64/setjmp.S as example:
/* Don't save shadow stack register if shadow stack isn't enabled. */
#if !SHSTK_ENABLED
# undef SHADOW_STACK_POINTER_OFFSET
#endif
.....
Shadow stack pointer is saved/restored only if --enable-cet is used to
configure glibc. If you compile glibc with -fcf-protection, but without
configuring glibc with --enable-cet, result is undefined.
On Sat, Jul 14, 2018 at 4:15 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Sat, Jul 14, 2018 at 4:07 PM, Florian Weimer <fw@deneb.enyo.de> wrote:
>> * H. J. Lu:
>>
>>> On Sat, Jul 14, 2018 at 12:57 PM, Florian Weimer <fw@deneb.enyo.de> wrote:
>>>> * H. J. Lu:
>>>>
>>>>> + /* Get the current ssp. */
>>>>> + rdsspd %edx
>>>>
>>>> This moves the required binutils version past current Debian's 2.28.
>>>>
>>>> I know we recently increased the minimum make version recently, but
>>>> binutils 2.28 is still quite new, I think.
>>>>
>>>> Could we list the bytes for the instruction explicitly instead?
>>>
>>> The next patch:
>>>
>>> https://sourceware.org/ml/libc-alpha/2018-07/msg00266.html
>>>
>>> has sysdeps/x86/configure.ac:
>>
>> We currently have this (as of commit
>> faaee1f07ed25b2779bfd935ffb29f431b80d6d3):
>>
>> ==> sysdeps/unix/sysv/linux/x86/jmp_buf-ssp.sym <==
>> #include <setjmpP.h>
>> #undef __saved_mask
>>
>> --
>> SHADOW_STACK_POINTER_OFFSET offsetof(struct __jmp_buf_tag, __saved_mask.__saved.__shadow_stack_pointer)
>>
>> ==> sysdeps/x86/jmp_buf-ssp.sym <==
>> -- FIXME: Define SHADOW_STACK_POINTER_OFFSET to support shadow stack.
>>
>> So SHADOW_STACK_POINTER_OFFSET is defined unconditionally. I don't
>> see how the quoted patch changes that.
>>
>> Making sure that rdssp is only assembled with --enable-cet looks like
>> the right solution, but you need something like #if ENABLE_CET, and
>> not depend on SHADOW_STACK_POINTER_OFFSET being defined.
>
> Take sysdeps/x86_64/setjmp.S as example:
>
> /* Don't save shadow stack register if shadow stack isn't enabled. */
> #if !SHSTK_ENABLED
> # undef SHADOW_STACK_POINTER_OFFSET
> #endif
> .....
>
> Shadow stack pointer is saved/restored only if --enable-cet is used to
> configure glibc. If you compile glibc with -fcf-protection, but without
> configuring glibc with --enable-cet, result is undefined.
>
BTW, it passed build-many-glibcs.py.
* H. J. Lu:
>> We currently have this (as of commit
>> faaee1f07ed25b2779bfd935ffb29f431b80d6d3):
>>
>> ==> sysdeps/unix/sysv/linux/x86/jmp_buf-ssp.sym <==
>> #include <setjmpP.h>
>> #undef __saved_mask
>>
>> --
>> SHADOW_STACK_POINTER_OFFSET offsetof(struct __jmp_buf_tag,
>> __saved_mask.__saved.__shadow_stack_pointer)
>>
>> ==> sysdeps/x86/jmp_buf-ssp.sym <==
>> -- FIXME: Define SHADOW_STACK_POINTER_OFFSET to support shadow stack.
>>
>> So SHADOW_STACK_POINTER_OFFSET is defined unconditionally. I don't
>> see how the quoted patch changes that.
>>
>> Making sure that rdssp is only assembled with --enable-cet looks like
>> the right solution, but you need something like #if ENABLE_CET, and
>> not depend on SHADOW_STACK_POINTER_OFFSET being defined.
>
> Take sysdeps/x86_64/setjmp.S as example:
>
> /* Don't save shadow stack register if shadow stack isn't enabled. */
> #if !SHSTK_ENABLED
> # undef SHADOW_STACK_POINTER_OFFSET
> #endif
> .....
>
> Shadow stack pointer is saved/restored only if --enable-cet is used to
> configure glibc. If you compile glibc with -fcf-protection, but without
> configuring glibc with --enable-cet, result is undefined.
That doesn't work because <jmp_buf-ssp.h> is included after the
#undef. I think you can avoid that by using #if SHTSTK_ENABLED
instead of #ifdef SHADOW_STACK_POINTER_OFFSET, which also expresses
the intent more accurately.
> BTW, it passed build-many-glibcs.py.
With binutils 2.28?
@@ -18,14 +18,55 @@
#include <sysdep.h>
#include <jmpbuf-offsets.h>
+#include <jmp_buf-ssp.h>
#include <asm-syntax.h>
#include <stap-probe.h>
+/* Don't restore shadow stack register if
+ 1. Shadow stack isn't enabled. Or
+ 2. __longjmp is defined for __longjmp_cancel.
+ */
+#if !SHSTK_ENABLED || defined __longjmp
+# undef SHADOW_STACK_POINTER_OFFSET
+#endif
+
.text
ENTRY (__longjmp)
#ifdef PTR_DEMANGLE
movl 4(%esp), %eax /* User's jmp_buf in %eax. */
+# ifdef SHADOW_STACK_POINTER_OFFSET
+# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
+ /* Check if Shadow Stack is enabled. */
+ testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
+ jz L(skip_ssp)
+# else
+ xorl %edx, %edx
+# endif
+ /* Check and adjust the Shadow-Stack-Pointer. */
+ rdsspd %edx
+ /* And compare it with the saved ssp value. */
+ subl SHADOW_STACK_POINTER_OFFSET(%eax), %edx
+ je L(skip_ssp)
+ /* 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
+ movl $255, %ebx
+L(loop):
+ cmpl %ebx, %edx
+ cmovb %edx, %ebx
+ incsspd %ebx
+ subl %ebx, %edx
+ ja L(loop)
+L(skip_ssp):
+# endif
/* Save the return address now. */
movl (JB_PC*4)(%eax), %edx
/* Get the stack pointer. */
@@ -56,6 +97,38 @@ ENTRY (__longjmp)
#else
movl 4(%esp), %ecx /* User's jmp_buf in %ecx. */
movl 8(%esp), %eax /* Second argument is return value. */
+# ifdef SHADOW_STACK_POINTER_OFFSET
+# if IS_IN (libc) && defined SHARED
+ /* Check if Shadow Stack is enabled. */
+ testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
+ jz L(skip_ssp)
+# 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 L(skip_ssp)
+ /* 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
+ movl $255, %ebx
+L(loop):
+ cmpl %ebx, %edx
+ cmovb %edx, %ebx
+ incsspd %ebx
+ subl %ebx, %edx
+ ja L(loop)
+L(skip_ssp):
+# endif
/* Save the return address now. */
movl (JB_PC*4)(%ecx), %edx
LIBC_PROBE (longjmp, 3, 4@%ecx, -4@%eax, 4@%edx)
@@ -22,12 +22,18 @@
#include <sysdep.h>
#include <jmpbuf-offsets.h>
+#include <jmp_buf-ssp.h>
#include <stap-probe.h>
#define PARMS 4 /* no space for saved regs */
#define JMPBUF PARMS
#define SIGMSK JMPBUF+4
+/* Don't save shadow stack register if shadow stack isn't enabled. */
+#if !SHSTK_ENABLED
+# undef SHADOW_STACK_POINTER_OFFSET
+#endif
+
ENTRY (_setjmp)
xorl %eax, %eax
@@ -51,6 +57,21 @@ ENTRY (_setjmp)
movl %ebp, (JB_BP*4)(%edx) /* Save caller's frame pointer. */
movl %eax, JB_SIZE(%edx) /* No signal mask set. */
+#ifdef SHADOW_STACK_POINTER_OFFSET
+# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
+ /* Check if Shadow Stack is enabled. */
+ testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
+ jz L(skip_ssp)
+# else
+ xorl %ecx, %ecx
+# endif
+ /* Get the current Shadow-Stack-Pointer and save it. */
+ rdsspd %ecx
+ movl %ecx, SHADOW_STACK_POINTER_OFFSET(%edx)
+# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
+L(skip_ssp):
+# endif
+#endif
ret
END (_setjmp)
libc_hidden_def (_setjmp)
@@ -22,12 +22,18 @@
#include <sysdep.h>
#include <jmpbuf-offsets.h>
+#include <jmp_buf-ssp.h>
#include <stap-probe.h>
#define PARMS 4 /* no space for saved regs */
#define JMPBUF PARMS
#define SIGMSK JMPBUF+4
+/* Don't save shadow stack register if shadow stack isn't enabled. */
+#if !SHSTK_ENABLED
+# undef SHADOW_STACK_POINTER_OFFSET
+#endif
+
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
@@ -51,6 +57,21 @@ ENTRY (setjmp)
#endif
movl %ecx, (JB_PC*4)(%eax)
movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer. */
+#ifdef SHADOW_STACK_POINTER_OFFSET
+# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
+ /* Check if Shadow Stack is enabled. */
+ testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
+ jz L(skip_ssp)
+# else
+ xorl %ecx, %ecx
+# endif
+ /* Get the current Shadow-Stack-Pointer and save it. */
+ rdsspd %ecx
+ movl %ecx, SHADOW_STACK_POINTER_OFFSET(%eax)
+# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
+L(skip_ssp):
+# endif
+#endif
/* Call __sigjmp_save. */
pushl $1
@@ -18,6 +18,7 @@
#include <sysdep.h>
#include <jmpbuf-offsets.h>
+#include <jmp_buf-ssp.h>
#include <asm-syntax.h>
#include <stap-probe.h>
@@ -25,6 +26,11 @@
#define JMPBUF PARMS
#define SIGMSK JMPBUF+4
+/* Don't save shadow stack register if shadow stack isn't enabled. */
+#if !SHSTK_ENABLED
+# undef SHADOW_STACK_POINTER_OFFSET
+#endif
+
ENTRY (__sigsetjmp)
movl JMPBUF(%esp), %eax
@@ -46,6 +52,21 @@ ENTRY (__sigsetjmp)
movl %ecx, (JB_PC*4)(%eax)
movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer. */
+#ifdef SHADOW_STACK_POINTER_OFFSET
+# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
+ /* Check if Shadow Stack is enabled. */
+ testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
+ jz L(skip_ssp)
+# else
+ xorl %ecx, %ecx
+# endif
+ /* Get the current Shadow-Stack-Pointer and save it. */
+ rdsspd %ecx
+ movl %ecx, SHADOW_STACK_POINTER_OFFSET(%eax)
+# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
+L(skip_ssp):
+# endif
+#endif
#if IS_IN (rtld)
/* In ld.so we never save the signal mask. */
xorl %eax, %eax
@@ -17,9 +17,14 @@
#include <sysdep.h>
#include <jmpbuf-offsets.h>
+#include <jmp_buf-ssp.h>
#include <asm-syntax.h>
#include <stap-probe.h>
+/* Don't restore shadow stack register if shadow stack isn't enabled. */
+#if !SHSTK_ENABLED
+# undef SHADOW_STACK_POINTER_OFFSET
+#endif
.section .rodata.str1.1,"aMS",@progbits,1
.type longjmp_msg,@object
@@ -46,6 +51,38 @@ longjmp_msg:
ENTRY (____longjmp_chk)
movl 4(%esp), %ecx /* User's jmp_buf in %ecx. */
+#ifdef SHADOW_STACK_POINTER_OFFSET
+# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
+ /* Check if Shadow Stack is enabled. */
+ testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
+ jz L(skip_ssp)
+# else
+ xorl %edx, %edx
+# endif
+ /* Check and adjust the Shadow-Stack-Pointer. */
+ rdsspd %edx
+ /* And compare it with the saved ssp value. */
+ subl SHADOW_STACK_POINTER_OFFSET(%ecx), %edx
+ je L(skip_ssp)
+ /* 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
+ movl $255, %ebx
+L(loop):
+ cmpl %ebx, %edx
+ cmovb %edx, %ebx
+ incsspd %ebx
+ subl %ebx, %edx
+ ja L(loop)
+L(skip_ssp):
+#endif
/* Save the return address now. */
movl (JB_PC*4)(%ecx), %edx
/* Get the stack pointer. */
@@ -21,6 +21,5 @@ sysdep_routines += dl-vdso
endif
ifeq ($(subdir),setjmp)
-gen-as-const-headers += jmp_buf-ssp.sym
tests += tst-saved_mask-1
endif
@@ -20,7 +20,13 @@
#include <asm-syntax.h>
#include <stap-probe.h>
+/* Don't restore shadow stack register if shadow stack isn't enabled. */
+#if !SHSTK_ENABLED
+# undef SHADOW_STACK_POINTER_OFFSET
+#endif
+
#include <sigaltstack-offsets.h>
+#include <jmp_buf-ssp.h>
.section .rodata.str1.1,"aMS",@progbits,1
.type longjmp_msg,@object
@@ -105,6 +111,38 @@ ENTRY(____longjmp_chk)
cfi_restore (%rsi)
.Lok:
+#ifdef SHADOW_STACK_POINTER_OFFSET
+# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
+ /* Check if Shadow Stack is enabled. */
+ testl $X86_FEATURE_1_SHSTK, %fs:FEATURE_1_OFFSET
+ jz L(skip_ssp)
+# else
+ xorl %eax, %eax
+# endif
+ /* Check and adjust the Shadow-Stack-Pointer. */
+ rdsspq %rax
+ /* And compare it with the saved ssp value. */
+ subq SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
+ je L(skip_ssp)
+ /* 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
+ movl $255, %ebx
+L(loop):
+ cmpq %rbx, %rax
+ cmovb %rax, %rbx
+ incsspq %rbx
+ subq %rbx, %rax
+ ja L(loop)
+L(skip_ssp):
+#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)
@@ -10,5 +10,6 @@ tests-static += tst-get-cpu-features-static
endif
ifeq ($(subdir),setjmp)
+gen-as-const-headers += jmp_buf-ssp.sym
sysdep_routines += __longjmp_cancel
endif
new file mode 100644
@@ -0,0 +1 @@
+-- FIXME: Define SHADOW_STACK_POINTER_OFFSET to support shadow stack.
@@ -17,9 +17,18 @@
#include <sysdep.h>
#include <jmpbuf-offsets.h>
+#include <jmp_buf-ssp.h>
#include <asm-syntax.h>
#include <stap-probe.h>
+/* Don't restore shadow stack register if
+ 1. Shadow stack isn't enabled. Or
+ 2. __longjmp is defined for __longjmp_cancel.
+ */
+#if !SHSTK_ENABLED || defined __longjmp
+# undef SHADOW_STACK_POINTER_OFFSET
+#endif
+
/* 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). */
@@ -41,6 +50,41 @@ ENTRY(__longjmp)
shlq $32, %rax
orq %rax, %r9
# endif
+#endif
+#ifdef SHADOW_STACK_POINTER_OFFSET
+# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
+ /* Check if Shadow Stack is enabled. */
+ testl $X86_FEATURE_1_SHSTK, %fs:FEATURE_1_OFFSET
+ jz L(skip_ssp)
+# else
+ xorl %eax, %eax
+# endif
+ /* Check and adjust the Shadow-Stack-Pointer. */
+ /* Get the current ssp. */
+ rdsspq %rax
+ /* And compare it with the saved ssp value. */
+ subq SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
+ je L(skip_ssp)
+ /* 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
+
+ movl $255, %ebx
+L(loop):
+ cmpq %rbx, %rax
+ cmovb %rax, %rbx
+ incsspq %rbx
+ subq %rbx, %rax
+ ja L(loop)
+
+L(skip_ssp):
#endif
LIBC_PROBE (longjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RDX_LP)
/* We add unwind information for the target here. */
@@ -18,9 +18,15 @@
#include <sysdep.h>
#include <jmpbuf-offsets.h>
+#include <jmp_buf-ssp.h>
#include <asm-syntax.h>
#include <stap-probe.h>
+/* Don't save shadow stack register if shadow stack isn't enabled. */
+#if !SHSTK_ENABLED
+# undef SHADOW_STACK_POINTER_OFFSET
+#endif
+
ENTRY (__sigsetjmp)
/* Save registers. */
movq %rbx, (JB_RBX*8)(%rdi)
@@ -54,6 +60,21 @@ ENTRY (__sigsetjmp)
#endif
movq %rax, (JB_PC*8)(%rdi)
+#ifdef SHADOW_STACK_POINTER_OFFSET
+# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
+ /* Check if Shadow Stack is enabled. */
+ testl $X86_FEATURE_1_SHSTK, %fs:FEATURE_1_OFFSET
+ jz L(skip_ssp)
+# else
+ xorl %eax, %eax
+# endif
+ /* Get the current Shadow-Stack-Pointer and save it. */
+ rdsspq %rax
+ movq %rax, SHADOW_STACK_POINTER_OFFSET(%rdi)
+# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
+L(skip_ssp):
+# endif
+#endif
#if IS_IN (rtld)
/* In ld.so we never save the signal mask. */
xorl %eax, %eax