forked from rpms/glibc
Shadow stack userspace support
Downstream only and disabled by default.
This commit is contained in:
parent
24deddf0a5
commit
144f612406
71
0001-x86-cet-Don-t-set-CET-active.patch
Normal file
71
0001-x86-cet-Don-t-set-CET-active.patch
Normal file
@ -0,0 +1,71 @@
|
||||
From c35bffd52dceed849fa027d607c0671049ee1428 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Fri, 12 May 2023 13:52:16 -0700
|
||||
Subject: [PATCH] x86/cet: Don't set CET active
|
||||
|
||||
Don't set CET active so that CET is disabled by default. Shadow stack
|
||||
can be enabled by
|
||||
|
||||
$ export GLIBC_TUNABLES=glibc.cpu.hwcaps=SHSTK
|
||||
|
||||
if shadow stack can be enabled by kernel.
|
||||
---
|
||||
sysdeps/x86/cpu-features.c | 2 +-
|
||||
sysdeps/x86/cpu-tunables.c | 17 ++++++++++++++++-
|
||||
2 files changed, 17 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||
index 45bc7fcac3..490a7e38be 100644
|
||||
--- a/sysdeps/x86/cpu-features.c
|
||||
+++ b/sysdeps/x86/cpu-features.c
|
||||
@@ -110,7 +110,7 @@ update_active (struct cpu_features *cpu_features)
|
||||
if (!CPU_FEATURES_CPU_P (cpu_features, RTM_ALWAYS_ABORT))
|
||||
CPU_FEATURE_SET_ACTIVE (cpu_features, RTM);
|
||||
|
||||
-#if CET_ENABLED
|
||||
+#if CET_ENABLED && 0
|
||||
CPU_FEATURE_SET_ACTIVE (cpu_features, IBT);
|
||||
CPU_FEATURE_SET_ACTIVE (cpu_features, SHSTK);
|
||||
#endif
|
||||
diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c
|
||||
index 0d4f328585..eb5d31821b 100644
|
||||
--- a/sysdeps/x86/cpu-tunables.c
|
||||
+++ b/sysdeps/x86/cpu-tunables.c
|
||||
@@ -47,6 +47,18 @@ extern __typeof (memcmp) DEFAULT_MEMCMP;
|
||||
break; \
|
||||
}
|
||||
|
||||
+#define CHECK_GLIBC_IFUNC_CPU_BOTH(f, cpu_features, name, \
|
||||
+ disable, len) \
|
||||
+ _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
|
||||
+ if (!DEFAULT_MEMCMP (f, #name, len)) \
|
||||
+ { \
|
||||
+ if (disable) \
|
||||
+ CPU_FEATURE_UNSET (cpu_features, name) \
|
||||
+ else \
|
||||
+ CPU_FEATURE_SET_ACTIVE (cpu_features, name) \
|
||||
+ break; \
|
||||
+ }
|
||||
+
|
||||
/* Disable a preferred feature NAME. We don't enable a preferred feature
|
||||
which isn't available. */
|
||||
#define CHECK_GLIBC_IFUNC_PREFERRED_OFF(f, cpu_features, name, len) \
|
||||
@@ -162,11 +174,14 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
+ {
|
||||
+ CHECK_GLIBC_IFUNC_CPU_BOTH (n, cpu_features, SHSTK, disable,
|
||||
+ 5);
|
||||
+ }
|
||||
if (disable)
|
||||
{
|
||||
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, LZCNT, 5);
|
||||
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, MOVBE, 5);
|
||||
- CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SHSTK, 5);
|
||||
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SSSE3, 5);
|
||||
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, XSAVE, 5);
|
||||
}
|
||||
--
|
||||
2.40.1
|
||||
|
22
glibc.spec
22
glibc.spec
@ -159,7 +159,7 @@ Version: %{glibcversion}
|
||||
# - It allows using the Release number without the %%dist tag in the dependency
|
||||
# generator to make the generated requires interchangeable between Rawhide
|
||||
# and ELN (.elnYY < .fcXX).
|
||||
%global baserelease 13
|
||||
%global baserelease 14
|
||||
Release: %{baserelease}%{?dist}
|
||||
|
||||
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
||||
@ -232,6 +232,23 @@ Patch17: glibc-cs-path.patch
|
||||
Patch23: glibc-python3.patch
|
||||
Patch24: glibc-disable-werror-tst-realloc.patch
|
||||
|
||||
Patch100: v2-0001-x86-cet-Check-user_shstk-in-proc-cpuinfo.patch
|
||||
Patch101: v2-0002-x86-cet-Update-tst-cet-vfork-1.patch
|
||||
Patch102: v2-0003-x86-cet-Don-t-assume-that-SHSTK-implies-IBT.patch
|
||||
Patch103: v2-0004-x86-cet-Check-legacy-shadow-stack-applications.patch
|
||||
Patch104: v2-0005-x86-cet-Check-CPU_FEATURE_ACTIVE-when-CET-is-disa.patch
|
||||
Patch105: v2-0006-x86-cet-Add-tests-for-GLIBC_TUNABLES-glibc.cpu.hw.patch
|
||||
Patch106: v2-0007-x86-cet-Check-legacy-shadow-stack-code-in-.init_a.patch
|
||||
Patch107: v2-0008-x86-cet-Check-CPU_FEATURE_ACTIVE-in-permissive-mo.patch
|
||||
Patch108: v2-0009-x86-Check-PT_GNU_PROPERTY-early.patch
|
||||
Patch109: v2-0010-x86-Modularize-sysdeps-x86-dl-cet.c.patch
|
||||
Patch110: v2-0011-x86-64-Add-fixup-asm-unistd.h-and-regenerate-arch.patch
|
||||
Patch111: v2-0012-x86-cet-Sync-with-the-kernel-shadow-stack-interfa.patch
|
||||
Patch112: v2-0013-elf-Always-provide-_dl_get_dl_main_map-in-libc.a.patch
|
||||
Patch113: v2-0014-x86-cet-Enable-shadow-stack-during-startup.patch
|
||||
Patch114: v2-0015-x86-cet-Check-feature_1-in-TCB-for-active-IBT-and.patch
|
||||
Patch115: 0001-x86-cet-Don-t-set-CET-active.patch
|
||||
|
||||
##############################################################################
|
||||
# Continued list of core "glibc" package information:
|
||||
##############################################################################
|
||||
@ -2195,6 +2212,9 @@ update_gconv_modules_cache ()
|
||||
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
|
||||
|
||||
%changelog
|
||||
* Thu Jun 08 2023 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.37.9000-14
|
||||
- Shadow stack userspace support, downstream only and disabled by default.
|
||||
|
||||
* Wed Jun 07 2023 Arjun Shankar <arjun@redhat.com> - 2.37.9000-13
|
||||
- Auto-sync with upstream branch master,
|
||||
commit 85e6d8b4175fcb195011a0a1bad37d6f3b2355db:
|
||||
|
27
v2-0001-x86-cet-Check-user_shstk-in-proc-cpuinfo.patch
Normal file
27
v2-0001-x86-cet-Check-user_shstk-in-proc-cpuinfo.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From c94d3234c48c9e8196144bfc150a8f7eee770986 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Wed, 1 Mar 2023 11:26:03 -0800
|
||||
Subject: [PATCH v2 01/15] x86/cet: Check user_shstk in /proc/cpuinfo
|
||||
|
||||
Linux kernel reports CPU shadow stack feature in /proc/cpuinfo as
|
||||
user_shstk, instead of shstk.
|
||||
---
|
||||
sysdeps/x86/tst-cpu-features-cpuinfo.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/sysdeps/x86/tst-cpu-features-cpuinfo.c b/sysdeps/x86/tst-cpu-features-cpuinfo.c
|
||||
index 18d64375ca..1d6c647b70 100644
|
||||
--- a/sysdeps/x86/tst-cpu-features-cpuinfo.c
|
||||
+++ b/sysdeps/x86/tst-cpu-features-cpuinfo.c
|
||||
@@ -246,7 +246,7 @@ do_test (int argc, char **argv)
|
||||
fails += CHECK_PROC (sgx, SGX);
|
||||
fails += CHECK_PROC (sgx_lc, SGX_LC);
|
||||
fails += CHECK_PROC (sha_ni, SHA);
|
||||
- fails += CHECK_PROC (shstk, SHSTK);
|
||||
+ fails += CHECK_PROC (user_shstk, SHSTK);
|
||||
fails += CHECK_PROC (smap, SMAP);
|
||||
fails += CHECK_PROC (smep, SMEP);
|
||||
fails += CHECK_PROC (smx, SMX);
|
||||
--
|
||||
2.40.1
|
||||
|
103
v2-0002-x86-cet-Update-tst-cet-vfork-1.patch
Normal file
103
v2-0002-x86-cet-Update-tst-cet-vfork-1.patch
Normal file
@ -0,0 +1,103 @@
|
||||
From f722c6853035ab390757eb725e0661cf22b9791e Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Sun, 16 Jan 2022 12:09:57 -0800
|
||||
Subject: [PATCH v2 02/15] x86/cet: Update tst-cet-vfork-1
|
||||
|
||||
Change tst-cet-vfork-1.c to verify that vfork child return triggers
|
||||
SIGSEGV due to shadow stack mismatch.
|
||||
---
|
||||
sysdeps/unix/sysv/linux/x86/tst-cet-vfork-1.c | 43 ++++++++-----------
|
||||
1 file changed, 17 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86/tst-cet-vfork-1.c b/sysdeps/unix/sysv/linux/x86/tst-cet-vfork-1.c
|
||||
index 9c4b6f4d42..c92ed9e737 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86/tst-cet-vfork-1.c
|
||||
+++ b/sysdeps/unix/sysv/linux/x86/tst-cet-vfork-1.c
|
||||
@@ -18,34 +18,26 @@
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdio.h>
|
||||
-#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <x86intrin.h>
|
||||
#include <support/test-driver.h>
|
||||
-#include <support/xsignal.h>
|
||||
-#include <support/xunistd.h>
|
||||
|
||||
__attribute__ ((noclone, noinline))
|
||||
static void
|
||||
do_test_1 (void)
|
||||
{
|
||||
pid_t p1;
|
||||
- int fd[2];
|
||||
|
||||
- if (pipe (fd) == -1)
|
||||
- {
|
||||
- puts ("pipe failed");
|
||||
- _exit (EXIT_FAILURE);
|
||||
- }
|
||||
+ /* NB: Since child return pops shadow stack which is shared with
|
||||
+ parent, child must not return after vfork. */
|
||||
|
||||
if ((p1 = vfork ()) == 0)
|
||||
{
|
||||
- pid_t p = getpid ();
|
||||
- TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p)));
|
||||
- /* Child return should trigger SIGSEGV. */
|
||||
+ /* Child return should trigger SIGSEGV due to shadow stack
|
||||
+ mismatch. */
|
||||
return;
|
||||
}
|
||||
else if (p1 == -1)
|
||||
@@ -54,22 +46,22 @@ do_test_1 (void)
|
||||
_exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
- pid_t p2 = 0;
|
||||
- if (TEMP_FAILURE_RETRY (read (fd[0], &p2, sizeof (pid_t)))
|
||||
- != sizeof (pid_t))
|
||||
- puts ("pipd read failed");
|
||||
- else
|
||||
+ int r;
|
||||
+ if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1)
|
||||
{
|
||||
- int r;
|
||||
- if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1)
|
||||
- puts ("waitpid failed");
|
||||
- else if (r != 0)
|
||||
- puts ("pip write in child failed");
|
||||
+ puts ("waitpid failed");
|
||||
+ _exit (EXIT_FAILURE);
|
||||
+ }
|
||||
+
|
||||
+ if (!WIFSIGNALED (r) || WTERMSIG (r) != SIGSEGV)
|
||||
+ {
|
||||
+ puts ("Child not terminated with SIGSEGV");
|
||||
+ _exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Parent exits immediately so that parent returns without triggering
|
||||
- SIGSEGV when shadow stack isn't in use. */
|
||||
- _exit (EXIT_FAILURE);
|
||||
+ SIGSEGV when shadow stack is in use. */
|
||||
+ _exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -80,9 +72,8 @@ do_test (void)
|
||||
return EXIT_UNSUPPORTED;
|
||||
do_test_1 ();
|
||||
/* Child exits immediately so that child returns without triggering
|
||||
- SIGSEGV when shadow stack isn't in use. */
|
||||
+ SIGSEGV when shadow stack is in use. */
|
||||
_exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
-#define EXPECTED_SIGNAL (_get_ssp () == 0 ? 0 : SIGSEGV)
|
||||
#include <support/test-driver.c>
|
||||
--
|
||||
2.40.1
|
||||
|
98
v2-0003-x86-cet-Don-t-assume-that-SHSTK-implies-IBT.patch
Normal file
98
v2-0003-x86-cet-Don-t-assume-that-SHSTK-implies-IBT.patch
Normal file
@ -0,0 +1,98 @@
|
||||
From 361cb3ec2ab4322f860d18a3a1d674603fe275c5 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Sun, 16 Jan 2022 18:23:58 -0800
|
||||
Subject: [PATCH v2 03/15] x86/cet: Don't assume that SHSTK implies IBT
|
||||
|
||||
Since shadow stack (SHSTK) is enabled in the Linux kernel without
|
||||
enabling indirect branch tracking (IBT), don't assume that SHSTK
|
||||
implies IBT. Use "CPU_FEATURE_ACTIVE (IBT)" to check if IBT is active
|
||||
and "CPU_FEATURE_ACTIVE (SHSTK)" to check if SHSTK is active.
|
||||
---
|
||||
sysdeps/x86/Makefile | 1 -
|
||||
sysdeps/x86/tst-cet-legacy-10.c | 6 +++---
|
||||
sysdeps/x86/tst-cet-legacy-8.c | 15 ++++++++-------
|
||||
3 files changed, 11 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
|
||||
index 917c26f116..ea45aad34c 100644
|
||||
--- a/sysdeps/x86/Makefile
|
||||
+++ b/sysdeps/x86/Makefile
|
||||
@@ -165,7 +165,6 @@ CFLAGS-tst-cet-legacy-mod-6a.c += -fcf-protection=branch
|
||||
CFLAGS-tst-cet-legacy-mod-6b.c += -fcf-protection
|
||||
CFLAGS-tst-cet-legacy-mod-6c.c += -fcf-protection
|
||||
CFLAGS-tst-cet-legacy-7.c += -fcf-protection=none
|
||||
-CFLAGS-tst-cet-legacy-8.c += -mshstk
|
||||
CFLAGS-tst-cet-legacy-10.c += -mshstk
|
||||
CFLAGS-tst-cet-legacy-10-static.c += -mshstk
|
||||
|
||||
diff --git a/sysdeps/x86/tst-cet-legacy-10.c b/sysdeps/x86/tst-cet-legacy-10.c
|
||||
index a85cdc3171..ae2c34de3e 100644
|
||||
--- a/sysdeps/x86/tst-cet-legacy-10.c
|
||||
+++ b/sysdeps/x86/tst-cet-legacy-10.c
|
||||
@@ -21,19 +21,19 @@
|
||||
#include <support/test-driver.h>
|
||||
#include <support/xunistd.h>
|
||||
|
||||
-/* Check that CPU_FEATURE_ACTIVE on IBT and SHSTK matches _get_ssp. */
|
||||
+/* Check that CPU_FEATURE_ACTIVE on SHSTK matches _get_ssp. */
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
if (_get_ssp () != 0)
|
||||
{
|
||||
- if (CPU_FEATURE_ACTIVE (IBT) && CPU_FEATURE_ACTIVE (SHSTK))
|
||||
+ if (CPU_FEATURE_ACTIVE (SHSTK))
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
- if (!CPU_FEATURE_ACTIVE (IBT) && !CPU_FEATURE_ACTIVE (SHSTK))
|
||||
+ if (!CPU_FEATURE_ACTIVE (SHSTK))
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
diff --git a/sysdeps/x86/tst-cet-legacy-8.c b/sysdeps/x86/tst-cet-legacy-8.c
|
||||
index 5d8d9ba7dc..77d77a5408 100644
|
||||
--- a/sysdeps/x86/tst-cet-legacy-8.c
|
||||
+++ b/sysdeps/x86/tst-cet-legacy-8.c
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
-#include <x86intrin.h>
|
||||
+#include <sys/platform/x86.h>
|
||||
#include <sys/mman.h>
|
||||
#include <support/test-driver.h>
|
||||
#include <support/xsignal.h>
|
||||
@@ -29,11 +29,6 @@
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
- /* NB: This test should trigger SIGSEGV on CET platforms. If SHSTK
|
||||
- is disabled, assuming IBT is also disabled. */
|
||||
- if (_get_ssp () == 0)
|
||||
- return EXIT_UNSUPPORTED;
|
||||
-
|
||||
void (*funcp) (void);
|
||||
funcp = xmmap (NULL, 0x1000, PROT_EXEC | PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1);
|
||||
@@ -41,8 +36,14 @@ do_test (void)
|
||||
/* Write RET instruction. */
|
||||
*(char *) funcp = 0xc3;
|
||||
funcp ();
|
||||
+
|
||||
+ /* NB: This test should trigger SIGSEGV when IBT is active. We should
|
||||
+ reach here if IBT isn't active. */
|
||||
+ if (!CPU_FEATURE_ACTIVE (IBT))
|
||||
+ return EXIT_UNSUPPORTED;
|
||||
+
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
-#define EXPECTED_SIGNAL (_get_ssp () == 0 ? 0 : SIGSEGV)
|
||||
+#define EXPECTED_SIGNAL (CPU_FEATURE_ACTIVE (IBT) ? SIGSEGV : 0)
|
||||
#include <support/test-driver.c>
|
||||
--
|
||||
2.40.1
|
||||
|
209
v2-0004-x86-cet-Check-legacy-shadow-stack-applications.patch
Normal file
209
v2-0004-x86-cet-Check-legacy-shadow-stack-applications.patch
Normal file
@ -0,0 +1,209 @@
|
||||
From 2db487201909cf8fc1216e0b41e5bdd0d6677460 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Tue, 21 Mar 2023 12:53:24 -0700
|
||||
Subject: [PATCH v2 04/15] x86/cet: Check legacy shadow stack applications
|
||||
|
||||
Add tests to verify that legacy shadow stack applications run properly
|
||||
when shadow stack is enabled in Linux kernel.
|
||||
---
|
||||
sysdeps/x86/Makefile | 23 ++++++++++++++
|
||||
sysdeps/x86/tst-shstk-legacy-1-extra.S | 35 ++++++++++++++++++++++
|
||||
sysdeps/x86/tst-shstk-legacy-1a-static.c | 1 +
|
||||
sysdeps/x86/tst-shstk-legacy-1a.c | 32 ++++++++++++++++++++
|
||||
sysdeps/x86/tst-shstk-legacy-1b-static.c | 1 +
|
||||
sysdeps/x86/tst-shstk-legacy-1b.c | 38 ++++++++++++++++++++++++
|
||||
6 files changed, 130 insertions(+)
|
||||
create mode 100644 sysdeps/x86/tst-shstk-legacy-1-extra.S
|
||||
create mode 100644 sysdeps/x86/tst-shstk-legacy-1a-static.c
|
||||
create mode 100644 sysdeps/x86/tst-shstk-legacy-1a.c
|
||||
create mode 100644 sysdeps/x86/tst-shstk-legacy-1b-static.c
|
||||
create mode 100644 sysdeps/x86/tst-shstk-legacy-1b.c
|
||||
|
||||
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
|
||||
index ea45aad34c..dea14e343c 100644
|
||||
--- a/sysdeps/x86/Makefile
|
||||
+++ b/sysdeps/x86/Makefile
|
||||
@@ -129,6 +129,21 @@ tests += tst-cet-legacy-1 tst-cet-legacy-1a tst-cet-legacy-2 \
|
||||
tst-cet-legacy-10 tst-cet-legacy-10-static
|
||||
tests-static += tst-cet-legacy-9-static tst-cet-legacy-10-static
|
||||
tst-cet-legacy-1a-ARGS = -- $(host-test-program-cmd)
|
||||
+
|
||||
+tests += \
|
||||
+ tst-shstk-legacy-1a \
|
||||
+ tst-shstk-legacy-1a-static \
|
||||
+ tst-shstk-legacy-1b \
|
||||
+ tst-shstk-legacy-1b-static \
|
||||
+# tests
|
||||
+tests-static += \
|
||||
+ tst-shstk-legacy-1a-static \
|
||||
+ tst-shstk-legacy-1b-static \
|
||||
+# tests-static
|
||||
+extra-objs += \
|
||||
+ tst-shstk-legacy-1-extra.o \
|
||||
+# extra-objs
|
||||
+
|
||||
tests += tst-cet-legacy-4a tst-cet-legacy-4b tst-cet-legacy-4c \
|
||||
tst-cet-legacy-5b tst-cet-legacy-6b
|
||||
modules-names += tst-cet-legacy-mod-1 tst-cet-legacy-mod-2 \
|
||||
@@ -168,6 +183,9 @@ CFLAGS-tst-cet-legacy-7.c += -fcf-protection=none
|
||||
CFLAGS-tst-cet-legacy-10.c += -mshstk
|
||||
CFLAGS-tst-cet-legacy-10-static.c += -mshstk
|
||||
|
||||
+CFLAGS-tst-shstk-legacy-1a.c += -fcf-protection=none
|
||||
+CFLAGS-tst-shstk-legacy-1a-static.c += -fcf-protection=none
|
||||
+
|
||||
$(objpfx)tst-cet-legacy-1: $(objpfx)tst-cet-legacy-mod-1.so \
|
||||
$(objpfx)tst-cet-legacy-mod-2.so
|
||||
$(objpfx)tst-cet-legacy-1a: $(objpfx)tst-cet-legacy-mod-1.so \
|
||||
@@ -200,6 +218,11 @@ $(objpfx)tst-cet-legacy-6b.out: $(objpfx)tst-cet-legacy-mod-6a.so \
|
||||
tst-cet-legacy-6b-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK
|
||||
tst-cet-legacy-9-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK
|
||||
tst-cet-legacy-9-static-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK
|
||||
+
|
||||
+$(objpfx)tst-shstk-legacy-1a: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
+$(objpfx)tst-shstk-legacy-1a-static: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
+$(objpfx)tst-shstk-legacy-1b: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
+$(objpfx)tst-shstk-legacy-1b-static: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
endif
|
||||
|
||||
# Add -fcf-protection to CFLAGS when CET is enabled.
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1-extra.S b/sysdeps/x86/tst-shstk-legacy-1-extra.S
|
||||
new file mode 100644
|
||||
index 0000000000..f3adb9f639
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1-extra.S
|
||||
@@ -0,0 +1,35 @@
|
||||
+/* Legacy shadow stack code.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+ .text
|
||||
+ .globl legacy
|
||||
+ .type legacy, @function
|
||||
+legacy:
|
||||
+ .cfi_startproc
|
||||
+#ifdef __x86_64__
|
||||
+ movq (%rsp), %rax
|
||||
+ addq $8, %rsp
|
||||
+ jmp *%rax
|
||||
+#else
|
||||
+ movl (%esp), %eax
|
||||
+ addl $4, %esp
|
||||
+ jmp *%eax
|
||||
+#endif
|
||||
+ .cfi_endproc
|
||||
+ .size legacy, .-legacy
|
||||
+ .section .note.GNU-stack,"",@progbits
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1a-static.c b/sysdeps/x86/tst-shstk-legacy-1a-static.c
|
||||
new file mode 100644
|
||||
index 0000000000..dd549890a0
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1a-static.c
|
||||
@@ -0,0 +1 @@
|
||||
+#include "tst-shstk-legacy-1a.c"
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1a.c b/sysdeps/x86/tst-shstk-legacy-1a.c
|
||||
new file mode 100644
|
||||
index 0000000000..c6f5810838
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1a.c
|
||||
@@ -0,0 +1,32 @@
|
||||
+/* Check that legacy shadow stack code won't trigger segfault.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdlib.h>
|
||||
+#include <support/test-driver.h>
|
||||
+
|
||||
+/* Check that legacy shadow stack code won't trigger segfault. */
|
||||
+extern void legacy (void);
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ legacy ();
|
||||
+ return EXIT_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1b-static.c b/sysdeps/x86/tst-shstk-legacy-1b-static.c
|
||||
new file mode 100644
|
||||
index 0000000000..4945344675
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1b-static.c
|
||||
@@ -0,0 +1 @@
|
||||
+#include "tst-shstk-legacy-1b.c"
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1b.c b/sysdeps/x86/tst-shstk-legacy-1b.c
|
||||
new file mode 100644
|
||||
index 0000000000..05231e60ae
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1b.c
|
||||
@@ -0,0 +1,38 @@
|
||||
+/* Check that legacy shadow stack code will trigger segfault.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdlib.h>
|
||||
+#include <sys/platform/x86.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/xsignal.h>
|
||||
+
|
||||
+/* Check that legacy shadow stack code will trigger segfault. */
|
||||
+extern void legacy (void);
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ if (!CPU_FEATURE_ACTIVE (SHSTK))
|
||||
+ return EXIT_UNSUPPORTED;
|
||||
+
|
||||
+ legacy ();
|
||||
+ return EXIT_FAILURE;
|
||||
+}
|
||||
+
|
||||
+#define EXPECTED_SIGNAL (CPU_FEATURE_ACTIVE (SHSTK) ? SIGSEGV : 0)
|
||||
+#include <support/test-driver.c>
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,61 @@
|
||||
From 13543173f98ca8f01311fa6a2bca409128561d18 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Fri, 10 Mar 2023 13:18:10 -0800
|
||||
Subject: [PATCH v2 05/15] x86/cet: Check CPU_FEATURE_ACTIVE when CET is
|
||||
disabled
|
||||
|
||||
Verify that CPU_FEATURE_ACTIVE (SHSTK) works properly when CET is
|
||||
disabled.
|
||||
---
|
||||
sysdeps/x86/Makefile | 8 ++++++--
|
||||
sysdeps/x86/tst-cet-legacy-10a-static.c | 2 ++
|
||||
sysdeps/x86/tst-cet-legacy-10a.c | 2 ++
|
||||
3 files changed, 10 insertions(+), 2 deletions(-)
|
||||
create mode 100644 sysdeps/x86/tst-cet-legacy-10a-static.c
|
||||
create mode 100644 sysdeps/x86/tst-cet-legacy-10a.c
|
||||
|
||||
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
|
||||
index dea14e343c..580c3ecdc5 100644
|
||||
--- a/sysdeps/x86/Makefile
|
||||
+++ b/sysdeps/x86/Makefile
|
||||
@@ -126,8 +126,10 @@ tests += tst-cet-legacy-1 tst-cet-legacy-1a tst-cet-legacy-2 \
|
||||
tst-cet-legacy-2a tst-cet-legacy-3 tst-cet-legacy-4 \
|
||||
tst-cet-legacy-5a tst-cet-legacy-6a tst-cet-legacy-7 \
|
||||
tst-cet-legacy-8 tst-cet-legacy-9 tst-cet-legacy-9-static \
|
||||
- tst-cet-legacy-10 tst-cet-legacy-10-static
|
||||
-tests-static += tst-cet-legacy-9-static tst-cet-legacy-10-static
|
||||
+ tst-cet-legacy-10 tst-cet-legacy-10-static \
|
||||
+ tst-cet-legacy-10a tst-cet-legacy-10a-static
|
||||
+tests-static += tst-cet-legacy-9-static tst-cet-legacy-10-static \
|
||||
+ tst-cet-legacy-10a-static
|
||||
tst-cet-legacy-1a-ARGS = -- $(host-test-program-cmd)
|
||||
|
||||
tests += \
|
||||
@@ -182,6 +184,8 @@ CFLAGS-tst-cet-legacy-mod-6c.c += -fcf-protection
|
||||
CFLAGS-tst-cet-legacy-7.c += -fcf-protection=none
|
||||
CFLAGS-tst-cet-legacy-10.c += -mshstk
|
||||
CFLAGS-tst-cet-legacy-10-static.c += -mshstk
|
||||
+CFLAGS-tst-cet-legacy-10a.c += -fcf-protection=none
|
||||
+CFLAGS-tst-cet-legacy-10a-static.c += -fcf-protection=none
|
||||
|
||||
CFLAGS-tst-shstk-legacy-1a.c += -fcf-protection=none
|
||||
CFLAGS-tst-shstk-legacy-1a-static.c += -fcf-protection=none
|
||||
diff --git a/sysdeps/x86/tst-cet-legacy-10a-static.c b/sysdeps/x86/tst-cet-legacy-10a-static.c
|
||||
new file mode 100644
|
||||
index 0000000000..05073a5d1e
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-cet-legacy-10a-static.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+#pragma GCC target ("shstk")
|
||||
+#include "tst-cet-legacy-10.c"
|
||||
diff --git a/sysdeps/x86/tst-cet-legacy-10a.c b/sysdeps/x86/tst-cet-legacy-10a.c
|
||||
new file mode 100644
|
||||
index 0000000000..05073a5d1e
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-cet-legacy-10a.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+#pragma GCC target ("shstk")
|
||||
+#include "tst-cet-legacy-10.c"
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,81 @@
|
||||
From 7a97a9ab63a37ae1191e514258e4f6fefdc2e41b Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Fri, 17 Mar 2023 16:21:49 -0700
|
||||
Subject: [PATCH v2 06/15] x86/cet: Add tests for
|
||||
GLIBC_TUNABLES=glibc.cpu.hwcaps=-SHSTK
|
||||
|
||||
Verify that GLIBC_TUNABLES=glibc.cpu.hwcaps=-SHSTK turns off shadow
|
||||
stack properly.
|
||||
---
|
||||
sysdeps/x86/Makefile | 7 +++++++
|
||||
sysdeps/x86/tst-shstk-legacy-1c-static.c | 1 +
|
||||
sysdeps/x86/tst-shstk-legacy-1c.c | 20 ++++++++++++++++++++
|
||||
3 files changed, 28 insertions(+)
|
||||
create mode 100644 sysdeps/x86/tst-shstk-legacy-1c-static.c
|
||||
create mode 100644 sysdeps/x86/tst-shstk-legacy-1c.c
|
||||
|
||||
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
|
||||
index 580c3ecdc5..5f1414fba3 100644
|
||||
--- a/sysdeps/x86/Makefile
|
||||
+++ b/sysdeps/x86/Makefile
|
||||
@@ -137,10 +137,13 @@ tests += \
|
||||
tst-shstk-legacy-1a-static \
|
||||
tst-shstk-legacy-1b \
|
||||
tst-shstk-legacy-1b-static \
|
||||
+ tst-shstk-legacy-1c \
|
||||
+ tst-shstk-legacy-1c-static \
|
||||
# tests
|
||||
tests-static += \
|
||||
tst-shstk-legacy-1a-static \
|
||||
tst-shstk-legacy-1b-static \
|
||||
+ tst-shstk-legacy-1c-static \
|
||||
# tests-static
|
||||
extra-objs += \
|
||||
tst-shstk-legacy-1-extra.o \
|
||||
@@ -227,6 +230,10 @@ $(objpfx)tst-shstk-legacy-1a: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
$(objpfx)tst-shstk-legacy-1a-static: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
$(objpfx)tst-shstk-legacy-1b: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
$(objpfx)tst-shstk-legacy-1b-static: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
+tst-shstk-legacy-1c-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-SHSTK
|
||||
+tst-shstk-legacy-1c-static-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-SHSTK
|
||||
+$(objpfx)tst-shstk-legacy-1c: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
+$(objpfx)tst-shstk-legacy-1c-static: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
endif
|
||||
|
||||
# Add -fcf-protection to CFLAGS when CET is enabled.
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1c-static.c b/sysdeps/x86/tst-shstk-legacy-1c-static.c
|
||||
new file mode 100644
|
||||
index 0000000000..91ea346aaf
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1c-static.c
|
||||
@@ -0,0 +1 @@
|
||||
+#include "tst-shstk-legacy-1c.c"
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1c.c b/sysdeps/x86/tst-shstk-legacy-1c.c
|
||||
new file mode 100644
|
||||
index 0000000000..eb218c6c70
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1c.c
|
||||
@@ -0,0 +1,20 @@
|
||||
+/* Check that legacy shadow stack code won't trigger segfault with
|
||||
+ GLIBC_TUNABLES=glibc.cpu.hwcaps=-SHSTK
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include "tst-shstk-legacy-1a.c"
|
||||
--
|
||||
2.40.1
|
||||
|
456
v2-0007-x86-cet-Check-legacy-shadow-stack-code-in-.init_a.patch
Normal file
456
v2-0007-x86-cet-Check-legacy-shadow-stack-code-in-.init_a.patch
Normal file
@ -0,0 +1,456 @@
|
||||
From d3bf3cba97111334082b817e59ff2840dbc98afa Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Wed, 22 Mar 2023 13:34:55 -0700
|
||||
Subject: [PATCH v2 07/15] x86/cet: Check legacy shadow stack code in
|
||||
.init_array section
|
||||
|
||||
Verify that legacy shadow stack code in .init_array section in application
|
||||
and shared library, which are marked as shadow stack enabled, will trigger
|
||||
segfault.
|
||||
---
|
||||
sysdeps/x86/Makefile | 36 +++++++++++++++
|
||||
sysdeps/x86/tst-shstk-legacy-1d-static.c | 1 +
|
||||
sysdeps/x86/tst-shstk-legacy-1d.c | 47 ++++++++++++++++++++
|
||||
sysdeps/x86/tst-shstk-legacy-1e-static.c | 1 +
|
||||
sysdeps/x86/tst-shstk-legacy-1e-static.sh | 32 ++++++++++++++
|
||||
sysdeps/x86/tst-shstk-legacy-1e.c | 53 +++++++++++++++++++++++
|
||||
sysdeps/x86/tst-shstk-legacy-1e.sh | 34 +++++++++++++++
|
||||
sysdeps/x86/tst-shstk-legacy-1f.c | 29 +++++++++++++
|
||||
sysdeps/x86/tst-shstk-legacy-1g.c | 35 +++++++++++++++
|
||||
sysdeps/x86/tst-shstk-legacy-1g.sh | 34 +++++++++++++++
|
||||
sysdeps/x86/tst-shstk-legacy-mod-1.c | 28 ++++++++++++
|
||||
11 files changed, 330 insertions(+)
|
||||
create mode 100644 sysdeps/x86/tst-shstk-legacy-1d-static.c
|
||||
create mode 100644 sysdeps/x86/tst-shstk-legacy-1d.c
|
||||
create mode 100644 sysdeps/x86/tst-shstk-legacy-1e-static.c
|
||||
create mode 100755 sysdeps/x86/tst-shstk-legacy-1e-static.sh
|
||||
create mode 100644 sysdeps/x86/tst-shstk-legacy-1e.c
|
||||
create mode 100755 sysdeps/x86/tst-shstk-legacy-1e.sh
|
||||
create mode 100644 sysdeps/x86/tst-shstk-legacy-1f.c
|
||||
create mode 100644 sysdeps/x86/tst-shstk-legacy-1g.c
|
||||
create mode 100755 sysdeps/x86/tst-shstk-legacy-1g.sh
|
||||
create mode 100644 sysdeps/x86/tst-shstk-legacy-mod-1.c
|
||||
|
||||
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
|
||||
index 5f1414fba3..b8b98177e0 100644
|
||||
--- a/sysdeps/x86/Makefile
|
||||
+++ b/sysdeps/x86/Makefile
|
||||
@@ -139,11 +139,22 @@ tests += \
|
||||
tst-shstk-legacy-1b-static \
|
||||
tst-shstk-legacy-1c \
|
||||
tst-shstk-legacy-1c-static \
|
||||
+ tst-shstk-legacy-1d \
|
||||
+ tst-shstk-legacy-1d-static \
|
||||
+ tst-shstk-legacy-1e \
|
||||
+ tst-shstk-legacy-1e-static \
|
||||
+ tst-shstk-legacy-1f \
|
||||
+ tst-shstk-legacy-1g \
|
||||
# tests
|
||||
+modules-names += \
|
||||
+ tst-shstk-legacy-mod-1 \
|
||||
+# modules-names
|
||||
tests-static += \
|
||||
tst-shstk-legacy-1a-static \
|
||||
tst-shstk-legacy-1b-static \
|
||||
tst-shstk-legacy-1c-static \
|
||||
+ tst-shstk-legacy-1d-static \
|
||||
+ tst-shstk-legacy-1e-static \
|
||||
# tests-static
|
||||
extra-objs += \
|
||||
tst-shstk-legacy-1-extra.o \
|
||||
@@ -192,6 +203,9 @@ CFLAGS-tst-cet-legacy-10a-static.c += -fcf-protection=none
|
||||
|
||||
CFLAGS-tst-shstk-legacy-1a.c += -fcf-protection=none
|
||||
CFLAGS-tst-shstk-legacy-1a-static.c += -fcf-protection=none
|
||||
+CFLAGS-tst-shstk-legacy-1d.c += -fcf-protection=none
|
||||
+CFLAGS-tst-shstk-legacy-1d-static.c += -fcf-protection=none
|
||||
+CFLAGS-tst-shstk-legacy-1f.c += -fcf-protection=none
|
||||
|
||||
$(objpfx)tst-cet-legacy-1: $(objpfx)tst-cet-legacy-mod-1.so \
|
||||
$(objpfx)tst-cet-legacy-mod-2.so
|
||||
@@ -234,6 +248,28 @@ tst-shstk-legacy-1c-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-SHSTK
|
||||
tst-shstk-legacy-1c-static-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-SHSTK
|
||||
$(objpfx)tst-shstk-legacy-1c: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
$(objpfx)tst-shstk-legacy-1c-static: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
+$(objpfx)tst-shstk-legacy-1d: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
+$(objpfx)tst-shstk-legacy-1d-static: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
+$(objpfx)tst-shstk-legacy-1e: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
+$(objpfx)tst-shstk-legacy-1e-static: $(objpfx)tst-shstk-legacy-1-extra.o
|
||||
+$(objpfx)tst-shstk-legacy-1e.out: \
|
||||
+ $(..)/sysdeps/x86/tst-shstk-legacy-1e.sh $(objpfx)tst-shstk-legacy-1e
|
||||
+ $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' 2> $@; \
|
||||
+ $(evaluate-test)
|
||||
+$(objpfx)tst-shstk-legacy-1e-static.out: \
|
||||
+ $(..)/sysdeps/x86/tst-shstk-legacy-1e-static.sh \
|
||||
+ $(objpfx)tst-shstk-legacy-1e-static
|
||||
+ $(SHELL) $< $(common-objpfx) 2> $@; \
|
||||
+ $(evaluate-test)
|
||||
+$(objpfx)tst-shstk-legacy-1f: $(objpfx)tst-shstk-legacy-mod-1.so
|
||||
+$(objpfx)tst-shstk-legacy-mod-1.so: \
|
||||
+ $(objpfx)tst-shstk-legacy-mod-1.os \
|
||||
+ $(objpfx)tst-shstk-legacy-1-extra.os
|
||||
+$(objpfx)tst-shstk-legacy-1g: $(objpfx)tst-shstk-legacy-mod-1.so
|
||||
+$(objpfx)tst-shstk-legacy-1g.out: \
|
||||
+ $(..)/sysdeps/x86/tst-shstk-legacy-1g.sh $(objpfx)tst-shstk-legacy-1g
|
||||
+ $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' 2> $@; \
|
||||
+ $(evaluate-test)
|
||||
endif
|
||||
|
||||
# Add -fcf-protection to CFLAGS when CET is enabled.
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1d-static.c b/sysdeps/x86/tst-shstk-legacy-1d-static.c
|
||||
new file mode 100644
|
||||
index 0000000000..dca27a5482
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1d-static.c
|
||||
@@ -0,0 +1 @@
|
||||
+#include "tst-shstk-legacy-1d.c"
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1d.c b/sysdeps/x86/tst-shstk-legacy-1d.c
|
||||
new file mode 100644
|
||||
index 0000000000..465cfab1db
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1d.c
|
||||
@@ -0,0 +1,47 @@
|
||||
+/* Check that legacy shadow stack code in init_array won't trigger
|
||||
+ segfault.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdlib.h>
|
||||
+#include <support/test-driver.h>
|
||||
+
|
||||
+/* Check that legacy shadow stack code in init_array won't trigger
|
||||
+ segfault. */
|
||||
+extern void legacy (void);
|
||||
+int done;
|
||||
+
|
||||
+void
|
||||
+legacy_1 (void)
|
||||
+{
|
||||
+ legacy ();
|
||||
+ done = 1;
|
||||
+}
|
||||
+
|
||||
+void (*init_array []) (void)
|
||||
+ __attribute__ ((section (".init_array"), aligned (sizeof (void *)))) =
|
||||
+{
|
||||
+ &legacy_1
|
||||
+};
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ return EXIT_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1e-static.c b/sysdeps/x86/tst-shstk-legacy-1e-static.c
|
||||
new file mode 100644
|
||||
index 0000000000..cb6ce0de00
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1e-static.c
|
||||
@@ -0,0 +1 @@
|
||||
+#include "tst-shstk-legacy-1e.c"
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1e-static.sh b/sysdeps/x86/tst-shstk-legacy-1e-static.sh
|
||||
new file mode 100755
|
||||
index 0000000000..e943aec70e
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1e-static.sh
|
||||
@@ -0,0 +1,32 @@
|
||||
+#!/bin/sh
|
||||
+# Check that legacy shadow stack code in init_array will trigger
|
||||
+# segfault.
|
||||
+# Copyright (C) 2023 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
|
||||
+# <https://www.gnu.org/licenses/>.
|
||||
+
|
||||
+common_objpfx=$1; shift
|
||||
+
|
||||
+${common_objpfx}elf/tst-shstk-legacy-1e-static
|
||||
+# The exit status should only be unsupported (77) or segfault (139).
|
||||
+status=$?
|
||||
+if test $status -eq 77; then
|
||||
+ exit 77
|
||||
+elif test $status == 139; then
|
||||
+ exit 0
|
||||
+else
|
||||
+ exit 1
|
||||
+fi
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1e.c b/sysdeps/x86/tst-shstk-legacy-1e.c
|
||||
new file mode 100644
|
||||
index 0000000000..e78a4b776e
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1e.c
|
||||
@@ -0,0 +1,53 @@
|
||||
+/* Check that legacy shadow stack code in init_array will trigger
|
||||
+ segfault.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdlib.h>
|
||||
+#include <sys/platform/x86.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/xsignal.h>
|
||||
+
|
||||
+/* Check that legacy shadow stack code in init_array will trigger
|
||||
+ segfault. */
|
||||
+extern void legacy (void);
|
||||
+int done;
|
||||
+
|
||||
+void
|
||||
+legacy_1 (void)
|
||||
+{
|
||||
+ legacy ();
|
||||
+ done = 1;
|
||||
+}
|
||||
+
|
||||
+void (*init_array []) (void)
|
||||
+ __attribute__ ((section (".init_array"), aligned (sizeof (void *)))) =
|
||||
+{
|
||||
+ &legacy_1
|
||||
+};
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ if (!CPU_FEATURE_ACTIVE (SHSTK))
|
||||
+ return EXIT_UNSUPPORTED;
|
||||
+
|
||||
+ return EXIT_FAILURE;
|
||||
+}
|
||||
+
|
||||
+#define EXPECTED_SIGNAL (CPU_FEATURE_ACTIVE (SHSTK) ? SIGSEGV : 0)
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1e.sh b/sysdeps/x86/tst-shstk-legacy-1e.sh
|
||||
new file mode 100755
|
||||
index 0000000000..b0467aa899
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1e.sh
|
||||
@@ -0,0 +1,34 @@
|
||||
+#!/bin/sh
|
||||
+# Check that legacy shadow stack code in init_array will trigger
|
||||
+# segfault.
|
||||
+# Copyright (C) 2023 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
|
||||
+# <https://www.gnu.org/licenses/>.
|
||||
+
|
||||
+common_objpfx=$1; shift
|
||||
+test_program_prefix=$1; shift
|
||||
+
|
||||
+${test_program_prefix} \
|
||||
+ ${common_objpfx}elf/tst-shstk-legacy-1e
|
||||
+# The exit status should only be unsupported (77) or segfault (139).
|
||||
+status=$?
|
||||
+if test $status -eq 77; then
|
||||
+ exit 77
|
||||
+elif test $status == 139; then
|
||||
+ exit 0
|
||||
+else
|
||||
+ exit 1
|
||||
+fi
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1f.c b/sysdeps/x86/tst-shstk-legacy-1f.c
|
||||
new file mode 100644
|
||||
index 0000000000..27e01a229e
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1f.c
|
||||
@@ -0,0 +1,29 @@
|
||||
+/* Check that legacy shadow stack code in init_array won't trigger
|
||||
+ segfault.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdlib.h>
|
||||
+#include <support/test-driver.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ return EXIT_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1g.c b/sysdeps/x86/tst-shstk-legacy-1g.c
|
||||
new file mode 100644
|
||||
index 0000000000..a1f3d242e9
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1g.c
|
||||
@@ -0,0 +1,35 @@
|
||||
+/* Check that legacy shadow stack code in init_array will trigger
|
||||
+ segfault.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdlib.h>
|
||||
+#include <sys/platform/x86.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/xsignal.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ if (!CPU_FEATURE_ACTIVE (SHSTK))
|
||||
+ return EXIT_UNSUPPORTED;
|
||||
+
|
||||
+ return EXIT_FAILURE;
|
||||
+}
|
||||
+
|
||||
+#define EXPECTED_SIGNAL (CPU_FEATURE_ACTIVE (SHSTK) ? SIGSEGV : 0)
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-1g.sh b/sysdeps/x86/tst-shstk-legacy-1g.sh
|
||||
new file mode 100755
|
||||
index 0000000000..c112bf6d8d
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-1g.sh
|
||||
@@ -0,0 +1,34 @@
|
||||
+#!/bin/sh
|
||||
+# Check that legacy shadow stack code in init_array will trigger
|
||||
+# segfault.
|
||||
+# Copyright (C) 2023 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
|
||||
+# <https://www.gnu.org/licenses/>.
|
||||
+
|
||||
+common_objpfx=$1; shift
|
||||
+test_program_prefix=$1; shift
|
||||
+
|
||||
+${test_program_prefix} \
|
||||
+ ${common_objpfx}elf/tst-shstk-legacy-1g
|
||||
+# The exit status should only be unsupported (77) or segfault (139).
|
||||
+status=$?
|
||||
+if test $status -eq 77; then
|
||||
+ exit 77
|
||||
+elif test $status == 139; then
|
||||
+ exit 0
|
||||
+else
|
||||
+ exit 1
|
||||
+fi
|
||||
diff --git a/sysdeps/x86/tst-shstk-legacy-mod-1.c b/sysdeps/x86/tst-shstk-legacy-mod-1.c
|
||||
new file mode 100644
|
||||
index 0000000000..b75b5484d9
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/tst-shstk-legacy-mod-1.c
|
||||
@@ -0,0 +1,28 @@
|
||||
+/* Check legacy shadow stack code in init_array.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+/* Check legacy shadow stack code in init_array. */
|
||||
+extern void legacy (void) __attribute__ ((visibility ("hidden")));
|
||||
+
|
||||
+void (*init_array []) (void)
|
||||
+ __attribute__ ((section (".init_array"), aligned (sizeof (void *)))) =
|
||||
+{
|
||||
+ &legacy
|
||||
+};
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,49 @@
|
||||
From 8230fefd2495d1fb7fa72c680dc10ae4d10fde61 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Tue, 28 Mar 2023 13:52:36 -0700
|
||||
Subject: [PATCH v2 08/15] x86/cet: Check CPU_FEATURE_ACTIVE in permissive mode
|
||||
|
||||
Verify that CPU_FEATURE_ACTIVE works properly in permissive mode.
|
||||
---
|
||||
sysdeps/x86/Makefile | 1 +
|
||||
sysdeps/x86/tst-cet-legacy-4.c | 5 +++++
|
||||
2 files changed, 6 insertions(+)
|
||||
|
||||
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
|
||||
index b8b98177e0..6ceefe16c7 100644
|
||||
--- a/sysdeps/x86/Makefile
|
||||
+++ b/sysdeps/x86/Makefile
|
||||
@@ -174,6 +174,7 @@ CFLAGS-tst-cet-legacy-mod-1.c += -fcf-protection=none
|
||||
CFLAGS-tst-cet-legacy-mod-2.c += -fcf-protection=none
|
||||
CFLAGS-tst-cet-legacy-3.c += -fcf-protection=none
|
||||
CFLAGS-tst-cet-legacy-4.c += -fcf-protection=branch
|
||||
+CPPFLAGS-tst-cet-legacy-4a.c += -DCET_IS_PERMISSIVE=1
|
||||
CFLAGS-tst-cet-legacy-4a.c += -fcf-protection
|
||||
CFLAGS-tst-cet-legacy-4b.c += -fcf-protection
|
||||
CFLAGS-tst-cet-legacy-mod-4.c += -fcf-protection=none
|
||||
diff --git a/sysdeps/x86/tst-cet-legacy-4.c b/sysdeps/x86/tst-cet-legacy-4.c
|
||||
index d75fb0e61c..c098120253 100644
|
||||
--- a/sysdeps/x86/tst-cet-legacy-4.c
|
||||
+++ b/sysdeps/x86/tst-cet-legacy-4.c
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
+#include <sys/platform/x86.h>
|
||||
|
||||
#include <support/check.h>
|
||||
|
||||
@@ -40,6 +41,10 @@ do_test (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+#ifdef CET_IS_PERMISSIVE
|
||||
+ TEST_VERIFY (!CPU_FEATURE_ACTIVE (IBT) && !CPU_FEATURE_ACTIVE (SHSTK));
|
||||
+#endif
|
||||
+
|
||||
fp = dlsym (h, "test");
|
||||
if (fp == NULL)
|
||||
FAIL_EXIT1 ("cannot get symbol 'test': %s\n", dlerror ());
|
||||
--
|
||||
2.40.1
|
||||
|
160
v2-0009-x86-Check-PT_GNU_PROPERTY-early.patch
Normal file
160
v2-0009-x86-Check-PT_GNU_PROPERTY-early.patch
Normal file
@ -0,0 +1,160 @@
|
||||
From 4323e979bd1745e10ae29667c290bff7f74d38e4 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Thu, 13 Jan 2022 14:45:46 -0800
|
||||
Subject: [PATCH v2 09/15] x86: Check PT_GNU_PROPERTY early
|
||||
|
||||
The PT_GNU_PROPERTY segment is scanned before PT_NOTE. For binaries
|
||||
with the PT_GNU_PROPERTY segment, we can check it to avoid scan of
|
||||
the PT_NOTE segment.
|
||||
---
|
||||
sysdeps/x86/dl-prop.h | 120 ++++++++++++++++++++++++++++--------------
|
||||
1 file changed, 80 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h
|
||||
index 87702df040..ca07b83701 100644
|
||||
--- a/sysdeps/x86/dl-prop.h
|
||||
+++ b/sysdeps/x86/dl-prop.h
|
||||
@@ -81,6 +81,60 @@ _dl_open_check (struct link_map *m)
|
||||
#endif
|
||||
}
|
||||
|
||||
+/* Check the GNU property and return its value. It returns:
|
||||
+ -1: Skip this note.
|
||||
+ 0: Stop checking.
|
||||
+ 1: Continue to check.
|
||||
+ */
|
||||
+static inline int
|
||||
+_dl_check_gnu_property (unsigned int type, unsigned int datasz,
|
||||
+ void *ptr, unsigned int *feature_1_and,
|
||||
+ unsigned int *needed_1,
|
||||
+ unsigned int *isa_1_needed)
|
||||
+{
|
||||
+ if (type == GNU_PROPERTY_X86_FEATURE_1_AND
|
||||
+ || type == GNU_PROPERTY_X86_ISA_1_NEEDED
|
||||
+ || type == GNU_PROPERTY_1_NEEDED)
|
||||
+ {
|
||||
+ /* The sizes of types which we are searching for are
|
||||
+ 4 bytes. There is no point to continue if this
|
||||
+ note is ill-formed. */
|
||||
+ if (datasz != 4)
|
||||
+ return -1;
|
||||
+
|
||||
+ /* NB: Stop the scan only after seeing all types which
|
||||
+ we are searching for. */
|
||||
+ _Static_assert (((GNU_PROPERTY_X86_ISA_1_NEEDED
|
||||
+ > GNU_PROPERTY_X86_FEATURE_1_AND)
|
||||
+ && (GNU_PROPERTY_X86_FEATURE_1_AND
|
||||
+ > GNU_PROPERTY_1_NEEDED)),
|
||||
+ "GNU_PROPERTY_X86_ISA_1_NEEDED > "
|
||||
+ "GNU_PROPERTY_X86_FEATURE_1_AND && "
|
||||
+ "GNU_PROPERTY_X86_FEATURE_1_AND > "
|
||||
+ "GNU_PROPERTY_1_NEEDED");
|
||||
+ if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
|
||||
+ *feature_1_and = *(unsigned int *) ptr;
|
||||
+ else if (type == GNU_PROPERTY_1_NEEDED)
|
||||
+ *needed_1 = *(unsigned int *) ptr;
|
||||
+ else
|
||||
+ {
|
||||
+ *isa_1_needed = *(unsigned int *) ptr;
|
||||
+
|
||||
+ /* Keep searching for the next GNU property note
|
||||
+ generated by the older linker. */
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+ else if (type > GNU_PROPERTY_X86_ISA_1_NEEDED)
|
||||
+ {
|
||||
+ /* Stop the scan since property type is in ascending
|
||||
+ order. */
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static inline void __attribute__ ((unused))
|
||||
_dl_process_property_note (struct link_map *l, const ElfW(Nhdr) *note,
|
||||
const ElfW(Addr) size, const ElfW(Addr) align)
|
||||
@@ -141,45 +195,14 @@ _dl_process_property_note (struct link_map *l, const ElfW(Nhdr) *note,
|
||||
|
||||
last_type = type;
|
||||
|
||||
- if (type == GNU_PROPERTY_X86_FEATURE_1_AND
|
||||
- || type == GNU_PROPERTY_X86_ISA_1_NEEDED
|
||||
- || type == GNU_PROPERTY_1_NEEDED)
|
||||
- {
|
||||
- /* The sizes of types which we are searching for are
|
||||
- 4 bytes. There is no point to continue if this
|
||||
- note is ill-formed. */
|
||||
- if (datasz != 4)
|
||||
- return;
|
||||
-
|
||||
- /* NB: Stop the scan only after seeing all types which
|
||||
- we are searching for. */
|
||||
- _Static_assert (((GNU_PROPERTY_X86_ISA_1_NEEDED
|
||||
- > GNU_PROPERTY_X86_FEATURE_1_AND)
|
||||
- && (GNU_PROPERTY_X86_FEATURE_1_AND
|
||||
- > GNU_PROPERTY_1_NEEDED)),
|
||||
- "GNU_PROPERTY_X86_ISA_1_NEEDED > "
|
||||
- "GNU_PROPERTY_X86_FEATURE_1_AND && "
|
||||
- "GNU_PROPERTY_X86_FEATURE_1_AND > "
|
||||
- "GNU_PROPERTY_1_NEEDED");
|
||||
- if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
|
||||
- feature_1_and = *(unsigned int *) ptr;
|
||||
- else if (type == GNU_PROPERTY_1_NEEDED)
|
||||
- needed_1 = *(unsigned int *) ptr;
|
||||
- else
|
||||
- {
|
||||
- isa_1_needed = *(unsigned int *) ptr;
|
||||
-
|
||||
- /* Keep searching for the next GNU property note
|
||||
- generated by the older linker. */
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- else if (type > GNU_PROPERTY_X86_ISA_1_NEEDED)
|
||||
- {
|
||||
- /* Stop the scan since property type is in ascending
|
||||
- order. */
|
||||
- break;
|
||||
- }
|
||||
+ int result = _dl_check_gnu_property (type, datasz, ptr,
|
||||
+ &feature_1_and,
|
||||
+ &needed_1,
|
||||
+ &isa_1_needed);
|
||||
+ if (result == -1)
|
||||
+ return; /* Skip this note. */
|
||||
+ else if (result == 0)
|
||||
+ break; /* Stop checking. */
|
||||
|
||||
/* Check the next property item. */
|
||||
ptr += ALIGN_UP (datasz, sizeof (ElfW(Addr)));
|
||||
@@ -217,7 +240,24 @@ static inline int __attribute__ ((always_inline))
|
||||
_dl_process_gnu_property (struct link_map *l, int fd, uint32_t type,
|
||||
uint32_t datasz, void *data)
|
||||
{
|
||||
- return 0;
|
||||
+ /* This is called on each GNU property. */
|
||||
+ unsigned int needed_1 = 0;
|
||||
+ unsigned int feature_1_and = 0;
|
||||
+ unsigned int isa_1_needed = 0;
|
||||
+ int result = _dl_check_gnu_property (type, datasz, data,
|
||||
+ &feature_1_and, &needed_1,
|
||||
+ &isa_1_needed);
|
||||
+ if (needed_1 != 0)
|
||||
+ l->l_1_needed = needed_1;
|
||||
+ if (isa_1_needed != 0)
|
||||
+ l->l_x86_isa_1_needed = isa_1_needed;
|
||||
+ if (feature_1_and != 0)
|
||||
+ l->l_x86_feature_1_and = feature_1_and;
|
||||
+ if ((needed_1 | isa_1_needed | feature_1_and) != 0)
|
||||
+ l->l_property = lc_property_valid;
|
||||
+ else if (l->l_property == lc_property_unknown)
|
||||
+ l->l_property = lc_property_none;
|
||||
+ return result <= 0 ? 0 : result;
|
||||
}
|
||||
|
||||
#endif /* _DL_PROP_H */
|
||||
--
|
||||
2.40.1
|
||||
|
511
v2-0010-x86-Modularize-sysdeps-x86-dl-cet.c.patch
Normal file
511
v2-0010-x86-Modularize-sysdeps-x86-dl-cet.c.patch
Normal file
@ -0,0 +1,511 @@
|
||||
From 8431e78b2df0ee194ac0bbd5a5136e89765444c4 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Fri, 24 Mar 2023 13:20:06 -0700
|
||||
Subject: [PATCH v2 10/15] x86: Modularize sysdeps/x86/dl-cet.c
|
||||
|
||||
Improve readability and make maintenance easier for dl-feature.c by
|
||||
modularizing sysdeps/x86/dl-cet.c:
|
||||
1. Support processors with:
|
||||
a. Only IBT. Or
|
||||
b. Only SHSTK. Or
|
||||
c. Both IBT and SHSTK.
|
||||
2. Lock CET features only if IBT or SHSTK are enabled and are not
|
||||
enabled permissively.
|
||||
---
|
||||
sysdeps/x86/dl-cet.c | 456 ++++++++++++++++++++++++++-----------------
|
||||
1 file changed, 280 insertions(+), 176 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c
|
||||
index 60ea1cb558..67c51ee8c2 100644
|
||||
--- a/sysdeps/x86/dl-cet.c
|
||||
+++ b/sysdeps/x86/dl-cet.c
|
||||
@@ -32,206 +32,310 @@
|
||||
# error GNU_PROPERTY_X86_FEATURE_1_SHSTK != X86_FEATURE_1_SHSTK
|
||||
#endif
|
||||
|
||||
-/* Check if object M is compatible with CET. */
|
||||
+struct dl_cet_info
|
||||
+{
|
||||
+ const char *program;
|
||||
+
|
||||
+ /* Check how IBT and SHSTK should be enabled. */
|
||||
+ enum dl_x86_cet_control enable_ibt_type;
|
||||
+ enum dl_x86_cet_control enable_shstk_type;
|
||||
+
|
||||
+ /* If IBT and SHSTK were previously enabled. */
|
||||
+ unsigned int feature_1_enabled;
|
||||
+
|
||||
+ /* If IBT and SHSTK should be enabled. */
|
||||
+ unsigned int enable_feature_1;
|
||||
+
|
||||
+ /* If there are any legacy shared object. */
|
||||
+ unsigned int feature_1_legacy;
|
||||
+
|
||||
+ /* Which shared object is the first legacy shared object. */
|
||||
+ unsigned int feature_1_legacy_ibt;
|
||||
+ unsigned int feature_1_legacy_shstk;
|
||||
+};
|
||||
+
|
||||
+/* Check if the object M and its dependencies are legacy object. */
|
||||
|
||||
static void
|
||||
-dl_cet_check (struct link_map *m, const char *program)
|
||||
+dl_check_legacy_object (struct link_map *m,
|
||||
+ struct dl_cet_info *info)
|
||||
{
|
||||
- /* Check how IBT should be enabled. */
|
||||
- enum dl_x86_cet_control enable_ibt_type
|
||||
- = GL(dl_x86_feature_control).ibt;
|
||||
- /* Check how SHSTK should be enabled. */
|
||||
- enum dl_x86_cet_control enable_shstk_type
|
||||
- = GL(dl_x86_feature_control).shstk;
|
||||
-
|
||||
- /* No legacy object check if both IBT and SHSTK are always on. */
|
||||
- if (enable_ibt_type == cet_always_on
|
||||
- && enable_shstk_type == cet_always_on)
|
||||
+ unsigned int i;
|
||||
+ struct link_map *l = NULL;
|
||||
+
|
||||
+ i = m->l_searchlist.r_nlist;
|
||||
+ while (i-- > 0)
|
||||
{
|
||||
- THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1));
|
||||
- return;
|
||||
- }
|
||||
+ /* Check each shared object to see if IBT and SHSTK are enabled. */
|
||||
+ l = m->l_initfini[i];
|
||||
|
||||
- /* Check if IBT is enabled by kernel. */
|
||||
- bool ibt_enabled
|
||||
- = (GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0;
|
||||
- /* Check if SHSTK is enabled by kernel. */
|
||||
- bool shstk_enabled
|
||||
- = (GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
|
||||
+ if (l->l_init_called)
|
||||
+ continue;
|
||||
|
||||
- if (ibt_enabled || shstk_enabled)
|
||||
- {
|
||||
- struct link_map *l = NULL;
|
||||
- unsigned int ibt_legacy = 0, shstk_legacy = 0;
|
||||
- bool found_ibt_legacy = false, found_shstk_legacy = false;
|
||||
-
|
||||
- /* Check if IBT and SHSTK are enabled in object. */
|
||||
- bool enable_ibt = (ibt_enabled
|
||||
- && enable_ibt_type != cet_always_off);
|
||||
- bool enable_shstk = (shstk_enabled
|
||||
- && enable_shstk_type != cet_always_off);
|
||||
- if (program)
|
||||
+#ifdef SHARED
|
||||
+ /* Skip check for ld.so since it has the features enabled. The
|
||||
+ features will be disabled later if they are not enabled in
|
||||
+ executable. */
|
||||
+ if (l == &GL(dl_rtld_map)
|
||||
+ || l->l_real == &GL(dl_rtld_map)
|
||||
+ || (info->program != NULL && l == m))
|
||||
+ continue;
|
||||
+#endif
|
||||
+
|
||||
+ /* IBT and SHSTK set only if enabled in executable and all DSOs.
|
||||
+ NB: cet_always_on is handled outside of the loop. */
|
||||
+ info->enable_feature_1 &= ((l->l_x86_feature_1_and
|
||||
+ & (GNU_PROPERTY_X86_FEATURE_1_IBT
|
||||
+ | GNU_PROPERTY_X86_FEATURE_1_SHSTK))
|
||||
+ | ~(GNU_PROPERTY_X86_FEATURE_1_IBT
|
||||
+ | GNU_PROPERTY_X86_FEATURE_1_SHSTK));
|
||||
+ if ((info->feature_1_legacy
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_IBT) == 0
|
||||
+ && ((info->enable_feature_1
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_IBT)
|
||||
+ != (info->feature_1_enabled
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_IBT)))
|
||||
{
|
||||
- /* Enable IBT and SHSTK only if they are enabled in executable.
|
||||
- NB: IBT and SHSTK may be disabled by environment variable:
|
||||
-
|
||||
- GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK
|
||||
- */
|
||||
- enable_ibt &= (CPU_FEATURE_USABLE (IBT)
|
||||
- && (enable_ibt_type == cet_always_on
|
||||
- || (m->l_x86_feature_1_and
|
||||
- & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0));
|
||||
- enable_shstk &= (CPU_FEATURE_USABLE (SHSTK)
|
||||
- && (enable_shstk_type == cet_always_on
|
||||
- || (m->l_x86_feature_1_and
|
||||
- & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0));
|
||||
+ info->feature_1_legacy_ibt = i;
|
||||
+ info->feature_1_legacy |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
||||
}
|
||||
|
||||
- /* ld.so is CET-enabled by kernel. But shared objects may not
|
||||
- support IBT nor SHSTK. */
|
||||
- if (enable_ibt || enable_shstk)
|
||||
- {
|
||||
- unsigned int i;
|
||||
+ if ((info->feature_1_legacy
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK) == 0
|
||||
+ && ((info->enable_feature_1
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
|
||||
+ != (info->feature_1_enabled
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK)))
|
||||
+ {
|
||||
+ info->feature_1_legacy_shstk = i;
|
||||
+ info->feature_1_legacy |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- i = m->l_searchlist.r_nlist;
|
||||
- while (i-- > 0)
|
||||
- {
|
||||
- /* Check each shared object to see if IBT and SHSTK are
|
||||
- enabled. */
|
||||
- l = m->l_initfini[i];
|
||||
+ /* Handle cet_always_on. */
|
||||
+ if ((info->feature_1_enabled
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0
|
||||
+ && info->enable_ibt_type == cet_always_on)
|
||||
+ {
|
||||
+ info->feature_1_legacy &= ~GNU_PROPERTY_X86_FEATURE_1_IBT;
|
||||
+ info->enable_feature_1 |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
||||
+ }
|
||||
|
||||
- if (l->l_init_called)
|
||||
- continue;
|
||||
+ if ((info->feature_1_enabled
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0
|
||||
+ && info->enable_shstk_type == cet_always_on)
|
||||
+ {
|
||||
+ info->feature_1_legacy &= ~GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
+ info->enable_feature_1 |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
+ }
|
||||
+}
|
||||
|
||||
#ifdef SHARED
|
||||
- /* Skip CET check for ld.so since ld.so is CET-enabled.
|
||||
- CET will be disabled later if CET isn't enabled in
|
||||
- executable. */
|
||||
- if (l == &GL(dl_rtld_map)
|
||||
- || l->l_real == &GL(dl_rtld_map)
|
||||
- || (program && l == m))
|
||||
- continue;
|
||||
+/* Enable IBT and SHSTK only if they are enabled in executable. Set
|
||||
+ feature bits properly at the start of the program. */
|
||||
+
|
||||
+static void
|
||||
+dl_cet_check_startup (struct link_map *m, struct dl_cet_info *info)
|
||||
+{
|
||||
+ /* NB: IBT and SHSTK may be disabled by environment variable:
|
||||
+
|
||||
+ GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK.
|
||||
+ */
|
||||
+ if (CPU_FEATURE_USABLE (IBT))
|
||||
+ {
|
||||
+ if (info->enable_ibt_type == cet_always_on)
|
||||
+ info->enable_feature_1 |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
||||
+ else
|
||||
+ info->enable_feature_1 &= ((m->l_x86_feature_1_and
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_IBT)
|
||||
+ | ~GNU_PROPERTY_X86_FEATURE_1_IBT);
|
||||
+ }
|
||||
+ else
|
||||
+ info->enable_feature_1 &= ~GNU_PROPERTY_X86_FEATURE_1_IBT;
|
||||
+
|
||||
+ if (CPU_FEATURE_USABLE (SHSTK))
|
||||
+ {
|
||||
+ if (info->enable_shstk_type == cet_always_on)
|
||||
+ info->enable_feature_1 |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
+ else
|
||||
+ info->enable_feature_1 &= ((m->l_x86_feature_1_and
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
|
||||
+ | ~GNU_PROPERTY_X86_FEATURE_1_SHSTK);
|
||||
+ }
|
||||
+ else
|
||||
+ info->enable_feature_1 &= ~GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
+
|
||||
+ if (info->enable_feature_1 != 0)
|
||||
+ dl_check_legacy_object (m, info);
|
||||
+
|
||||
+ unsigned int disable_feature_1
|
||||
+ = info->enable_feature_1 ^ info->feature_1_enabled;
|
||||
+ if (disable_feature_1 != 0)
|
||||
+ {
|
||||
+ /* Disable features in the kernel because of legacy objects or
|
||||
+ cet_always_off. */
|
||||
+ if (dl_cet_disable_cet (disable_feature_1) != 0)
|
||||
+ _dl_fatal_printf ("%s: can't disable x86 Features\n",
|
||||
+ info->program);
|
||||
+
|
||||
+ /* Clear the disabled bits. Sync dl_x86_feature_1 and
|
||||
+ info->feature_1_enabled with info->enable_feature_1. */
|
||||
+ info->feature_1_enabled = info->enable_feature_1;
|
||||
+ GL(dl_x86_feature_1) = info->enable_feature_1;
|
||||
+ }
|
||||
+
|
||||
+ if (HAS_CPU_FEATURE (IBT) || HAS_CPU_FEATURE (SHSTK))
|
||||
+ {
|
||||
+ /* Lock CET features only if IBT or SHSTK are enabled and are not
|
||||
+ enabled permissively. */
|
||||
+ unsigned int feature_1_lock = 0;
|
||||
+
|
||||
+ if (((info->feature_1_enabled & GNU_PROPERTY_X86_FEATURE_1_IBT)
|
||||
+ != 0)
|
||||
+ && info->enable_ibt_type != cet_permissive)
|
||||
+ feature_1_lock |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
||||
+
|
||||
+ if (((info->feature_1_enabled & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
|
||||
+ != 0)
|
||||
+ && info->enable_shstk_type != cet_permissive)
|
||||
+ feature_1_lock |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
+
|
||||
+ if (feature_1_lock != 0
|
||||
+ && dl_cet_lock_cet () != 0)
|
||||
+ _dl_fatal_printf ("%s: can't lock CET\n", info->program);
|
||||
+ }
|
||||
+
|
||||
+ THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1));
|
||||
+}
|
||||
#endif
|
||||
|
||||
- /* IBT is enabled only if it is enabled in executable as
|
||||
- well as all shared objects. */
|
||||
- enable_ibt &= (enable_ibt_type == cet_always_on
|
||||
- || (l->l_x86_feature_1_and
|
||||
- & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0);
|
||||
- if (!found_ibt_legacy && enable_ibt != ibt_enabled)
|
||||
- {
|
||||
- found_ibt_legacy = true;
|
||||
- ibt_legacy = i;
|
||||
- }
|
||||
-
|
||||
- /* SHSTK is enabled only if it is enabled in executable as
|
||||
- well as all shared objects. */
|
||||
- enable_shstk &= (enable_shstk_type == cet_always_on
|
||||
- || (l->l_x86_feature_1_and
|
||||
- & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0);
|
||||
- if (enable_shstk != shstk_enabled)
|
||||
- {
|
||||
- found_shstk_legacy = true;
|
||||
- shstk_legacy = i;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+/* Check feature bits when dlopening the shared object M. */
|
||||
+
|
||||
+static void
|
||||
+dl_cet_check_dlopen (struct link_map *m, struct dl_cet_info *info)
|
||||
+{
|
||||
+ /* Check if there are any legacy objects loaded. */
|
||||
+ if (info->enable_feature_1 != 0)
|
||||
+ {
|
||||
+ dl_check_legacy_object (m, info);
|
||||
|
||||
- bool cet_feature_changed = false;
|
||||
+ /* Skip if there are no legacy shared objects loaded. */
|
||||
+ if (info->feature_1_legacy == 0)
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- if (enable_ibt != ibt_enabled || enable_shstk != shstk_enabled)
|
||||
- {
|
||||
- if (!program)
|
||||
- {
|
||||
- if (enable_ibt_type != cet_permissive)
|
||||
- {
|
||||
- /* When IBT is enabled, we cannot dlopen a shared
|
||||
- object without IBT. */
|
||||
- if (found_ibt_legacy)
|
||||
- _dl_signal_error (0,
|
||||
- m->l_initfini[ibt_legacy]->l_name,
|
||||
- "dlopen",
|
||||
- N_("rebuild shared object with IBT support enabled"));
|
||||
- }
|
||||
-
|
||||
- if (enable_shstk_type != cet_permissive)
|
||||
- {
|
||||
- /* When SHSTK is enabled, we cannot dlopen a shared
|
||||
- object without SHSTK. */
|
||||
- if (found_shstk_legacy)
|
||||
- _dl_signal_error (0,
|
||||
- m->l_initfini[shstk_legacy]->l_name,
|
||||
- "dlopen",
|
||||
- N_("rebuild shared object with SHSTK support enabled"));
|
||||
- }
|
||||
-
|
||||
- if (enable_ibt_type != cet_permissive
|
||||
- && enable_shstk_type != cet_permissive)
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- /* Disable IBT and/or SHSTK if they are enabled by kernel, but
|
||||
- disabled in executable or shared objects. */
|
||||
- unsigned int cet_feature = 0;
|
||||
-
|
||||
- if (!enable_ibt)
|
||||
- cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
||||
- if (!enable_shstk)
|
||||
- cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
-
|
||||
- int res = dl_cet_disable_cet (cet_feature);
|
||||
- if (res != 0)
|
||||
- {
|
||||
- if (program)
|
||||
- _dl_fatal_printf ("%s: can't disable CET\n", program);
|
||||
- else
|
||||
- {
|
||||
- if (found_ibt_legacy)
|
||||
- l = m->l_initfini[ibt_legacy];
|
||||
- else
|
||||
- l = m->l_initfini[shstk_legacy];
|
||||
- _dl_signal_error (-res, l->l_name, "dlopen",
|
||||
- N_("can't disable CET"));
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /* Clear the disabled bits in dl_x86_feature_1. */
|
||||
- GL(dl_x86_feature_1) &= ~cet_feature;
|
||||
-
|
||||
- cet_feature_changed = true;
|
||||
- }
|
||||
+ unsigned int disable_feature_1 = 0;
|
||||
+ unsigned int legacy_obj = 0;
|
||||
+ const char *msg = NULL;
|
||||
|
||||
-#ifdef SHARED
|
||||
- if (program && (ibt_enabled || shstk_enabled))
|
||||
+ if ((info->feature_1_enabled
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0
|
||||
+ && (info->feature_1_legacy
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0)
|
||||
+ {
|
||||
+ if (info->enable_ibt_type != cet_permissive)
|
||||
{
|
||||
- if ((!ibt_enabled
|
||||
- || enable_ibt_type != cet_permissive)
|
||||
- && (!shstk_enabled
|
||||
- || enable_shstk_type != cet_permissive))
|
||||
- {
|
||||
- /* Lock CET if IBT or SHSTK is enabled in executable unless
|
||||
- IBT or SHSTK is enabled permissively. */
|
||||
- int res = dl_cet_lock_cet ();
|
||||
- if (res != 0)
|
||||
- _dl_fatal_printf ("%s: can't lock CET\n", program);
|
||||
- }
|
||||
-
|
||||
- /* Set feature_1 if IBT or SHSTK is enabled in executable. */
|
||||
- cet_feature_changed = true;
|
||||
+ legacy_obj = info->feature_1_legacy_ibt;
|
||||
+ msg = N_("rebuild shared object with IBT support enabled");
|
||||
}
|
||||
-#endif
|
||||
+ else
|
||||
+ disable_feature_1 |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
||||
+ }
|
||||
|
||||
- if (cet_feature_changed)
|
||||
+ /* Check the next feature only if there is no error. */
|
||||
+ if (msg == NULL
|
||||
+ && (info->feature_1_enabled
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0
|
||||
+ && (info->feature_1_legacy
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0)
|
||||
+ {
|
||||
+ if (info->enable_shstk_type != cet_permissive)
|
||||
{
|
||||
- unsigned int feature_1 = 0;
|
||||
- if (enable_ibt)
|
||||
- feature_1 |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
||||
- if (enable_shstk)
|
||||
- feature_1 |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
- struct pthread *self = THREAD_SELF;
|
||||
- THREAD_SETMEM (self, header.feature_1, feature_1);
|
||||
+ legacy_obj = info->feature_1_legacy_shstk;
|
||||
+ msg = N_("rebuild shared object with SHSTK support enabled");
|
||||
}
|
||||
+ else
|
||||
+ disable_feature_1 |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
+ }
|
||||
+
|
||||
+ /* If there is an error, long jump back to the caller. */
|
||||
+ if (msg != NULL)
|
||||
+ _dl_signal_error (0, m->l_initfini[legacy_obj]->l_name, "dlopen",
|
||||
+ msg);
|
||||
+
|
||||
+ if (disable_feature_1 != 0)
|
||||
+ {
|
||||
+ int res = dl_cet_disable_cet (disable_feature_1);
|
||||
+ if (res)
|
||||
+ {
|
||||
+ if ((disable_feature_1
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0)
|
||||
+ msg = N_("can't disable IBT");
|
||||
+ else
|
||||
+ msg = N_("can't disable SHSTK");
|
||||
+ /* Long jump back to the caller on error. */
|
||||
+ _dl_signal_error (-res, m->l_initfini[legacy_obj]->l_name,
|
||||
+ "dlopen", msg);
|
||||
+ }
|
||||
+
|
||||
+ /* Clear the disabled bits in dl_x86_feature_1. */
|
||||
+ GL(dl_x86_feature_1) &= ~disable_feature_1;
|
||||
+
|
||||
+ THREAD_SETMEM (THREAD_SELF, header.feature_1,
|
||||
+ GL(dl_x86_feature_1));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+dl_cet_check (struct link_map *m, const char *program)
|
||||
+{
|
||||
+ struct dl_cet_info info;
|
||||
+
|
||||
+ /* Check how IBT and SHSTK should be enabled. */
|
||||
+ info.enable_ibt_type = GL(dl_x86_feature_control).ibt;
|
||||
+ info.enable_shstk_type = GL(dl_x86_feature_control).shstk;
|
||||
+
|
||||
+ info.feature_1_enabled = GL(dl_x86_feature_1);
|
||||
+
|
||||
+ /* No legacy object check if IBT and SHSTK are always on. */
|
||||
+ if (info.enable_ibt_type == cet_always_on
|
||||
+ && info.enable_shstk_type == cet_always_on)
|
||||
+ {
|
||||
+#ifdef SHARED
|
||||
+ /* Set it only during startup. */
|
||||
+ if (program != NULL)
|
||||
+ THREAD_SETMEM (THREAD_SELF, header.feature_1,
|
||||
+ info.feature_1_enabled);
|
||||
+#endif
|
||||
+ return;
|
||||
}
|
||||
+
|
||||
+ /* Check if IBT and SHSTK were enabled by kernel. */
|
||||
+ if (info.feature_1_enabled == 0)
|
||||
+ return;
|
||||
+
|
||||
+ info.program = program;
|
||||
+
|
||||
+ /* Check which features should be enabled. */
|
||||
+ info.enable_feature_1 = 0;
|
||||
+ if (info.enable_ibt_type != cet_always_off)
|
||||
+ info.enable_feature_1 |= (info.feature_1_enabled
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_IBT);
|
||||
+ if (info.enable_shstk_type != cet_always_off)
|
||||
+ info.enable_feature_1 |= (info.feature_1_enabled
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK);
|
||||
+
|
||||
+ /* Start with no legacy objects. */
|
||||
+ info.feature_1_legacy = 0;
|
||||
+ info.feature_1_legacy_ibt = 0;
|
||||
+ info.feature_1_legacy_shstk = 0;
|
||||
+
|
||||
+#ifdef SHARED
|
||||
+ if (program)
|
||||
+ dl_cet_check_startup (m, &info);
|
||||
+ else
|
||||
+#endif
|
||||
+ dl_cet_check_dlopen (m, &info);
|
||||
}
|
||||
|
||||
void
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,96 @@
|
||||
From da84f75756ca022e84be6fefd2b8167852949612 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Fri, 7 Jan 2022 14:31:25 -0800
|
||||
Subject: [PATCH v2 11/15] x86-64: Add <fixup-asm-unistd.h> and regenerate
|
||||
arch-syscall.h
|
||||
|
||||
Add the map_shadow_stack system call to Linux/x86-64.
|
||||
---
|
||||
sysdeps/unix/sysv/linux/syscall-names.list | 1 +
|
||||
.../unix/sysv/linux/x86_64/64/arch-syscall.h | 1 +
|
||||
.../sysv/linux/x86_64/64/fixup-asm-unistd.h | 20 +++++++++++++++++++
|
||||
.../unix/sysv/linux/x86_64/x32/arch-syscall.h | 1 +
|
||||
.../sysv/linux/x86_64/x32/fixup-asm-unistd.h | 4 ++++
|
||||
5 files changed, 27 insertions(+)
|
||||
create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/fixup-asm-unistd.h
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
index 5d27b5279c..2bb924c8c4 100644
|
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
@@ -245,6 +245,7 @@ lsetxattr
|
||||
lstat
|
||||
lstat64
|
||||
madvise
|
||||
+map_shadow_stack
|
||||
mbind
|
||||
membarrier
|
||||
memfd_create
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
|
||||
index b4ab892ec1..c09890ab74 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
|
||||
@@ -152,6 +152,7 @@
|
||||
#define __NR_lsetxattr 189
|
||||
#define __NR_lstat 6
|
||||
#define __NR_madvise 28
|
||||
+#define __NR_map_shadow_stack 451
|
||||
#define __NR_mbind 237
|
||||
#define __NR_membarrier 324
|
||||
#define __NR_memfd_create 319
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/fixup-asm-unistd.h b/sysdeps/unix/sysv/linux/x86_64/64/fixup-asm-unistd.h
|
||||
new file mode 100644
|
||||
index 0000000000..20d941796d
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/fixup-asm-unistd.h
|
||||
@@ -0,0 +1,20 @@
|
||||
+/* Regularize <asm/unistd.h> definitions. X86-64/64 version.
|
||||
+ Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
+
|
||||
+ 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/>. */
|
||||
+
|
||||
+#ifndef __NR_map_shadow_stack
|
||||
+# define __NR_map_shadow_stack 451
|
||||
+#endif
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
|
||||
index 772559c87b..7ad88cb20d 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
|
||||
@@ -146,6 +146,7 @@
|
||||
#define __NR_lsetxattr 1073742013
|
||||
#define __NR_lstat 1073741830
|
||||
#define __NR_madvise 1073741852
|
||||
+#define __NR_map_shadow_stack 1073742275
|
||||
#define __NR_mbind 1073742061
|
||||
#define __NR_membarrier 1073742148
|
||||
#define __NR_memfd_create 1073742143
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h b/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h
|
||||
index ae854321a2..882a2ad8c8 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/fixup-asm-unistd.h
|
||||
@@ -15,6 +15,10 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
+#ifndef __NR_map_shadow_stack
|
||||
+# define __NR_map_shadow_stack 1073742275
|
||||
+#endif
|
||||
+
|
||||
/* X32 uses the same 64-bit syscall interface for set_thread_area. */
|
||||
#ifndef __NR_set_thread_area
|
||||
# define __NR_set_thread_area 1073742029
|
||||
--
|
||||
2.40.1
|
||||
|
803
v2-0012-x86-cet-Sync-with-the-kernel-shadow-stack-interfa.patch
Normal file
803
v2-0012-x86-cet-Sync-with-the-kernel-shadow-stack-interfa.patch
Normal file
@ -0,0 +1,803 @@
|
||||
From fc14bc65a7e0d3fbe5d939272f25d2e81100e44a Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Sat, 15 Aug 2020 08:04:23 -0700
|
||||
Subject: [PATCH v2 12/15] x86/cet: Sync with the kernel shadow stack interface
|
||||
|
||||
Sync with the upstream shadow stack kernel. Although shadow stack is
|
||||
only supported for x86-64, the i386 shadow stack support is also adjusted.
|
||||
Don't enable CET for i386 since CET won't work on i386.
|
||||
|
||||
1. When the shadow stack base in TCB is unset, the default shadow stack
|
||||
is in use. Use the current shadow stack pointer as the marker for the
|
||||
default shadow stack.
|
||||
2. Allocate shadow stack with the map_shadow_stack syscall.
|
||||
3. Rename arch_prctl CET commands to ARCH_SHSTK_XXX.
|
||||
4. Rewrite the CET control functions with the current kernel shadow stack
|
||||
interface.
|
||||
|
||||
Since CET is no longer enabled by kernel, a separate patch will enable
|
||||
shadow stack during startup.
|
||||
---
|
||||
sysdeps/i386/nptl/tls.h | 2 +-
|
||||
sysdeps/unix/sysv/linux/i386/getcontext.S | 28 +-----
|
||||
sysdeps/unix/sysv/linux/i386/makecontext.S | 88 +++++++------------
|
||||
sysdeps/unix/sysv/linux/i386/swapcontext.S | 22 +----
|
||||
sysdeps/unix/sysv/linux/x86/Makefile | 1 +
|
||||
.../sysv/linux/x86/allocate-shadow-stack.c | 54 ++++++++++++
|
||||
.../sysv/linux/x86/allocate-shadow-stack.h | 27 ++++++
|
||||
sysdeps/unix/sysv/linux/x86/bits/mman.h | 5 ++
|
||||
sysdeps/unix/sysv/linux/x86/cpu-features.c | 13 ++-
|
||||
sysdeps/unix/sysv/linux/x86/dl-cet.h | 16 +++-
|
||||
.../unix/sysv/linux/x86/include/asm/prctl.h | 37 ++++----
|
||||
.../sysv/linux/x86/tst-cet-setcontext-1.c | 17 ++--
|
||||
.../unix/sysv/linux/x86_64/__start_context.S | 38 ++------
|
||||
sysdeps/unix/sysv/linux/x86_64/getcontext.S | 30 ++-----
|
||||
sysdeps/unix/sysv/linux/x86_64/makecontext.c | 29 +++---
|
||||
sysdeps/unix/sysv/linux/x86_64/swapcontext.S | 22 +----
|
||||
sysdeps/x86/cpu-features.c | 15 ++--
|
||||
sysdeps/x86/dl-cet.c | 2 +-
|
||||
sysdeps/x86_64/nptl/tls.h | 2 +-
|
||||
19 files changed, 218 insertions(+), 230 deletions(-)
|
||||
create mode 100644 sysdeps/unix/sysv/linux/x86/allocate-shadow-stack.c
|
||||
create mode 100644 sysdeps/unix/sysv/linux/x86/allocate-shadow-stack.h
|
||||
|
||||
diff --git a/sysdeps/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h
|
||||
index 95e7c5be51..da4b83dd49 100644
|
||||
--- a/sysdeps/i386/nptl/tls.h
|
||||
+++ b/sysdeps/i386/nptl/tls.h
|
||||
@@ -49,7 +49,7 @@ typedef struct
|
||||
void *__private_tm[3];
|
||||
/* GCC split stack support. */
|
||||
void *__private_ss;
|
||||
- /* The lowest address of shadow stack, */
|
||||
+ /* The marker for the current shadow stack. */
|
||||
unsigned long ssp_base;
|
||||
} tcbhead_t;
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/i386/getcontext.S b/sysdeps/unix/sysv/linux/i386/getcontext.S
|
||||
index b69a73847b..49ece43dd2 100644
|
||||
--- a/sysdeps/unix/sysv/linux/i386/getcontext.S
|
||||
+++ b/sysdeps/unix/sysv/linux/i386/getcontext.S
|
||||
@@ -54,31 +54,11 @@ ENTRY(__getcontext)
|
||||
cmpl %gs:SSP_BASE_OFFSET, %eax
|
||||
jnz L(shadow_stack_bound_recorded)
|
||||
|
||||
- /* Save EBX in the first scratch register slot. */
|
||||
- movl %ebx, oSCRATCH1(%edx)
|
||||
-
|
||||
- /* Get the base address and size of the default shadow stack
|
||||
- which must be the current shadow stack since nothing has
|
||||
- been recorded yet. */
|
||||
- sub $24, %esp
|
||||
- mov %esp, %ecx
|
||||
- movl $ARCH_CET_STATUS, %ebx
|
||||
- movl $__NR_arch_prctl, %eax
|
||||
- ENTER_KERNEL
|
||||
- testl %eax, %eax
|
||||
- jz L(continue_no_err)
|
||||
-
|
||||
- /* This should never happen. */
|
||||
- hlt
|
||||
-
|
||||
-L(continue_no_err):
|
||||
- /* Restore EBX from the first scratch register slot. */
|
||||
- movl oSCRATCH1(%edx), %ebx
|
||||
-
|
||||
- /* Record the base of the current shadow stack. */
|
||||
- movl 8(%esp), %eax
|
||||
+ /* When the shadow stack base is unset, the default shadow
|
||||
+ stack is in use. Use the current shadow stack pointer
|
||||
+ as the marker for the default shadow stack. */
|
||||
+ rdsspd %eax
|
||||
movl %eax, %gs:SSP_BASE_OFFSET
|
||||
- add $24, %esp
|
||||
|
||||
L(shadow_stack_bound_recorded):
|
||||
/* Load address of the context data structure. */
|
||||
diff --git a/sysdeps/unix/sysv/linux/i386/makecontext.S b/sysdeps/unix/sysv/linux/i386/makecontext.S
|
||||
index 346cdd0e0a..bf481420dc 100644
|
||||
--- a/sysdeps/unix/sysv/linux/i386/makecontext.S
|
||||
+++ b/sysdeps/unix/sysv/linux/i386/makecontext.S
|
||||
@@ -73,28 +73,37 @@ ENTRY(__makecontext)
|
||||
testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
|
||||
jz L(skip_ssp)
|
||||
|
||||
- /* Reload the pointer to ucontext. */
|
||||
- movl 4(%esp), %eax
|
||||
+ /* Shadow stack is enabled. Load the pointer to ucontext in
|
||||
+ ECX. */
|
||||
+ movl 4(%esp), %ecx
|
||||
+
|
||||
+ /* Pass the address of __ssp[1] in EDX. */
|
||||
+ leal (oSSP + 4)(%ecx), %edx
|
||||
+ /* Pass stack size in EAX. */
|
||||
+ movl oSS_SIZE(%ecx), %eax
|
||||
+
|
||||
+ /* Call __allocate_shadow_stack to allocate a new shadow stack. */
|
||||
+ call __allocate_shadow_stack
|
||||
+ /* Check for error return. */
|
||||
+ testl %eax, %eax
|
||||
+ jne L(hlt) /* This should never happen. */
|
||||
|
||||
- /* Shadow stack is enabled. We need to allocate a new shadow
|
||||
- stack. */
|
||||
- subl oSS_SP(%eax), %edx
|
||||
- shrl $STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT, %edx
|
||||
+ /* Reload the pointer to ucontext into ECX. */
|
||||
+ movl 4(%esp), %ecx
|
||||
|
||||
- /* Align shadow stack size to 8 bytes. */
|
||||
- addl $7, %edx
|
||||
- andl $-8, %edx
|
||||
+ /* Load the base address of the new shadow stack into EAX. */
|
||||
+ movl (oSSP + 4)(%ecx), %eax
|
||||
|
||||
- /* Store shadow stack size in __ssp[2]. */
|
||||
- movl %edx, (oSSP + 8)(%eax)
|
||||
+ /* Store the new shadow stack pointer, the shadow stack base +
|
||||
+ the shadow stack size - 4, in __ssp[0]. */
|
||||
+ addl (oSSP + 8)(%ecx), %eax
|
||||
+ subl $4, %eax
|
||||
+ movl %eax, oSSP(%ecx)
|
||||
|
||||
/* Save ESI in the second scratch register slot. */
|
||||
- movl %esi, oSCRATCH2(%eax)
|
||||
+ movl %esi, oSCRATCH2(%ecx)
|
||||
/* Save EDI in the third scratch register slot. */
|
||||
- movl %edi, oSCRATCH3(%eax)
|
||||
-
|
||||
- /* Save the pointer to ucontext. */
|
||||
- movl %eax, %edi
|
||||
+ movl %edi, oSCRATCH3(%ecx)
|
||||
|
||||
/* Get the original shadow stack pointer. */
|
||||
rdsspd %esi
|
||||
@@ -104,7 +113,7 @@ ENTRY(__makecontext)
|
||||
andl $-8, %esi
|
||||
|
||||
/* Load the top of the new stack into EDX. */
|
||||
- movl oESP(%eax), %edx
|
||||
+ movl oESP(%ecx), %edx
|
||||
|
||||
/* We need to terminate the FDE here because the unwinder looks
|
||||
at ra-1 for unwind information. */
|
||||
@@ -118,39 +127,14 @@ ENTRY(__makecontext)
|
||||
onto stack. */
|
||||
addl $4, %esp
|
||||
|
||||
- /* Allocate the new shadow stack. Save EBX in the first scratch
|
||||
- register slot. */
|
||||
- movl %ebx, oSCRATCH1(%eax)
|
||||
-
|
||||
- /* CET syscall takes 64-bit sizes. */
|
||||
- subl $16, %esp
|
||||
- movl (oSSP + 8)(%eax), %ecx
|
||||
- movl %ecx, (%esp)
|
||||
- movl $0, 4(%esp)
|
||||
- movl %ecx, 8(%esp)
|
||||
- movl $0, 12(%esp)
|
||||
- movl %esp, %ecx
|
||||
-
|
||||
- movl $ARCH_CET_ALLOC_SHSTK, %ebx
|
||||
- movl $__NR_arch_prctl, %eax
|
||||
- ENTER_KERNEL
|
||||
- testl %eax, %eax
|
||||
- jne L(hlt) /* This should never happen. */
|
||||
-
|
||||
- /* Copy the base address of the new shadow stack to __ssp[1]. */
|
||||
- movl (%esp), %eax
|
||||
- movl %eax, (oSSP + 4)(%edi)
|
||||
-
|
||||
- addl $16, %esp
|
||||
+ /* Load the new shadow stack base in __ssp[1] into EAX. */
|
||||
+ movl (oSSP + 4)(%ecx), %eax
|
||||
|
||||
- /* Restore EBX from the first scratch register slot. */
|
||||
- movl oSCRATCH1(%edi), %ebx
|
||||
-
|
||||
- /* Get the size of the new shadow stack. */
|
||||
- movl (oSSP + 8)(%edi), %ecx
|
||||
+ /* Load the new shadow stack size in __ssp[2] into EDI. */
|
||||
+ movl (oSSP + 8)(%ecx), %edi
|
||||
|
||||
/* Use the restore stoken to restore the new shadow stack. */
|
||||
- rstorssp -8(%eax, %ecx)
|
||||
+ rstorssp -8(%eax, %edi)
|
||||
|
||||
/* Save the restore token at the next 8 byte aligned boundary
|
||||
on the original shadow stack. */
|
||||
@@ -162,27 +146,21 @@ ENTRY(__makecontext)
|
||||
jmp L(exitcode)
|
||||
1:
|
||||
|
||||
- /* Get the new shadow stack pointer. */
|
||||
- rdsspd %eax
|
||||
-
|
||||
/* Use the restore stoken to restore the original shadow stack. */
|
||||
rstorssp -8(%esi)
|
||||
|
||||
/* Save the restore token on the new shadow stack. */
|
||||
saveprevssp
|
||||
|
||||
- /* Store the new shadow stack pointer in __ssp[0]. */
|
||||
- movl %eax, oSSP(%edi)
|
||||
-
|
||||
/* Restore the original stack. */
|
||||
mov %edx, %esp
|
||||
|
||||
cfi_startproc
|
||||
|
||||
/* Restore ESI from the second scratch register slot. */
|
||||
- movl oSCRATCH2(%edi), %esi
|
||||
+ movl oSCRATCH2(%ecx), %esi
|
||||
/* Restore EDI from the third scratch register slot. */
|
||||
- movl oSCRATCH3(%edi), %edi
|
||||
+ movl oSCRATCH3(%ecx), %edi
|
||||
|
||||
ret
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/i386/swapcontext.S b/sysdeps/unix/sysv/linux/i386/swapcontext.S
|
||||
index 551df10c91..d4f31fa5d5 100644
|
||||
--- a/sysdeps/unix/sysv/linux/i386/swapcontext.S
|
||||
+++ b/sysdeps/unix/sysv/linux/i386/swapcontext.S
|
||||
@@ -85,25 +85,11 @@ ENTRY(__swapcontext)
|
||||
cmpl %gs:SSP_BASE_OFFSET, %eax
|
||||
jnz L(shadow_stack_bound_recorded)
|
||||
|
||||
- /* Get the base address and size of the default shadow stack
|
||||
- which must be the current shadow stack since nothing has
|
||||
- been recorded yet. */
|
||||
- sub $24, %esp
|
||||
- mov %esp, %ecx
|
||||
- movl $ARCH_CET_STATUS, %ebx
|
||||
- movl $__NR_arch_prctl, %eax
|
||||
- ENTER_KERNEL
|
||||
- testl %eax, %eax
|
||||
- jz L(continue_no_err)
|
||||
-
|
||||
- /* This should never happen. */
|
||||
- hlt
|
||||
-
|
||||
-L(continue_no_err):
|
||||
- /* Record the base of the current shadow stack. */
|
||||
- movl 8(%esp), %eax
|
||||
+ /* When the shadow stack base is unset, the default shadow
|
||||
+ stack is in use. Use the current shadow stack pointer
|
||||
+ as the marker for the default shadow stack. */
|
||||
+ rdsspd %eax
|
||||
movl %eax, %gs:SSP_BASE_OFFSET
|
||||
- add $24, %esp
|
||||
|
||||
L(shadow_stack_bound_recorded):
|
||||
/* Load address of the context data structure we save in. */
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86/Makefile b/sysdeps/unix/sysv/linux/x86/Makefile
|
||||
index 9dfdd689a9..ed0d6500b9 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86/Makefile
|
||||
+++ b/sysdeps/unix/sysv/linux/x86/Makefile
|
||||
@@ -44,6 +44,7 @@ CFLAGS-tst-cet-vfork-1.c += -mshstk
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),stdlib)
|
||||
+sysdep_routines += allocate-shadow-stack
|
||||
tests += tst-cet-setcontext-1
|
||||
CFLAGS-tst-cet-setcontext-1.c += -mshstk
|
||||
endif
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86/allocate-shadow-stack.c b/sysdeps/unix/sysv/linux/x86/allocate-shadow-stack.c
|
||||
new file mode 100644
|
||||
index 0000000000..3a76db1a60
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/x86/allocate-shadow-stack.c
|
||||
@@ -0,0 +1,54 @@
|
||||
+/* Helper function to allocate shadow stack.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <sysdep.h>
|
||||
+#include <stdint.h>
|
||||
+#include <errno.h>
|
||||
+#include <sys/mman.h>
|
||||
+#include <libc-pointer-arith.h>
|
||||
+#include <allocate-shadow-stack.h>
|
||||
+
|
||||
+/* NB: This can be treated as a syscall by caller. */
|
||||
+
|
||||
+#ifndef __x86_64__
|
||||
+__attribute__ ((regparm (2)))
|
||||
+#endif
|
||||
+long int
|
||||
+__allocate_shadow_stack (size_t stack_size,
|
||||
+ shadow_stack_size_t *child_stack)
|
||||
+{
|
||||
+#ifdef __NR_map_shadow_stack
|
||||
+ size_t shadow_stack_size
|
||||
+ = stack_size >> STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT;
|
||||
+ /* Align shadow stack to 8 bytes. */
|
||||
+ shadow_stack_size = ALIGN_UP (shadow_stack_size, 8);
|
||||
+ void *shadow_stack = (void *)INLINE_SYSCALL_CALL
|
||||
+ (map_shadow_stack, NULL, shadow_stack_size, SHADOW_STACK_SET_TOKEN);
|
||||
+ /* Report the map_shadow_stack error. */
|
||||
+ if (shadow_stack == MAP_FAILED)
|
||||
+ return -errno;
|
||||
+
|
||||
+ /* Save the shadow stack base and size on child stack. */
|
||||
+ child_stack[0] = (uintptr_t) shadow_stack;
|
||||
+ child_stack[1] = shadow_stack_size;
|
||||
+
|
||||
+ return 0;
|
||||
+#else
|
||||
+ return -ENOSYS;
|
||||
+#endif
|
||||
+}
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86/allocate-shadow-stack.h b/sysdeps/unix/sysv/linux/x86/allocate-shadow-stack.h
|
||||
new file mode 100644
|
||||
index 0000000000..834373e0d3
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/x86/allocate-shadow-stack.h
|
||||
@@ -0,0 +1,27 @@
|
||||
+/* Helper function to allocate shadow stack.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <ucontext.h>
|
||||
+
|
||||
+typedef __typeof (((ucontext_t *) 0)->__ssp[0]) shadow_stack_size_t;
|
||||
+
|
||||
+extern long int __allocate_shadow_stack (size_t, shadow_stack_size_t *)
|
||||
+#ifndef __x86_64__
|
||||
+ __attribute__ ((regparm (2)))
|
||||
+#endif
|
||||
+ attribute_hidden;
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86/bits/mman.h b/sysdeps/unix/sysv/linux/x86/bits/mman.h
|
||||
index b335ceff43..17bb078375 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86/bits/mman.h
|
||||
+++ b/sysdeps/unix/sysv/linux/x86/bits/mman.h
|
||||
@@ -26,6 +26,11 @@
|
||||
/* Other flags. */
|
||||
#define MAP_32BIT 0x40 /* Only give out 32-bit addresses. */
|
||||
|
||||
+#ifdef __USE_MISC
|
||||
+/* Set up a restore token in the newly allocatd shadow stack */
|
||||
+# define SHADOW_STACK_SET_TOKEN 0x1
|
||||
+#endif
|
||||
+
|
||||
#include <bits/mman-map-flags-generic.h>
|
||||
|
||||
/* Include generic Linux declarations. */
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86/cpu-features.c b/sysdeps/unix/sysv/linux/x86/cpu-features.c
|
||||
index 41e7600668..0e6e2bf855 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86/cpu-features.c
|
||||
+++ b/sysdeps/unix/sysv/linux/x86/cpu-features.c
|
||||
@@ -23,10 +23,15 @@
|
||||
static inline int __attribute__ ((always_inline))
|
||||
get_cet_status (void)
|
||||
{
|
||||
- unsigned long long cet_status[3];
|
||||
- if (INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_CET_STATUS, cet_status) == 0)
|
||||
- return cet_status[0];
|
||||
- return 0;
|
||||
+ unsigned long long kernel_feature;
|
||||
+ unsigned int status = 0;
|
||||
+ if (INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_STATUS,
|
||||
+ &kernel_feature) == 0)
|
||||
+ {
|
||||
+ if ((kernel_feature & ARCH_SHSTK_SHSTK) != 0)
|
||||
+ status = GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
+ }
|
||||
+ return status;
|
||||
}
|
||||
|
||||
# ifndef SHARED
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86/dl-cet.h b/sysdeps/unix/sysv/linux/x86/dl-cet.h
|
||||
index c885bf1323..da220ac627 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86/dl-cet.h
|
||||
+++ b/sysdeps/unix/sysv/linux/x86/dl-cet.h
|
||||
@@ -21,12 +21,20 @@
|
||||
static inline int __attribute__ ((always_inline))
|
||||
dl_cet_disable_cet (unsigned int cet_feature)
|
||||
{
|
||||
- return (int) INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_CET_DISABLE,
|
||||
- cet_feature);
|
||||
+ if (cet_feature != GNU_PROPERTY_X86_FEATURE_1_SHSTK)
|
||||
+ return -1;
|
||||
+ long long int kernel_feature = ARCH_SHSTK_SHSTK;
|
||||
+ return (int) INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_DISABLE,
|
||||
+ kernel_feature);
|
||||
}
|
||||
|
||||
static inline int __attribute__ ((always_inline))
|
||||
-dl_cet_lock_cet (void)
|
||||
+dl_cet_lock_cet (unsigned int cet_feature)
|
||||
{
|
||||
- return (int) INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_CET_LOCK, 0);
|
||||
+ if (cet_feature != GNU_PROPERTY_X86_FEATURE_1_SHSTK)
|
||||
+ return -1;
|
||||
+ /* Lock all SHSTK features. */
|
||||
+ long long int kernel_feature = -1;
|
||||
+ return (int) INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_LOCK,
|
||||
+ kernel_feature);
|
||||
}
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h b/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h
|
||||
index 45ad0b052f..2f511321ad 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h
|
||||
+++ b/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h
|
||||
@@ -4,24 +4,19 @@
|
||||
|
||||
#include_next <asm/prctl.h>
|
||||
|
||||
-#ifndef ARCH_CET_STATUS
|
||||
-/* CET features:
|
||||
- IBT: GNU_PROPERTY_X86_FEATURE_1_IBT
|
||||
- SHSTK: GNU_PROPERTY_X86_FEATURE_1_SHSTK
|
||||
- */
|
||||
-/* Return CET features in unsigned long long *addr:
|
||||
- features: addr[0].
|
||||
- shadow stack base address: addr[1].
|
||||
- shadow stack size: addr[2].
|
||||
- */
|
||||
-# define ARCH_CET_STATUS 0x3001
|
||||
-/* Disable CET features in unsigned int features. */
|
||||
-# define ARCH_CET_DISABLE 0x3002
|
||||
-/* Lock all CET features. */
|
||||
-# define ARCH_CET_LOCK 0x3003
|
||||
-/* Allocate a new shadow stack with unsigned long long *addr:
|
||||
- IN: requested shadow stack size: *addr.
|
||||
- OUT: allocated shadow stack address: *addr.
|
||||
- */
|
||||
-# define ARCH_CET_ALLOC_SHSTK 0x3004
|
||||
-#endif /* ARCH_CET_STATUS */
|
||||
+#ifndef ARCH_SHSTK_ENABLE
|
||||
+/* Enable SHSTK features in unsigned long int features. */
|
||||
+# define ARCH_SHSTK_ENABLE 0x5001
|
||||
+/* Disable SHSTK features in unsigned long int features. */
|
||||
+# define ARCH_SHSTK_DISABLE 0x5002
|
||||
+/* Lock SHSTK features in unsigned long int features. */
|
||||
+# define ARCH_SHSTK_LOCK 0x5003
|
||||
+/* Unlock SHSTK features in unsigned long int features. */
|
||||
+# define ARCH_SHSTK_UNLOCK 0x5004
|
||||
+/* Return SHSTK features in unsigned long int features. */
|
||||
+# define ARCH_SHSTK_STATUS 0x5005
|
||||
+
|
||||
+/* ARCH_SHSTK_ features bits */
|
||||
+# define ARCH_SHSTK_SHSTK 0x1
|
||||
+# define ARCH_SHSTK_WRSS 0x2
|
||||
+#endif
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86/tst-cet-setcontext-1.c b/sysdeps/unix/sysv/linux/x86/tst-cet-setcontext-1.c
|
||||
index 837a9fd0eb..2ea66c803b 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86/tst-cet-setcontext-1.c
|
||||
+++ b/sysdeps/unix/sysv/linux/x86/tst-cet-setcontext-1.c
|
||||
@@ -87,15 +87,14 @@ do_test (void)
|
||||
ctx[4].uc_link = &ctx[0];
|
||||
makecontext (&ctx[4], (void (*) (void)) f1, 0);
|
||||
|
||||
- /* NB: When shadow stack is enabled, makecontext calls arch_prctl
|
||||
- with ARCH_CET_ALLOC_SHSTK to allocate a new shadow stack which
|
||||
- can be unmapped. The base address and size of the new shadow
|
||||
- stack are returned in __ssp[1] and __ssp[2]. makecontext is
|
||||
- called for CTX1, CTX3 and CTX4. But only CTX1 is used. New
|
||||
- shadow stacks are allocated in the order of CTX3, CTX1, CTX4.
|
||||
- It is very likely that CTX1's shadow stack is placed between
|
||||
- CTX3 and CTX4. We munmap CTX3's and CTX4's shadow stacks to
|
||||
- create gaps above and below CTX1's shadow stack. We check
|
||||
+ /* NB: When shadow stack is enabled, makecontext calls map_shadow_stack
|
||||
+ to allocate a new shadow stack which can be unmapped. The base
|
||||
+ address and size of the new shadow stack are returned in __ssp[1]
|
||||
+ and __ssp[2]. makecontext is called for CTX1, CTX3 and CTX4. But
|
||||
+ only CTX1 is used. New shadow stacks are allocated in the order
|
||||
+ of CTX3, CTX1, CTX4. It is very likely that CTX1's shadow stack is
|
||||
+ placed between CTX3 and CTX4. We munmap CTX3's and CTX4's shadow
|
||||
+ stacks to create gaps above and below CTX1's shadow stack. We check
|
||||
that setcontext CTX1 works correctly in this case. */
|
||||
if (_get_ssp () != 0)
|
||||
{
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/__start_context.S b/sysdeps/unix/sysv/linux/x86_64/__start_context.S
|
||||
index f6436dd6bb..ae04203c90 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86_64/__start_context.S
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/__start_context.S
|
||||
@@ -24,20 +24,14 @@
|
||||
/* Use CALL to push __start_context onto the new stack as well as the new
|
||||
shadow stack. RDI points to ucontext:
|
||||
Incoming:
|
||||
- __ssp[0]: The original caller's shadow stack pointer.
|
||||
- __ssp[1]: The size of the new shadow stack.
|
||||
- __ssp[2]: The size of the new shadow stack.
|
||||
- Outgoing:
|
||||
__ssp[0]: The new shadow stack pointer.
|
||||
__ssp[1]: The base address of the new shadow stack.
|
||||
__ssp[2]: The size of the new shadow stack.
|
||||
*/
|
||||
|
||||
ENTRY(__push___start_context)
|
||||
- /* Save the pointer to ucontext. */
|
||||
- movq %rdi, %r9
|
||||
/* Get the original shadow stack pointer. */
|
||||
- rdsspq %r8
|
||||
+ rdsspq %rcx
|
||||
/* Save the original stack pointer. */
|
||||
movq %rsp, %rdx
|
||||
/* Load the top of the new stack into RSI. */
|
||||
@@ -45,24 +39,12 @@ ENTRY(__push___start_context)
|
||||
/* Add 8 bytes to RSI since CALL will push the 8-byte return
|
||||
address onto stack. */
|
||||
leaq 8(%rsi), %rsp
|
||||
- /* Allocate the new shadow stack. The size of the new shadow
|
||||
- stack is passed in __ssp[1]. */
|
||||
- lea (oSSP + 8)(%rdi), %RSI_LP
|
||||
- movl $ARCH_CET_ALLOC_SHSTK, %edi
|
||||
- movl $__NR_arch_prctl, %eax
|
||||
- /* The new shadow stack base is returned in __ssp[1]. */
|
||||
- syscall
|
||||
- testq %rax, %rax
|
||||
- jne L(hlt) /* This should never happen. */
|
||||
-
|
||||
- /* Get the size of the new shadow stack. */
|
||||
- movq 8(%rsi), %rdi
|
||||
-
|
||||
- /* Get the base address of the new shadow stack. */
|
||||
- movq (%rsi), %rsi
|
||||
-
|
||||
+ /* The size of the new shadow stack is stored in __ssp[2]. */
|
||||
+ mov (oSSP + 16)(%rdi), %RSI_LP
|
||||
+ /* The new shadow stack base is stored in __ssp[1]. */
|
||||
+ mov (oSSP + 8)(%rdi), %RAX_LP
|
||||
/* Use the restore stoken to restore the new shadow stack. */
|
||||
- rstorssp -8(%rsi, %rdi)
|
||||
+ rstorssp -8(%rax, %rsi)
|
||||
|
||||
/* Save the restore token on the original shadow stack. */
|
||||
saveprevssp
|
||||
@@ -73,18 +55,12 @@ ENTRY(__push___start_context)
|
||||
jmp __start_context
|
||||
1:
|
||||
|
||||
- /* Get the new shadow stack pointer. */
|
||||
- rdsspq %rdi
|
||||
-
|
||||
/* Use the restore stoken to restore the original shadow stack. */
|
||||
- rstorssp -8(%r8)
|
||||
+ rstorssp -8(%rcx)
|
||||
|
||||
/* Save the restore token on the new shadow stack. */
|
||||
saveprevssp
|
||||
|
||||
- /* Store the new shadow stack pointer in __ssp[0]. */
|
||||
- movq %rdi, oSSP(%r9)
|
||||
-
|
||||
/* Restore the original stack. */
|
||||
mov %rdx, %rsp
|
||||
ret
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/getcontext.S b/sysdeps/unix/sysv/linux/x86_64/getcontext.S
|
||||
index a00e2f6290..71f3802dca 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86_64/getcontext.S
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/getcontext.S
|
||||
@@ -58,35 +58,15 @@ ENTRY(__getcontext)
|
||||
testl $X86_FEATURE_1_SHSTK, %fs:FEATURE_1_OFFSET
|
||||
jz L(no_shstk)
|
||||
|
||||
- /* Save RDI in RDX which won't be clobbered by syscall. */
|
||||
- movq %rdi, %rdx
|
||||
-
|
||||
xorl %eax, %eax
|
||||
cmpq %fs:SSP_BASE_OFFSET, %rax
|
||||
jnz L(shadow_stack_bound_recorded)
|
||||
|
||||
- /* Get the base address and size of the default shadow stack
|
||||
- which must be the current shadow stack since nothing has
|
||||
- been recorded yet. */
|
||||
- sub $24, %RSP_LP
|
||||
- mov %RSP_LP, %RSI_LP
|
||||
- movl $ARCH_CET_STATUS, %edi
|
||||
- movl $__NR_arch_prctl, %eax
|
||||
- syscall
|
||||
- testq %rax, %rax
|
||||
- jz L(continue_no_err)
|
||||
-
|
||||
- /* This should never happen. */
|
||||
- hlt
|
||||
-
|
||||
-L(continue_no_err):
|
||||
- /* Record the base of the current shadow stack. */
|
||||
- movq 8(%rsp), %rax
|
||||
+ /* When the shadow stack base is unset, the default shadow
|
||||
+ stack is in use. Use the current shadow stack pointer
|
||||
+ as the marker for the default shadow stack. */
|
||||
+ rdsspq %rax
|
||||
movq %rax, %fs:SSP_BASE_OFFSET
|
||||
- add $24, %RSP_LP
|
||||
-
|
||||
- /* Restore RDI. */
|
||||
- movq %rdx, %rdi
|
||||
|
||||
L(shadow_stack_bound_recorded):
|
||||
/* Get the current shadow stack pointer. */
|
||||
@@ -94,7 +74,7 @@ L(shadow_stack_bound_recorded):
|
||||
/* NB: Save the caller's shadow stack so that we can jump back
|
||||
to the caller directly. */
|
||||
addq $8, %rax
|
||||
- movq %rax, oSSP(%rdx)
|
||||
+ movq %rax, oSSP(%rdi)
|
||||
|
||||
/* Save the current shadow stack base in ucontext. */
|
||||
movq %fs:SSP_BASE_OFFSET, %rax
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/makecontext.c b/sysdeps/unix/sysv/linux/x86_64/makecontext.c
|
||||
index de9e03eb81..788b730132 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86_64/makecontext.c
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/makecontext.c
|
||||
@@ -24,6 +24,8 @@
|
||||
# include <pthread.h>
|
||||
# include <libc-pointer-arith.h>
|
||||
# include <sys/prctl.h>
|
||||
+# include <sys/mman.h>
|
||||
+# include <allocate-shadow-stack.h>
|
||||
#endif
|
||||
|
||||
#include "ucontext_i.h"
|
||||
@@ -88,23 +90,24 @@ __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
|
||||
if ((feature_1 & X86_FEATURE_1_SHSTK) != 0)
|
||||
{
|
||||
/* Shadow stack is enabled. We need to allocate a new shadow
|
||||
- stack. */
|
||||
- unsigned long ssp_size = (((uintptr_t) sp
|
||||
- - (uintptr_t) ucp->uc_stack.ss_sp)
|
||||
- >> STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT);
|
||||
- /* Align shadow stack to 8 bytes. */
|
||||
- ssp_size = ALIGN_UP (ssp_size, 8);
|
||||
-
|
||||
- ucp->__ssp[1] = ssp_size;
|
||||
- ucp->__ssp[2] = ssp_size;
|
||||
-
|
||||
- /* Call __push___start_context to allocate a new shadow stack,
|
||||
- push __start_context onto the new stack as well as the new
|
||||
- shadow stack. NB: After __push___start_context returns,
|
||||
+ stack. NB:
|
||||
ucp->__ssp[0]: The new shadow stack pointer.
|
||||
ucp->__ssp[1]: The base address of the new shadow stack.
|
||||
ucp->__ssp[2]: The size of the new shadow stack.
|
||||
*/
|
||||
+ long int ret
|
||||
+ = __allocate_shadow_stack (((uintptr_t) sp
|
||||
+ - (uintptr_t) ucp->uc_stack.ss_sp),
|
||||
+ &ucp->__ssp[1]);
|
||||
+ if (ret != 0)
|
||||
+ {
|
||||
+ /* FIXME: What should we do? */
|
||||
+ abort ();
|
||||
+ }
|
||||
+
|
||||
+ ucp->__ssp[0] = ucp->__ssp[1] + ucp->__ssp[2] - 8;
|
||||
+ /* Call __push___start_context to push __start_context onto the new
|
||||
+ stack as well as the new shadow stack. */
|
||||
__push___start_context (ucp);
|
||||
}
|
||||
else
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/swapcontext.S b/sysdeps/unix/sysv/linux/x86_64/swapcontext.S
|
||||
index 5925752164..2f2fe9875b 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86_64/swapcontext.S
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/swapcontext.S
|
||||
@@ -109,25 +109,11 @@ ENTRY(__swapcontext)
|
||||
cmpq %fs:SSP_BASE_OFFSET, %rax
|
||||
jnz L(shadow_stack_bound_recorded)
|
||||
|
||||
- /* Get the base address and size of the default shadow stack
|
||||
- which must be the current shadow stack since nothing has
|
||||
- been recorded yet. */
|
||||
- sub $24, %RSP_LP
|
||||
- mov %RSP_LP, %RSI_LP
|
||||
- movl $ARCH_CET_STATUS, %edi
|
||||
- movl $__NR_arch_prctl, %eax
|
||||
- syscall
|
||||
- testq %rax, %rax
|
||||
- jz L(continue_no_err)
|
||||
-
|
||||
- /* This should never happen. */
|
||||
- hlt
|
||||
-
|
||||
-L(continue_no_err):
|
||||
- /* Record the base of the current shadow stack. */
|
||||
- movq 8(%rsp), %rax
|
||||
+ /* When the shadow stack base is unset, the default shadow
|
||||
+ stack is in use. Use the current shadow stack pointer
|
||||
+ as the marker for the default shadow stack. */
|
||||
+ rdsspq %rax
|
||||
movq %rax, %fs:SSP_BASE_OFFSET
|
||||
- add $24, %RSP_LP
|
||||
|
||||
L(shadow_stack_bound_recorded):
|
||||
/* If we unwind the stack, we can't undo stack unwinding. Just
|
||||
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||
index 5bff8ec0b4..6c0d6c100d 100644
|
||||
--- a/sysdeps/x86/cpu-features.c
|
||||
+++ b/sysdeps/x86/cpu-features.c
|
||||
@@ -851,8 +851,9 @@ no_cpuid:
|
||||
|
||||
# ifndef SHARED
|
||||
/* Check if IBT and SHSTK are enabled by kernel. */
|
||||
- if ((cet_status & GNU_PROPERTY_X86_FEATURE_1_IBT)
|
||||
- || (cet_status & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
|
||||
+ if ((cet_status
|
||||
+ & (GNU_PROPERTY_X86_FEATURE_1_IBT
|
||||
+ | GNU_PROPERTY_X86_FEATURE_1_SHSTK)))
|
||||
{
|
||||
/* Disable IBT and/or SHSTK if they are enabled by kernel, but
|
||||
disabled by environment variable:
|
||||
@@ -861,9 +862,11 @@ no_cpuid:
|
||||
*/
|
||||
unsigned int cet_feature = 0;
|
||||
if (!CPU_FEATURE_USABLE (IBT))
|
||||
- cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
||||
+ cet_feature |= (cet_status
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_IBT);
|
||||
if (!CPU_FEATURE_USABLE (SHSTK))
|
||||
- cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
+ cet_feature |= (cet_status
|
||||
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK);
|
||||
|
||||
if (cet_feature)
|
||||
{
|
||||
@@ -878,7 +881,9 @@ no_cpuid:
|
||||
lock CET if IBT or SHSTK is enabled permissively. */
|
||||
if (GL(dl_x86_feature_control).ibt != cet_permissive
|
||||
&& GL(dl_x86_feature_control).shstk != cet_permissive)
|
||||
- dl_cet_lock_cet ();
|
||||
+ dl_cet_lock_cet (GL(dl_x86_feature_1)
|
||||
+ & (GNU_PROPERTY_X86_FEATURE_1_IBT
|
||||
+ | GNU_PROPERTY_X86_FEATURE_1_SHSTK));
|
||||
}
|
||||
# endif
|
||||
}
|
||||
diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c
|
||||
index 67c51ee8c2..8b911fd931 100644
|
||||
--- a/sysdeps/x86/dl-cet.c
|
||||
+++ b/sysdeps/x86/dl-cet.c
|
||||
@@ -201,7 +201,7 @@ dl_cet_check_startup (struct link_map *m, struct dl_cet_info *info)
|
||||
feature_1_lock |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
|
||||
if (feature_1_lock != 0
|
||||
- && dl_cet_lock_cet () != 0)
|
||||
+ && dl_cet_lock_cet (feature_1_lock) != 0)
|
||||
_dl_fatal_printf ("%s: can't lock CET\n", info->program);
|
||||
}
|
||||
|
||||
diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h
|
||||
index 1403f939f7..4bcc2552a1 100644
|
||||
--- a/sysdeps/x86_64/nptl/tls.h
|
||||
+++ b/sysdeps/x86_64/nptl/tls.h
|
||||
@@ -60,7 +60,7 @@ typedef struct
|
||||
void *__private_tm[4];
|
||||
/* GCC split stack support. */
|
||||
void *__private_ss;
|
||||
- /* The lowest address of shadow stack, */
|
||||
+ /* The marker for the current shadow stack. */
|
||||
unsigned long long int ssp_base;
|
||||
/* Must be kept even if it is no longer used by glibc since programs,
|
||||
like AddressSanitizer, depend on the size of tcbhead_t. */
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,59 @@
|
||||
From dfb1d9949aca739933464bde8710375358536047 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Fri, 14 Jan 2022 06:04:25 -0800
|
||||
Subject: [PATCH v2 13/15] elf: Always provide _dl_get_dl_main_map in libc.a
|
||||
|
||||
Always provide _dl_get_dl_main_map in libc.a. It will be used by x86
|
||||
to process PT_GNU_PROPERTY segment.
|
||||
---
|
||||
elf/dl-support.c | 2 --
|
||||
sysdeps/generic/ldsodefs.h | 8 ++++----
|
||||
2 files changed, 4 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/elf/dl-support.c b/elf/dl-support.c
|
||||
index 322599916f..042be8a433 100644
|
||||
--- a/elf/dl-support.c
|
||||
+++ b/elf/dl-support.c
|
||||
@@ -353,7 +353,6 @@ _dl_non_dynamic_init (void)
|
||||
DL_SYSINFO_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
-#if ENABLE_STATIC_PIE
|
||||
/* Since relocation to hidden _dl_main_map causes relocation overflow on
|
||||
aarch64, a function is used to get the address of _dl_main_map. */
|
||||
|
||||
@@ -362,7 +361,6 @@ _dl_get_dl_main_map (void)
|
||||
{
|
||||
return &_dl_main_map;
|
||||
}
|
||||
-#endif
|
||||
|
||||
/* This is used by _dl_runtime_profile, not used on static code. */
|
||||
void
|
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||
index ba53176296..7a0903cb8a 100644
|
||||
--- a/sysdeps/generic/ldsodefs.h
|
||||
+++ b/sysdeps/generic/ldsodefs.h
|
||||
@@ -1172,15 +1172,15 @@ void __libc_setup_tls (void);
|
||||
# if ENABLE_STATIC_PIE
|
||||
/* Relocate static executable with PIE. */
|
||||
extern void _dl_relocate_static_pie (void) attribute_hidden;
|
||||
-
|
||||
-/* Get a pointer to _dl_main_map. */
|
||||
-extern struct link_map * _dl_get_dl_main_map (void)
|
||||
- __attribute__ ((visibility ("hidden")));
|
||||
# else
|
||||
# define _dl_relocate_static_pie()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
+/* Get a pointer to _dl_main_map. */
|
||||
+extern struct link_map * _dl_get_dl_main_map (void)
|
||||
+ __attribute__ ((visibility ("hidden")));
|
||||
+
|
||||
/* Perform early memory allocation, avoiding a TCB dependency.
|
||||
Terminate the process if allocation fails. May attempt to use
|
||||
brk. */
|
||||
--
|
||||
2.40.1
|
||||
|
518
v2-0014-x86-cet-Enable-shadow-stack-during-startup.patch
Normal file
518
v2-0014-x86-cet-Enable-shadow-stack-during-startup.patch
Normal file
@ -0,0 +1,518 @@
|
||||
From 29b8bde6bbe322ea35f494b4f3dae3d5d55d3949 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Thu, 13 Jan 2022 15:35:07 -0800
|
||||
Subject: [PATCH v2 14/15] x86/cet: Enable shadow stack during startup
|
||||
|
||||
Previously, CET was enabled by kernel before passing control to user
|
||||
space and the startup code must disable CET if applications or shared
|
||||
libraries aren't CET enabled. Since the current kernel only supports
|
||||
shadow stack and won't enable shadow stack before passing control to
|
||||
user space, we need to enable shadow stack during startup if the
|
||||
application and all shared library are shadow stack enabled. There
|
||||
is no need to disable shadow stack at startup. Shadow stack can only
|
||||
be enabled in a function which will never return. Otherwise, shadow
|
||||
stack will underflow at the function return.
|
||||
|
||||
1. GL(dl_x86_feature_1) is set to the CET features which are supported
|
||||
by the processor and are not disabled by the tunable. Only non-zero
|
||||
features in GL(dl_x86_feature_1) should be enabled. After enabling
|
||||
shadow stack with ARCH_SHSTK_ENABLE, ARCH_SHSTK_STATUS is used to check
|
||||
if shadow stack is really enabled.
|
||||
2. Use ARCH_SHSTK_ENABLE in RTLD_START in dynamic executable. It is
|
||||
safe since RTLD_START never returns.
|
||||
3. Call arch_prctl (ARCH_SHSTK_ENABLE) from ARCH_SETUP_TLS in static
|
||||
executable. Since the start function using ARCH_SETUP_TLS never returns,
|
||||
it is safe to enable shadow stack in ARCH_SETUP_TLS.
|
||||
---
|
||||
sysdeps/unix/sysv/linux/x86/cpu-features.c | 49 --------------
|
||||
sysdeps/unix/sysv/linux/x86/dl-cet.h | 23 +++++++
|
||||
sysdeps/unix/sysv/linux/x86_64/dl-cet.h | 47 +++++++++++++
|
||||
sysdeps/x86/cpu-features-offsets.sym | 1 +
|
||||
sysdeps/x86/cpu-features.c | 51 --------------
|
||||
sysdeps/x86/dl-cet.c | 77 +++++++++++-----------
|
||||
sysdeps/x86/get-cpuid-feature-leaf.c | 2 +-
|
||||
sysdeps/x86/include/cpu-features.h | 3 +
|
||||
sysdeps/x86/libc-start.h | 54 ++++++++++++++-
|
||||
sysdeps/x86_64/dl-machine.h | 12 +++-
|
||||
sysdeps/x86_64/x32/dl-machine.h | 7 +-
|
||||
11 files changed, 180 insertions(+), 146 deletions(-)
|
||||
delete mode 100644 sysdeps/unix/sysv/linux/x86/cpu-features.c
|
||||
create mode 100644 sysdeps/unix/sysv/linux/x86_64/dl-cet.h
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86/cpu-features.c b/sysdeps/unix/sysv/linux/x86/cpu-features.c
|
||||
deleted file mode 100644
|
||||
index 0e6e2bf855..0000000000
|
||||
--- a/sysdeps/unix/sysv/linux/x86/cpu-features.c
|
||||
+++ /dev/null
|
||||
@@ -1,49 +0,0 @@
|
||||
-/* Initialize CPU feature data for Linux/x86.
|
||||
- This file is part of the GNU C Library.
|
||||
- Copyright (C) 2018-2023 Free Software Foundation, Inc.
|
||||
-
|
||||
- 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
|
||||
- <https://www.gnu.org/licenses/>. */
|
||||
-
|
||||
-#if CET_ENABLED
|
||||
-# include <sys/prctl.h>
|
||||
-# include <asm/prctl.h>
|
||||
-
|
||||
-static inline int __attribute__ ((always_inline))
|
||||
-get_cet_status (void)
|
||||
-{
|
||||
- unsigned long long kernel_feature;
|
||||
- unsigned int status = 0;
|
||||
- if (INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_STATUS,
|
||||
- &kernel_feature) == 0)
|
||||
- {
|
||||
- if ((kernel_feature & ARCH_SHSTK_SHSTK) != 0)
|
||||
- status = GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
- }
|
||||
- return status;
|
||||
-}
|
||||
-
|
||||
-# ifndef SHARED
|
||||
-static inline void
|
||||
-x86_setup_tls (void)
|
||||
-{
|
||||
- __libc_setup_tls ();
|
||||
- THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1));
|
||||
-}
|
||||
-
|
||||
-# define ARCH_SETUP_TLS() x86_setup_tls ()
|
||||
-# endif
|
||||
-#endif
|
||||
-
|
||||
-#include <sysdeps/x86/cpu-features.c>
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86/dl-cet.h b/sysdeps/unix/sysv/linux/x86/dl-cet.h
|
||||
index da220ac627..634c885d33 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86/dl-cet.h
|
||||
+++ b/sysdeps/unix/sysv/linux/x86/dl-cet.h
|
||||
@@ -38,3 +38,26 @@ dl_cet_lock_cet (unsigned int cet_feature)
|
||||
return (int) INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_LOCK,
|
||||
kernel_feature);
|
||||
}
|
||||
+
|
||||
+static inline unsigned int __attribute__ ((always_inline))
|
||||
+dl_cet_get_cet_status (void)
|
||||
+{
|
||||
+ unsigned long long kernel_feature;
|
||||
+ unsigned int status = 0;
|
||||
+ if (INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_STATUS,
|
||||
+ &kernel_feature) == 0)
|
||||
+ {
|
||||
+ if ((kernel_feature & ARCH_SHSTK_SHSTK) != 0)
|
||||
+ status = GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
+ }
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+/* Enable shadow stack with a macro to avoid shadow stack underflow. */
|
||||
+#define ENABLE_X86_CET(cet_feature) \
|
||||
+ if ((cet_feature & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) \
|
||||
+ { \
|
||||
+ long long int kernel_feature = ARCH_SHSTK_SHSTK; \
|
||||
+ INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_ENABLE, \
|
||||
+ kernel_feature); \
|
||||
+ }
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/dl-cet.h b/sysdeps/unix/sysv/linux/x86_64/dl-cet.h
|
||||
new file mode 100644
|
||||
index 0000000000..e23e05c6b8
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/dl-cet.h
|
||||
@@ -0,0 +1,47 @@
|
||||
+/* Linux/x86-64 CET initializers function.
|
||||
+ Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
+
|
||||
+ 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <cpu-features-offsets.h>
|
||||
+#include_next <dl-cet.h>
|
||||
+
|
||||
+#define X86_STRINGIFY_1(x) #x
|
||||
+#define X86_STRINGIFY(x) X86_STRINGIFY_1 (x)
|
||||
+
|
||||
+/* Enable shadow stack before calling _dl_init if it is enabled in
|
||||
+ GL(dl_x86_feature_1). Call _dl_setup_x86_features to setup shadow
|
||||
+ stack. */
|
||||
+#define RTLD_START_ENABLE_X86_FEATURES \
|
||||
+"\
|
||||
+ # Check if shadow stack is enabled in GL(dl_x86_feature_1).\n\
|
||||
+ movl _rtld_local+" X86_STRINGIFY (RTLD_GLOBAL_DL_X86_FEATURE_1_OFFSET) "(%rip), %edx\n\
|
||||
+ testl $" X86_STRINGIFY (X86_FEATURE_1_SHSTK) ", %edx\n\
|
||||
+ jz 1f\n\
|
||||
+ # Enable shadow stack if enabled in GL(dl_x86_feature_1).\n\
|
||||
+ movl $" X86_STRINGIFY (ARCH_SHSTK_SHSTK) ", %esi\n\
|
||||
+ movl $" X86_STRINGIFY (ARCH_SHSTK_ENABLE) ", %edi\n\
|
||||
+ movl $" X86_STRINGIFY (__NR_arch_prctl) ", %eax\n\
|
||||
+ syscall\n\
|
||||
+1:\n\
|
||||
+ # Pass GL(dl_x86_feature_1) to _dl_cet_setup_features.\n\
|
||||
+ movl %edx, %edi\n\
|
||||
+ # Align stack for the _dl_cet_setup_features call.\n\
|
||||
+ andq $-16, %rsp\n\
|
||||
+ call _dl_cet_setup_features\n\
|
||||
+ # Restore %rax and %rsp from %r12 and %r13.\n\
|
||||
+ movq %r12, %rax\n\
|
||||
+ movq %r13, %rsp\n\
|
||||
+"
|
||||
diff --git a/sysdeps/x86/cpu-features-offsets.sym b/sysdeps/x86/cpu-features-offsets.sym
|
||||
index 6d03cea8e8..5429f60632 100644
|
||||
--- a/sysdeps/x86/cpu-features-offsets.sym
|
||||
+++ b/sysdeps/x86/cpu-features-offsets.sym
|
||||
@@ -4,3 +4,4 @@
|
||||
|
||||
RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET offsetof (struct rtld_global_ro, _dl_x86_cpu_features)
|
||||
XSAVE_STATE_SIZE_OFFSET offsetof (struct cpu_features, xsave_state_size)
|
||||
+RTLD_GLOBAL_DL_X86_FEATURE_1_OFFSET offsetof (struct rtld_global, _dl_x86_feature_1)
|
||||
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||
index 6c0d6c100d..45bc7fcac3 100644
|
||||
--- a/sysdeps/x86/cpu-features.c
|
||||
+++ b/sysdeps/x86/cpu-features.c
|
||||
@@ -836,57 +836,6 @@ no_cpuid:
|
||||
TUNABLE_CALLBACK (set_x86_ibt));
|
||||
TUNABLE_GET (x86_shstk, tunable_val_t *,
|
||||
TUNABLE_CALLBACK (set_x86_shstk));
|
||||
-
|
||||
- /* Check CET status. */
|
||||
- unsigned int cet_status = get_cet_status ();
|
||||
-
|
||||
- if ((cet_status & GNU_PROPERTY_X86_FEATURE_1_IBT) == 0)
|
||||
- CPU_FEATURE_UNSET (cpu_features, IBT)
|
||||
- if ((cet_status & GNU_PROPERTY_X86_FEATURE_1_SHSTK) == 0)
|
||||
- CPU_FEATURE_UNSET (cpu_features, SHSTK)
|
||||
-
|
||||
- if (cet_status)
|
||||
- {
|
||||
- GL(dl_x86_feature_1) = cet_status;
|
||||
-
|
||||
-# ifndef SHARED
|
||||
- /* Check if IBT and SHSTK are enabled by kernel. */
|
||||
- if ((cet_status
|
||||
- & (GNU_PROPERTY_X86_FEATURE_1_IBT
|
||||
- | GNU_PROPERTY_X86_FEATURE_1_SHSTK)))
|
||||
- {
|
||||
- /* Disable IBT and/or SHSTK if they are enabled by kernel, but
|
||||
- disabled by environment variable:
|
||||
-
|
||||
- GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK
|
||||
- */
|
||||
- unsigned int cet_feature = 0;
|
||||
- if (!CPU_FEATURE_USABLE (IBT))
|
||||
- cet_feature |= (cet_status
|
||||
- & GNU_PROPERTY_X86_FEATURE_1_IBT);
|
||||
- if (!CPU_FEATURE_USABLE (SHSTK))
|
||||
- cet_feature |= (cet_status
|
||||
- & GNU_PROPERTY_X86_FEATURE_1_SHSTK);
|
||||
-
|
||||
- if (cet_feature)
|
||||
- {
|
||||
- int res = dl_cet_disable_cet (cet_feature);
|
||||
-
|
||||
- /* Clear the disabled bits in dl_x86_feature_1. */
|
||||
- if (res == 0)
|
||||
- GL(dl_x86_feature_1) &= ~cet_feature;
|
||||
- }
|
||||
-
|
||||
- /* Lock CET if IBT or SHSTK is enabled in executable. Don't
|
||||
- lock CET if IBT or SHSTK is enabled permissively. */
|
||||
- if (GL(dl_x86_feature_control).ibt != cet_permissive
|
||||
- && GL(dl_x86_feature_control).shstk != cet_permissive)
|
||||
- dl_cet_lock_cet (GL(dl_x86_feature_1)
|
||||
- & (GNU_PROPERTY_X86_FEATURE_1_IBT
|
||||
- | GNU_PROPERTY_X86_FEATURE_1_SHSTK));
|
||||
- }
|
||||
-# endif
|
||||
- }
|
||||
#endif
|
||||
|
||||
#ifndef SHARED
|
||||
diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c
|
||||
index 8b911fd931..7f37244d37 100644
|
||||
--- a/sysdeps/x86/dl-cet.c
|
||||
+++ b/sysdeps/x86/dl-cet.c
|
||||
@@ -172,40 +172,11 @@ dl_cet_check_startup (struct link_map *m, struct dl_cet_info *info)
|
||||
= info->enable_feature_1 ^ info->feature_1_enabled;
|
||||
if (disable_feature_1 != 0)
|
||||
{
|
||||
- /* Disable features in the kernel because of legacy objects or
|
||||
- cet_always_off. */
|
||||
- if (dl_cet_disable_cet (disable_feature_1) != 0)
|
||||
- _dl_fatal_printf ("%s: can't disable x86 Features\n",
|
||||
- info->program);
|
||||
-
|
||||
/* Clear the disabled bits. Sync dl_x86_feature_1 and
|
||||
info->feature_1_enabled with info->enable_feature_1. */
|
||||
info->feature_1_enabled = info->enable_feature_1;
|
||||
GL(dl_x86_feature_1) = info->enable_feature_1;
|
||||
}
|
||||
-
|
||||
- if (HAS_CPU_FEATURE (IBT) || HAS_CPU_FEATURE (SHSTK))
|
||||
- {
|
||||
- /* Lock CET features only if IBT or SHSTK are enabled and are not
|
||||
- enabled permissively. */
|
||||
- unsigned int feature_1_lock = 0;
|
||||
-
|
||||
- if (((info->feature_1_enabled & GNU_PROPERTY_X86_FEATURE_1_IBT)
|
||||
- != 0)
|
||||
- && info->enable_ibt_type != cet_permissive)
|
||||
- feature_1_lock |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
||||
-
|
||||
- if (((info->feature_1_enabled & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
|
||||
- != 0)
|
||||
- && info->enable_shstk_type != cet_permissive)
|
||||
- feature_1_lock |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
-
|
||||
- if (feature_1_lock != 0
|
||||
- && dl_cet_lock_cet (feature_1_lock) != 0)
|
||||
- _dl_fatal_printf ("%s: can't lock CET\n", info->program);
|
||||
- }
|
||||
-
|
||||
- THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -291,6 +262,15 @@ dl_cet_check (struct link_map *m, const char *program)
|
||||
{
|
||||
struct dl_cet_info info;
|
||||
|
||||
+ /* CET is enabled only if RTLD_START_ENABLE_X86_FEATURES is defined. */
|
||||
+#if defined SHARED && defined RTLD_START_ENABLE_X86_FEATURES
|
||||
+ /* Set dl_x86_feature_1 to features enabled in the executable. */
|
||||
+ if (program != NULL)
|
||||
+ GL(dl_x86_feature_1) = (m->l_x86_feature_1_and
|
||||
+ & (X86_FEATURE_1_IBT
|
||||
+ | X86_FEATURE_1_SHSTK));
|
||||
+#endif
|
||||
+
|
||||
/* Check how IBT and SHSTK should be enabled. */
|
||||
info.enable_ibt_type = GL(dl_x86_feature_control).ibt;
|
||||
info.enable_shstk_type = GL(dl_x86_feature_control).shstk;
|
||||
@@ -300,17 +280,9 @@ dl_cet_check (struct link_map *m, const char *program)
|
||||
/* No legacy object check if IBT and SHSTK are always on. */
|
||||
if (info.enable_ibt_type == cet_always_on
|
||||
&& info.enable_shstk_type == cet_always_on)
|
||||
- {
|
||||
-#ifdef SHARED
|
||||
- /* Set it only during startup. */
|
||||
- if (program != NULL)
|
||||
- THREAD_SETMEM (THREAD_SELF, header.feature_1,
|
||||
- info.feature_1_enabled);
|
||||
-#endif
|
||||
- return;
|
||||
- }
|
||||
+ return;
|
||||
|
||||
- /* Check if IBT and SHSTK were enabled by kernel. */
|
||||
+ /* Check if IBT and SHSTK were enabled. */
|
||||
if (info.feature_1_enabled == 0)
|
||||
return;
|
||||
|
||||
@@ -344,6 +316,33 @@ _dl_cet_open_check (struct link_map *l)
|
||||
dl_cet_check (l, NULL);
|
||||
}
|
||||
|
||||
+/* Set GL(dl_x86_feature_1) to the enabled features and clear the
|
||||
+ active bits of the disabled features. */
|
||||
+
|
||||
+attribute_hidden
|
||||
+void
|
||||
+_dl_cet_setup_features (unsigned int cet_feature)
|
||||
+{
|
||||
+ /* NB: cet_feature == GL(dl_x86_feature_1) which is set to features
|
||||
+ enabled from executable, not necessarily supported by kernel. */
|
||||
+ if (cet_feature)
|
||||
+ {
|
||||
+ cet_feature = dl_cet_get_cet_status ();
|
||||
+ /* Sync GL(dl_x86_feature_1) with kernel. */
|
||||
+ GL(dl_x86_feature_1) = cet_feature;
|
||||
+ if (cet_feature)
|
||||
+ {
|
||||
+ THREAD_SETMEM (THREAD_SELF, header.feature_1, cet_feature);
|
||||
+
|
||||
+ /* Lock CET if IBT or SHSTK is enabled in executable. Don't
|
||||
+ lock CET if IBT or SHSTK is enabled permissively. */
|
||||
+ if (GL(dl_x86_feature_control).ibt != cet_permissive
|
||||
+ && (GL(dl_x86_feature_control).shstk != cet_permissive))
|
||||
+ dl_cet_lock_cet (cet_feature);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#ifdef SHARED
|
||||
|
||||
# ifndef LINKAGE
|
||||
diff --git a/sysdeps/x86/get-cpuid-feature-leaf.c b/sysdeps/x86/get-cpuid-feature-leaf.c
|
||||
index 40a46cc79c..9317a6b494 100644
|
||||
--- a/sysdeps/x86/get-cpuid-feature-leaf.c
|
||||
+++ b/sysdeps/x86/get-cpuid-feature-leaf.c
|
||||
@@ -24,7 +24,7 @@ __x86_get_cpuid_feature_leaf (unsigned int leaf)
|
||||
static const struct cpuid_feature feature = {};
|
||||
if (leaf < CPUID_INDEX_MAX)
|
||||
return ((const struct cpuid_feature *)
|
||||
- &GLRO(dl_x86_cpu_features).features[leaf]);
|
||||
+ &GLRO(dl_x86_cpu_features).features[leaf]);
|
||||
else
|
||||
return &feature;
|
||||
}
|
||||
diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
|
||||
index 40b8129d6a..e6a2424682 100644
|
||||
--- a/sysdeps/x86/include/cpu-features.h
|
||||
+++ b/sysdeps/x86/include/cpu-features.h
|
||||
@@ -958,6 +958,9 @@ extern const struct cpu_features *_dl_x86_get_cpu_features (void)
|
||||
# define INIT_ARCH()
|
||||
# define _dl_x86_get_cpu_features() (&GLRO(dl_x86_cpu_features))
|
||||
extern void _dl_x86_init_cpu_features (void) attribute_hidden;
|
||||
+
|
||||
+extern void _dl_cet_setup_features (unsigned int)
|
||||
+ attribute_hidden;
|
||||
#endif
|
||||
|
||||
#ifdef __x86_64__
|
||||
diff --git a/sysdeps/x86/libc-start.h b/sysdeps/x86/libc-start.h
|
||||
index e93da6ef3d..856230daeb 100644
|
||||
--- a/sysdeps/x86/libc-start.h
|
||||
+++ b/sysdeps/x86/libc-start.h
|
||||
@@ -19,7 +19,57 @@
|
||||
#ifndef SHARED
|
||||
# define ARCH_SETUP_IREL() apply_irel ()
|
||||
# define ARCH_APPLY_IREL()
|
||||
-# ifndef ARCH_SETUP_TLS
|
||||
-# define ARCH_SETUP_TLS() __libc_setup_tls ()
|
||||
+# ifdef __CET__
|
||||
+/* Get CET features enabled in the static executable. */
|
||||
+
|
||||
+static inline unsigned int
|
||||
+get_cet_feature (void)
|
||||
+{
|
||||
+ /* Check if CET is supported and not disabled by tunables. */
|
||||
+ struct cpu_features *cpu_features
|
||||
+ = (struct cpu_features *) __get_cpu_features ();
|
||||
+ unsigned int cet_feature = 0;
|
||||
+ if (CPU_FEATURE_USABLE_P (cpu_features, IBT))
|
||||
+ cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
||||
+ if (CPU_FEATURE_USABLE_P (cpu_features, SHSTK))
|
||||
+ cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||||
+ if (!cet_feature)
|
||||
+ return cet_feature;
|
||||
+
|
||||
+ struct link_map *main_map = _dl_get_dl_main_map ();
|
||||
+
|
||||
+ /* Scan program headers backward to check PT_GNU_PROPERTY early for
|
||||
+ x86 feature bits on static executable. */
|
||||
+ const ElfW(Phdr) *phdr = GL(dl_phdr);
|
||||
+ const ElfW(Phdr) *ph;
|
||||
+ for (ph = phdr + GL(dl_phnum); ph != phdr; ph--)
|
||||
+ if (ph[-1].p_type == PT_GNU_PROPERTY)
|
||||
+ {
|
||||
+ _dl_process_pt_gnu_property (main_map, -1, &ph[-1]);
|
||||
+ /* Enable IBT and SHSTK only if they are enabled on static
|
||||
+ executable. */
|
||||
+ cet_feature &= (main_map->l_x86_feature_1_and
|
||||
+ & (GNU_PROPERTY_X86_FEATURE_1_IBT
|
||||
+ | GNU_PROPERTY_X86_FEATURE_1_SHSTK));
|
||||
+ /* Set GL(dl_x86_feature_1) to the enabled CET features. */
|
||||
+ GL(dl_x86_feature_1) = cet_feature;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return cet_feature;
|
||||
+}
|
||||
+
|
||||
+/* The function using this macro to enable shadow stack must not return
|
||||
+ to avoid shadow stack underflow. */
|
||||
+# define ARCH_SETUP_TLS() \
|
||||
+ { \
|
||||
+ __libc_setup_tls (); \
|
||||
+ \
|
||||
+ unsigned int cet_feature = get_cet_feature (); \
|
||||
+ ENABLE_X86_CET (cet_feature); \
|
||||
+ _dl_cet_setup_features (cet_feature); \
|
||||
+ }
|
||||
+# else
|
||||
+# define ARCH_SETUP_TLS() __libc_setup_tls ()
|
||||
# endif
|
||||
#endif /* !SHARED */
|
||||
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
|
||||
index 9ea2a70837..b4159880f3 100644
|
||||
--- a/sysdeps/x86_64/dl-machine.h
|
||||
+++ b/sysdeps/x86_64/dl-machine.h
|
||||
@@ -29,6 +29,11 @@
|
||||
#include <dl-static-tls.h>
|
||||
#include <dl-machine-rel.h>
|
||||
#include <isa-level.h>
|
||||
+#ifdef __CET__
|
||||
+# include <dl-cet.h>
|
||||
+#else
|
||||
+# define RTLD_START_ENABLE_X86_FEATURES
|
||||
+#endif
|
||||
|
||||
/* Return nonzero iff ELF header is compatible with the running host. */
|
||||
static inline int __attribute__ ((unused))
|
||||
@@ -144,13 +149,16 @@ _start:\n\
|
||||
_dl_start_user:\n\
|
||||
# Save the user entry point address in %r12.\n\
|
||||
movq %rax, %r12\n\
|
||||
+ # Save %rsp value in %r13.\n\
|
||||
+ movq %rsp, %r13\n\
|
||||
+"\
|
||||
+ RTLD_START_ENABLE_X86_FEATURES \
|
||||
+"\
|
||||
# Read the original argument count.\n\
|
||||
movq (%rsp), %rdx\n\
|
||||
# Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env)\n\
|
||||
# argc -> rsi\n\
|
||||
movq %rdx, %rsi\n\
|
||||
- # Save %rsp value in %r13.\n\
|
||||
- movq %rsp, %r13\n\
|
||||
# And align stack for the _dl_init call. \n\
|
||||
andq $-16, %rsp\n\
|
||||
# _dl_loaded -> rdi\n\
|
||||
diff --git a/sysdeps/x86_64/x32/dl-machine.h b/sysdeps/x86_64/x32/dl-machine.h
|
||||
index 648a11f926..d8598b3e9c 100644
|
||||
--- a/sysdeps/x86_64/x32/dl-machine.h
|
||||
+++ b/sysdeps/x86_64/x32/dl-machine.h
|
||||
@@ -45,13 +45,16 @@ _start:\n\
|
||||
_dl_start_user:\n\
|
||||
# Save the user entry point address in %r12.\n\
|
||||
movl %eax, %r12d\n\
|
||||
+ # Save %rsp value in %r13.\n\
|
||||
+ movl %esp, %r13d\n\
|
||||
+"\
|
||||
+ RTLD_START_ENABLE_X86_FEATURES \
|
||||
+"\
|
||||
# Read the original argument count.\n\
|
||||
movl (%rsp), %edx\n\
|
||||
# Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env)\n\
|
||||
# argc -> rsi\n\
|
||||
movl %edx, %esi\n\
|
||||
- # Save %rsp value in %r13.\n\
|
||||
- movl %esp, %r13d\n\
|
||||
# And align stack for the _dl_init call.\n\
|
||||
and $-16, %esp\n\
|
||||
# _dl_loaded -> rdi\n\
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,89 @@
|
||||
From 7b3c43e6b089eb7efefdbb32b99da6b1ab469151 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Tue, 11 Apr 2023 14:03:43 -0700
|
||||
Subject: [PATCH v2 15/15] x86/cet: Check feature_1 in TCB for active IBT and
|
||||
SHSTK
|
||||
|
||||
Initially, IBT and SHSTK are marked as active when CPU supports them
|
||||
and CET are enabled in glibc. They can be disabled early by tunables
|
||||
before relocation. Since after relocation, GLRO(dl_x86_cpu_features)
|
||||
becomes read-only, we can't update GLRO(dl_x86_cpu_features) to mark
|
||||
IBT and SHSTK as inactive. Instead, check the feature_1 field in TCB
|
||||
to decide if IBT and SHST are active.
|
||||
---
|
||||
sysdeps/x86/bits/platform/x86.h | 8 ++++++++
|
||||
sysdeps/x86/get-cpuid-feature-leaf.c | 11 ++++++++++-
|
||||
sysdeps/x86/sys/platform/x86.h | 17 +++++++++++++++++
|
||||
3 files changed, 35 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/sysdeps/x86/bits/platform/x86.h b/sysdeps/x86/bits/platform/x86.h
|
||||
index 6555f9b91d..c9b6ee1766 100644
|
||||
--- a/sysdeps/x86/bits/platform/x86.h
|
||||
+++ b/sysdeps/x86/bits/platform/x86.h
|
||||
@@ -326,3 +326,11 @@ enum
|
||||
|
||||
x86_cpu_PTWRITE = x86_cpu_index_14_ecx_0_ebx + 4
|
||||
};
|
||||
+
|
||||
+/* Bits in the feature_1 field in TCB. */
|
||||
+
|
||||
+enum
|
||||
+{
|
||||
+ x86_feature_1_ibt = 1U << 0,
|
||||
+ x86_feature_1_shstk = 1U << 1
|
||||
+};
|
||||
diff --git a/sysdeps/x86/get-cpuid-feature-leaf.c b/sysdeps/x86/get-cpuid-feature-leaf.c
|
||||
index 9317a6b494..f69936b31e 100644
|
||||
--- a/sysdeps/x86/get-cpuid-feature-leaf.c
|
||||
+++ b/sysdeps/x86/get-cpuid-feature-leaf.c
|
||||
@@ -15,9 +15,18 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
-
|
||||
+#include <assert.h>
|
||||
+#include <tcb-offsets.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
+#ifdef __x86_64__
|
||||
+# ifdef __LP64__
|
||||
+_Static_assert (FEATURE_1_OFFSET == 72, "FEATURE_1_OFFSET != 72");
|
||||
+# else
|
||||
+_Static_assert (FEATURE_1_OFFSET == 40, "FEATURE_1_OFFSET != 40");
|
||||
+# endif
|
||||
+#endif
|
||||
+
|
||||
const struct cpuid_feature *
|
||||
__x86_get_cpuid_feature_leaf (unsigned int leaf)
|
||||
{
|
||||
diff --git a/sysdeps/x86/sys/platform/x86.h b/sysdeps/x86/sys/platform/x86.h
|
||||
index 1ea2c5fc0b..89b1b16f22 100644
|
||||
--- a/sysdeps/x86/sys/platform/x86.h
|
||||
+++ b/sysdeps/x86/sys/platform/x86.h
|
||||
@@ -45,6 +45,23 @@ x86_cpu_present (unsigned int __index)
|
||||
static __inline__ _Bool
|
||||
x86_cpu_active (unsigned int __index)
|
||||
{
|
||||
+ if (__index == x86_cpu_IBT || __index == x86_cpu_SHSTK)
|
||||
+ {
|
||||
+#ifdef __x86_64__
|
||||
+ unsigned int __feature_1;
|
||||
+# ifdef __LP64__
|
||||
+ __asm__ ("mov %%fs:72, %0" : "=r" (__feature_1));
|
||||
+# else
|
||||
+ __asm__ ("mov %%fs:40, %0" : "=r" (__feature_1));
|
||||
+# endif
|
||||
+ if (__index == x86_cpu_IBT)
|
||||
+ return __feature_1 & x86_feature_1_ibt;
|
||||
+ else
|
||||
+ return __feature_1 & x86_feature_1_shstk;
|
||||
+#else
|
||||
+ return false;
|
||||
+#endif
|
||||
+ }
|
||||
const struct cpuid_feature *__ptr = __x86_get_cpuid_feature_leaf
|
||||
(__index / (8 * sizeof (unsigned int) * 4));
|
||||
unsigned int __reg
|
||||
--
|
||||
2.40.1
|
||||
|
Loading…
Reference in New Issue
Block a user