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
|
# - It allows using the Release number without the %%dist tag in the dependency
|
||||||
# generator to make the generated requires interchangeable between Rawhide
|
# generator to make the generated requires interchangeable between Rawhide
|
||||||
# and ELN (.elnYY < .fcXX).
|
# and ELN (.elnYY < .fcXX).
|
||||||
%global baserelease 13
|
%global baserelease 14
|
||||||
Release: %{baserelease}%{?dist}
|
Release: %{baserelease}%{?dist}
|
||||||
|
|
||||||
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
||||||
@ -232,6 +232,23 @@ Patch17: glibc-cs-path.patch
|
|||||||
Patch23: glibc-python3.patch
|
Patch23: glibc-python3.patch
|
||||||
Patch24: glibc-disable-werror-tst-realloc.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:
|
# 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
|
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
|
||||||
|
|
||||||
%changelog
|
%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
|
* Wed Jun 07 2023 Arjun Shankar <arjun@redhat.com> - 2.37.9000-13
|
||||||
- Auto-sync with upstream branch master,
|
- Auto-sync with upstream branch master,
|
||||||
commit 85e6d8b4175fcb195011a0a1bad37d6f3b2355db:
|
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