@@ -18,14 +18,57 @@
#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 !defined __CET__ || (__CET__ & 2) == 0 || 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 $(1 << 1), %gs:FEATURE_1_OFFSET
+ jz .Lnoadj
+# 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 .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. */
@@ -56,6 +99,41 @@ 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 $(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
+ movl $255, %ebx
+.Loopadj:
+ incsspd %ebx
+ 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)
@@ -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 !defined __CET__ || (__CET__ & 2) == 0
+# 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 $(1 << 1), %gs:FEATURE_1_OFFSET
+ jz .Lskip_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
+.Lskip_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 !defined __CET__ || (__CET__ & 2) == 0
+# 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 $(1 << 1), %gs:FEATURE_1_OFFSET
+ jz .Lskip_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
+.Lskip_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 !defined __CET__ || (__CET__ & 2) == 0
+# 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 $(1 << 1), %gs:FEATURE_1_OFFSET
+ jz .Lskip_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
+.Lskip_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 !defined __CET__ || (__CET__ & 2) == 0
+# undef SHADOW_STACK_POINTER_OFFSET
+#endif
.section .rodata.str1.1,"aMS",@progbits,1
.type longjmp_msg,@object
@@ -46,6 +51,41 @@ 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 $(1 << 1), %gs:FEATURE_1_OFFSET
+ jz .Lnoadj
+# 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 .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
+ movl $255, %ebx
+.Loopadj:
+ incsspd %ebx
+ 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. */
@@ -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 !defined __CET__ || (__CET__ & 2) == 0
+# 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,41 @@ 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 $(1 << 1), %fs:FEATURE_1_OFFSET
+ jz .Lnoadj
+# 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 .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
+ movl $255, %ebx
+.Loopadj:
+ incsspq %rbx
+ 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)
@@ -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 !defined __CET__ || (__CET__ & 2) == 0 || 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,42 @@ 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 $(1 << 1), %fs:FEATURE_1_OFFSET
+ jz .Lnoadj
+# 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 .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
+ movl $255, %ebx
+.Loopadj:
+ incsspq %rbx
+ 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. */
@@ -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 !defined __CET__ || (__CET__ & 2) == 0
+# 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 $(1 << 1), %fs:FEATURE_1_OFFSET
+ jz .Lskip_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
+.Lskip_ssp:
+# endif
+#endif
#if IS_IN (rtld)
/* In ld.so we never save the signal mask. */
xorl %eax, %eax