summaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S')
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S38
1 files changed, 38 insertions, 0 deletions
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)