aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2020-02-10 07:58:45 -0800
committerH.J. Lu <hjl.tools@gmail.com>2020-02-10 07:59:10 -0800
commitbf6465d0461234ccd45ae34d5e2375a0bee0081d (patch)
tree71a56036daba549bcf0290f3780a4b27a1304c37 /gcc
parent1cad5e89a9e1b4ffa47bc6e3551643b342f6cfe8 (diff)
downloadgcc-bf6465d0461234ccd45ae34d5e2375a0bee0081d.zip
gcc-bf6465d0461234ccd45ae34d5e2375a0bee0081d.tar.gz
gcc-bf6465d0461234ccd45ae34d5e2375a0bee0081d.tar.bz2
i386: Properly pop restore token in signal frame
Linux CET kernel places a restore token on shadow stack for signal handler to enhance security. The restore token is 8 byte and aligned to 8 bytes. It is usually transparent to user programs since kernel will pop the restore token when signal handler returns. But when an exception is thrown from a signal handler, now we need to pop the restore token from shadow stack. For x86-64, we just need to treat the signal frame as normal frame. For i386, we need to search for the restore token to check if the original shadow stack is 8 byte aligned. If the original shadow stack is 8 byte aligned, we just need to pop 2 slots, one restore token, from shadow stack. Otherwise, we need to pop 3 slots, one restore token + 4 byte padding, from shadow stack. This patch also includes 2 tests, one has a restore token with 4 byte padding and one without. Tested on Linux/x86-64 CET machine with and without -m32. libgcc/ PR libgcc/85334 * config/i386/shadow-stack-unwind.h (_Unwind_Frames_Increment): New. gcc/testsuite/ PR libgcc/85334 * g++.target/i386/pr85334-1.C: New test. * g++.target/i386/pr85334-2.C: Likewise.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.target/i386/pr85334-1.C55
-rw-r--r--gcc/testsuite/g++.target/i386/pr85334-2.C48
4 files changed, 115 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 60bd347..e416516 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2020-02-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR libgcc/85334
+ * config/i386/shadow-stack-unwind.h (_Unwind_Frames_Increment):
+ New.
+
2020-02-10 Richard Earnshaw <rearnsha@arm.com>
PR target/91913
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b3966ec..64835ff 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2020-02-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR libgcc/85334
+ * g++.target/i386/pr85334-1.C: New test.
+ * g++.target/i386/pr85334-2.C: Likewise.
+
2020-02-10 Jakub Jelinek <jakub@redhat.com>
PR other/93641
diff --git a/gcc/testsuite/g++.target/i386/pr85334-1.C b/gcc/testsuite/g++.target/i386/pr85334-1.C
new file mode 100644
index 0000000..3c5ccad
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr85334-1.C
@@ -0,0 +1,55 @@
+// { dg-do run }
+// { dg-require-effective-target cet }
+// { dg-additional-options "-fexceptions -fnon-call-exceptions -fcf-protection" }
+
+// Delta between numbers of call stacks of pr85334-1.C and pr85334-2.C is 1.
+
+#include <signal.h>
+#include <stdlib.h>
+
+void sighandler (int signo, siginfo_t * si, void * uc)
+{
+ throw (5);
+}
+
+char *
+__attribute ((noinline, noclone))
+dosegv ()
+{
+ * ((volatile int *)0) = 12;
+ return 0;
+}
+
+int
+__attribute ((noinline, noclone))
+func2 ()
+{
+ try {
+ dosegv ();
+ }
+ catch (int x) {
+ return (x != 5);
+ }
+ return 1;
+}
+
+int
+__attribute ((noinline, noclone))
+func1 ()
+{
+ return func2 ();
+}
+
+int main ()
+{
+ struct sigaction sa;
+ int status;
+
+ sa.sa_sigaction = sighandler;
+ sa.sa_flags = SA_SIGINFO;
+
+ status = sigaction (SIGSEGV, & sa, NULL);
+ status = sigaction (SIGBUS, & sa, NULL);
+
+ return func1 ();
+}
diff --git a/gcc/testsuite/g++.target/i386/pr85334-2.C b/gcc/testsuite/g++.target/i386/pr85334-2.C
new file mode 100644
index 0000000..e2b5afe
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr85334-2.C
@@ -0,0 +1,48 @@
+// { dg-do run }
+// { dg-require-effective-target cet }
+// { dg-additional-options "-fexceptions -fnon-call-exceptions -fcf-protection" }
+
+// Delta between numbers of call stacks of pr85334-1.C and pr85334-2.C is 1.
+
+#include <signal.h>
+#include <stdlib.h>
+
+void sighandler (int signo, siginfo_t * si, void * uc)
+{
+ throw (5);
+}
+
+char *
+__attribute ((noinline, noclone))
+dosegv ()
+{
+ * ((volatile int *)0) = 12;
+ return 0;
+}
+
+int
+__attribute ((noinline, noclone))
+func1 ()
+{
+ try {
+ dosegv ();
+ }
+ catch (int x) {
+ return (x != 5);
+ }
+ return 1;
+}
+
+int main ()
+{
+ struct sigaction sa;
+ int status;
+
+ sa.sa_sigaction = sighandler;
+ sa.sa_flags = SA_SIGINFO;
+
+ status = sigaction (SIGSEGV, & sa, NULL);
+ status = sigaction (SIGBUS, & sa, NULL);
+
+ return func1 ();
+}