forked from rpms/glibc
575 lines
18 KiB
Diff
575 lines
18 KiB
Diff
|
commit 1fabdb99084df004f7f4cdc7068d1be209a258be
|
||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||
|
Date: Wed Mar 18 04:35:54 2020 -0700
|
||
|
|
||
|
x86: Remove ARCH_CET_LEGACY_BITMAP [BZ #25397]
|
||
|
|
||
|
Since legacy bitmap doesn't cover jitted code generated by legacy JIT
|
||
|
engine, it isn't very useful. This patch removes ARCH_CET_LEGACY_BITMAP
|
||
|
and treats indirect branch tracking similar to shadow stack by removing
|
||
|
legacy bitmap support.
|
||
|
|
||
|
Tested on CET Linux/x86-64 and non-CET Linux/x86-64.
|
||
|
|
||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||
|
---
|
||
|
|
||
|
diff --git a/sysdeps/unix/sysv/linux/x86/dl-cet.h b/sysdeps/unix/sysv/linux/x86/dl-cet.h
|
||
|
index 3fbcfeb..47c52e6 100644
|
||
|
--- a/sysdeps/unix/sysv/linux/x86/dl-cet.h
|
||
|
+++ b/sysdeps/unix/sysv/linux/x86/dl-cet.h
|
||
|
@@ -19,27 +19,6 @@
|
||
|
#include <asm/prctl.h>
|
||
|
|
||
|
static inline int __attribute__ ((always_inline))
|
||
|
-dl_cet_allocate_legacy_bitmap (unsigned long *legacy_bitmap)
|
||
|
-{
|
||
|
- /* Allocate legacy bitmap. */
|
||
|
- INTERNAL_SYSCALL_DECL (err);
|
||
|
-#ifdef __LP64__
|
||
|
- return (int) INTERNAL_SYSCALL (arch_prctl, err, 2,
|
||
|
- ARCH_CET_LEGACY_BITMAP, legacy_bitmap);
|
||
|
-#else
|
||
|
- unsigned long long legacy_bitmap_u64[2];
|
||
|
- int res = INTERNAL_SYSCALL (arch_prctl, err, 2,
|
||
|
- ARCH_CET_LEGACY_BITMAP, legacy_bitmap_u64);
|
||
|
- if (res == 0)
|
||
|
- {
|
||
|
- legacy_bitmap[0] = legacy_bitmap_u64[0];
|
||
|
- legacy_bitmap[1] = legacy_bitmap_u64[1];
|
||
|
- }
|
||
|
- return res;
|
||
|
-#endif
|
||
|
-}
|
||
|
-
|
||
|
-static inline int __attribute__ ((always_inline))
|
||
|
dl_cet_disable_cet (unsigned int cet_feature)
|
||
|
{
|
||
|
INTERNAL_SYSCALL_DECL (err);
|
||
|
diff --git a/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h b/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h
|
||
|
index f67f329..45ad0b0 100644
|
||
|
--- a/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h
|
||
|
+++ b/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h
|
||
|
@@ -24,9 +24,4 @@
|
||
|
OUT: allocated shadow stack address: *addr.
|
||
|
*/
|
||
|
# define ARCH_CET_ALLOC_SHSTK 0x3004
|
||
|
-/* Return legacy region bitmap info in unsigned long long *addr:
|
||
|
- address: addr[0].
|
||
|
- size: addr[1].
|
||
|
- */
|
||
|
-# define ARCH_CET_LEGACY_BITMAP 0x3005
|
||
|
#endif /* ARCH_CET_STATUS */
|
||
|
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
|
||
|
index 43ad4a7..d9bdf0b 100644
|
||
|
--- a/sysdeps/x86/Makefile
|
||
|
+++ b/sysdeps/x86/Makefile
|
||
|
@@ -20,7 +20,8 @@ sysdep-dl-routines += dl-cet
|
||
|
|
||
|
tests += tst-cet-legacy-1 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-5a tst-cet-legacy-6a tst-cet-legacy-7 \
|
||
|
+ tst-cet-legacy-8
|
||
|
ifneq (no,$(have-tunables))
|
||
|
tests += tst-cet-legacy-4a tst-cet-legacy-4b tst-cet-legacy-4c \
|
||
|
tst-cet-legacy-5b tst-cet-legacy-6b
|
||
|
@@ -42,14 +43,16 @@ CFLAGS-tst-cet-legacy-4b.c += -fcf-protection
|
||
|
CFLAGS-tst-cet-legacy-mod-4.c += -fcf-protection=none
|
||
|
CFLAGS-tst-cet-legacy-5a.c += -fcf-protection
|
||
|
CFLAGS-tst-cet-legacy-5b.c += -fcf-protection
|
||
|
-CFLAGS-tst-cet-legacy-mod-5a.c += -fcf-protection=none
|
||
|
+CFLAGS-tst-cet-legacy-mod-5a.c += -fcf-protection=branch
|
||
|
CFLAGS-tst-cet-legacy-mod-5b.c += -fcf-protection
|
||
|
CFLAGS-tst-cet-legacy-mod-5c.c += -fcf-protection
|
||
|
CFLAGS-tst-cet-legacy-6a.c += -fcf-protection
|
||
|
CFLAGS-tst-cet-legacy-6b.c += -fcf-protection
|
||
|
-CFLAGS-tst-cet-legacy-mod-6a.c += -fcf-protection=none
|
||
|
+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
|
||
|
|
||
|
$(objpfx)tst-cet-legacy-1: $(objpfx)tst-cet-legacy-mod-1.so \
|
||
|
$(objpfx)tst-cet-legacy-mod-2.so
|
||
|
diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c
|
||
|
index b82ba14..627d937 100644
|
||
|
--- a/sysdeps/x86/dl-cet.c
|
||
|
+++ b/sysdeps/x86/dl-cet.c
|
||
|
@@ -33,63 +33,6 @@
|
||
|
# error GNU_PROPERTY_X86_FEATURE_1_SHSTK != X86_FEATURE_1_SHSTK
|
||
|
#endif
|
||
|
|
||
|
-static int
|
||
|
-dl_cet_mark_legacy_region (struct link_map *l)
|
||
|
-{
|
||
|
- /* Mark PT_LOAD segments with PF_X in legacy code page bitmap. */
|
||
|
- size_t i, phnum = l->l_phnum;
|
||
|
- const ElfW(Phdr) *phdr = l->l_phdr;
|
||
|
-#ifdef __x86_64__
|
||
|
- typedef unsigned long long word_t;
|
||
|
-#else
|
||
|
- typedef unsigned long word_t;
|
||
|
-#endif
|
||
|
- unsigned int bits_to_set;
|
||
|
- word_t mask_to_set;
|
||
|
-#define BITS_PER_WORD (sizeof (word_t) * 8)
|
||
|
-#define BITMAP_FIRST_WORD_MASK(start) \
|
||
|
- (~((word_t) 0) << ((start) & (BITS_PER_WORD - 1)))
|
||
|
-#define BITMAP_LAST_WORD_MASK(nbits) \
|
||
|
- (~((word_t) 0) >> (-(nbits) & (BITS_PER_WORD - 1)))
|
||
|
-
|
||
|
- word_t *bitmap = (word_t *) GL(dl_x86_legacy_bitmap)[0];
|
||
|
- word_t bitmap_size = GL(dl_x86_legacy_bitmap)[1];
|
||
|
- word_t *p;
|
||
|
- size_t page_size = GLRO(dl_pagesize);
|
||
|
-
|
||
|
- for (i = 0; i < phnum; i++)
|
||
|
- if (phdr[i].p_type == PT_LOAD && (phdr[i].p_flags & PF_X))
|
||
|
- {
|
||
|
- /* One bit in legacy bitmap represents a page. */
|
||
|
- ElfW(Addr) start = (phdr[i].p_vaddr + l->l_addr) / page_size;
|
||
|
- ElfW(Addr) len = (phdr[i].p_memsz + page_size - 1) / page_size;
|
||
|
- ElfW(Addr) end = start + len;
|
||
|
-
|
||
|
- if ((end / 8) > bitmap_size)
|
||
|
- return -EINVAL;
|
||
|
-
|
||
|
- p = bitmap + (start / BITS_PER_WORD);
|
||
|
- bits_to_set = BITS_PER_WORD - (start % BITS_PER_WORD);
|
||
|
- mask_to_set = BITMAP_FIRST_WORD_MASK (start);
|
||
|
-
|
||
|
- while (len >= bits_to_set)
|
||
|
- {
|
||
|
- *p |= mask_to_set;
|
||
|
- len -= bits_to_set;
|
||
|
- bits_to_set = BITS_PER_WORD;
|
||
|
- mask_to_set = ~((word_t) 0);
|
||
|
- p++;
|
||
|
- }
|
||
|
- if (len)
|
||
|
- {
|
||
|
- mask_to_set &= BITMAP_LAST_WORD_MASK (end);
|
||
|
- *p |= mask_to_set;
|
||
|
- }
|
||
|
- }
|
||
|
-
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
/* Check if object M is compatible with CET. */
|
||
|
|
||
|
static void
|
||
|
@@ -117,6 +60,8 @@ dl_cet_check (struct link_map *m, const char *program)
|
||
|
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
|
||
|
@@ -142,10 +87,7 @@ dl_cet_check (struct link_map *m, const char *program)
|
||
|
support IBT nor SHSTK. */
|
||
|
if (enable_ibt || enable_shstk)
|
||
|
{
|
||
|
- int res;
|
||
|
unsigned int i;
|
||
|
- unsigned int first_legacy, last_legacy;
|
||
|
- bool need_legacy_bitmap = false;
|
||
|
|
||
|
i = m->l_searchlist.r_nlist;
|
||
|
while (i-- > 0)
|
||
|
@@ -167,91 +109,25 @@ dl_cet_check (struct link_map *m, const char *program)
|
||
|
continue;
|
||
|
#endif
|
||
|
|
||
|
- if (enable_ibt
|
||
|
- && enable_ibt_type != CET_ALWAYS_ON
|
||
|
- && !(l->l_cet & lc_ibt))
|
||
|
+ /* 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_cet & lc_ibt) != 0);
|
||
|
+ if (!found_ibt_legacy && enable_ibt != ibt_enabled)
|
||
|
{
|
||
|
- /* Remember the first and last legacy objects. */
|
||
|
- if (!need_legacy_bitmap)
|
||
|
- last_legacy = i;
|
||
|
- first_legacy = i;
|
||
|
- need_legacy_bitmap = true;
|
||
|
+ 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_cet & lc_shstk) != 0);
|
||
|
- }
|
||
|
-
|
||
|
- if (need_legacy_bitmap)
|
||
|
- {
|
||
|
- if (GL(dl_x86_legacy_bitmap)[0])
|
||
|
- {
|
||
|
- /* Change legacy bitmap to writable. */
|
||
|
- if (__mprotect ((void *) GL(dl_x86_legacy_bitmap)[0],
|
||
|
- GL(dl_x86_legacy_bitmap)[1],
|
||
|
- PROT_READ | PROT_WRITE) < 0)
|
||
|
- {
|
||
|
-mprotect_failure:
|
||
|
- if (program)
|
||
|
- _dl_fatal_printf ("%s: mprotect legacy bitmap failed\n",
|
||
|
- l->l_name);
|
||
|
- else
|
||
|
- _dl_signal_error (EINVAL, l->l_name, "dlopen",
|
||
|
- N_("mprotect legacy bitmap failed"));
|
||
|
- }
|
||
|
- }
|
||
|
- else
|
||
|
+ if (enable_shstk != shstk_enabled)
|
||
|
{
|
||
|
- /* Allocate legacy bitmap. */
|
||
|
- int res = dl_cet_allocate_legacy_bitmap
|
||
|
- (GL(dl_x86_legacy_bitmap));
|
||
|
- if (res != 0)
|
||
|
- {
|
||
|
- if (program)
|
||
|
- _dl_fatal_printf ("%s: legacy bitmap isn't available\n",
|
||
|
- l->l_name);
|
||
|
- else
|
||
|
- _dl_signal_error (EINVAL, l->l_name, "dlopen",
|
||
|
- N_("legacy bitmap isn't available"));
|
||
|
- }
|
||
|
+ found_shstk_legacy = true;
|
||
|
+ shstk_legacy = i;
|
||
|
}
|
||
|
-
|
||
|
- /* Put legacy shared objects in legacy bitmap. */
|
||
|
- for (i = first_legacy; i <= last_legacy; i++)
|
||
|
- {
|
||
|
- l = m->l_initfini[i];
|
||
|
-
|
||
|
- if (l->l_init_called || (l->l_cet & lc_ibt))
|
||
|
- continue;
|
||
|
-
|
||
|
-#ifdef SHARED
|
||
|
- if (l == &GL(dl_rtld_map)
|
||
|
- || l->l_real == &GL(dl_rtld_map)
|
||
|
- || (program && l == m))
|
||
|
- continue;
|
||
|
-#endif
|
||
|
-
|
||
|
- /* If IBT is enabled in executable and IBT isn't enabled
|
||
|
- in this shard object, mark PT_LOAD segments with PF_X
|
||
|
- in legacy code page bitmap. */
|
||
|
- res = dl_cet_mark_legacy_region (l);
|
||
|
- if (res != 0)
|
||
|
- {
|
||
|
- if (program)
|
||
|
- _dl_fatal_printf ("%s: failed to mark legacy code region\n",
|
||
|
- l->l_name);
|
||
|
- else
|
||
|
- _dl_signal_error (-res, l->l_name, "dlopen",
|
||
|
- N_("failed to mark legacy code region"));
|
||
|
- }
|
||
|
- }
|
||
|
-
|
||
|
- /* Change legacy bitmap to read-only. */
|
||
|
- if (__mprotect ((void *) GL(dl_x86_legacy_bitmap)[0],
|
||
|
- GL(dl_x86_legacy_bitmap)[1], PROT_READ) < 0)
|
||
|
- goto mprotect_failure;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -259,23 +135,40 @@ mprotect_failure:
|
||
|
|
||
|
if (enable_ibt != ibt_enabled || enable_shstk != shstk_enabled)
|
||
|
{
|
||
|
- if (!program
|
||
|
- && enable_shstk_type != CET_PERMISSIVE)
|
||
|
+ if (!program)
|
||
|
{
|
||
|
- /* When SHSTK is enabled, we can't dlopening a shared
|
||
|
- object without SHSTK. */
|
||
|
- if (enable_shstk != shstk_enabled)
|
||
|
- _dl_signal_error (EINVAL, l->l_name, "dlopen",
|
||
|
- N_("shadow stack isn't enabled"));
|
||
|
- return;
|
||
|
+ 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;
|
||
|
|
||
|
- /* Disable IBT only during program startup. */
|
||
|
- if (program && !enable_ibt)
|
||
|
+ if (!enable_ibt)
|
||
|
cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
||
|
if (!enable_shstk)
|
||
|
cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
||
|
@@ -286,8 +179,14 @@ mprotect_failure:
|
||
|
if (program)
|
||
|
_dl_fatal_printf ("%s: can't disable CET\n", program);
|
||
|
else
|
||
|
- _dl_signal_error (-res, l->l_name, "dlopen",
|
||
|
- N_("can't disable CET"));
|
||
|
+ {
|
||
|
+ 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. */
|
||
|
@@ -297,17 +196,21 @@ mprotect_failure:
|
||
|
}
|
||
|
|
||
|
#ifdef SHARED
|
||
|
- if (program
|
||
|
- && (!shstk_enabled
|
||
|
- || enable_shstk_type != CET_PERMISSIVE)
|
||
|
- && (ibt_enabled || shstk_enabled))
|
||
|
+ if (program && (ibt_enabled || shstk_enabled))
|
||
|
{
|
||
|
- /* Lock CET if IBT or SHSTK is enabled in executable. Don't
|
||
|
- lock CET if SHSTK is enabled permissively. */
|
||
|
- int res = dl_cet_lock_cet ();
|
||
|
- if (res != 0)
|
||
|
- _dl_fatal_printf ("%s: can't lock CET\n", program);
|
||
|
+ 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;
|
||
|
}
|
||
|
#endif
|
||
|
diff --git a/sysdeps/x86/dl-procruntime.c b/sysdeps/x86/dl-procruntime.c
|
||
|
index eddbde6..920bfe8 100644
|
||
|
--- a/sysdeps/x86/dl-procruntime.c
|
||
|
+++ b/sysdeps/x86/dl-procruntime.c
|
||
|
@@ -54,15 +54,4 @@ PROCINFO_CLASS unsigned int _dl_x86_feature_1[2]
|
||
|
# else
|
||
|
,
|
||
|
# endif
|
||
|
-
|
||
|
-# if !defined PROCINFO_DECL && defined SHARED
|
||
|
- ._dl_x86_legacy_bitmap
|
||
|
-# else
|
||
|
-PROCINFO_CLASS unsigned long _dl_x86_legacy_bitmap[2]
|
||
|
-# endif
|
||
|
-# if !defined SHARED || defined PROCINFO_DECL
|
||
|
-;
|
||
|
-# else
|
||
|
-,
|
||
|
-# endif
|
||
|
#endif
|
||
|
diff --git a/sysdeps/x86/tst-cet-legacy-4.c b/sysdeps/x86/tst-cet-legacy-4.c
|
||
|
index 3ead63d..f0ba326 100644
|
||
|
--- a/sysdeps/x86/tst-cet-legacy-4.c
|
||
|
+++ b/sysdeps/x86/tst-cet-legacy-4.c
|
||
|
@@ -20,6 +20,9 @@
|
||
|
#include <dlfcn.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
+#include <string.h>
|
||
|
+
|
||
|
+#include <support/check.h>
|
||
|
|
||
|
static int
|
||
|
do_test (void)
|
||
|
@@ -31,22 +34,18 @@ do_test (void)
|
||
|
h = dlopen (modname, RTLD_LAZY);
|
||
|
if (h == NULL)
|
||
|
{
|
||
|
- printf ("cannot open '%s': %s\n", modname, dlerror ());
|
||
|
- exit (1);
|
||
|
+ const char *err = dlerror ();
|
||
|
+ if (!strstr (err, "rebuild shared object with IBT support enabled"))
|
||
|
+ FAIL_EXIT1 ("incorrect dlopen '%s' error: %s\n", modname, err);
|
||
|
+ return 0;
|
||
|
}
|
||
|
|
||
|
fp = dlsym (h, "test");
|
||
|
if (fp == NULL)
|
||
|
- {
|
||
|
- printf ("cannot get symbol 'test': %s\n", dlerror ());
|
||
|
- exit (1);
|
||
|
- }
|
||
|
+ FAIL_EXIT1 ("cannot get symbol 'test': %s\n", dlerror ());
|
||
|
|
||
|
if (fp () != 0)
|
||
|
- {
|
||
|
- puts ("test () != 0");
|
||
|
- exit (1);
|
||
|
- }
|
||
|
+ FAIL_EXIT1 ("test () != 0");
|
||
|
|
||
|
dlclose (h);
|
||
|
|
||
|
diff --git a/sysdeps/x86/tst-cet-legacy-5.c b/sysdeps/x86/tst-cet-legacy-5.c
|
||
|
index fbf640f..e1ca09d 100644
|
||
|
--- a/sysdeps/x86/tst-cet-legacy-5.c
|
||
|
+++ b/sysdeps/x86/tst-cet-legacy-5.c
|
||
|
@@ -35,7 +35,8 @@ do_test_1 (const char *modname, bool fail)
|
||
|
if (fail)
|
||
|
{
|
||
|
const char *err = dlerror ();
|
||
|
- if (strstr (err, "shadow stack isn't enabled") == NULL)
|
||
|
+ if (strstr (err, "rebuild shared object with SHSTK support enabled")
|
||
|
+ == NULL)
|
||
|
{
|
||
|
printf ("incorrect dlopen '%s' error: %s\n", modname,
|
||
|
dlerror ());
|
||
|
diff --git a/sysdeps/x86/tst-cet-legacy-6.c b/sysdeps/x86/tst-cet-legacy-6.c
|
||
|
index 9151225..184a35b 100644
|
||
|
--- a/sysdeps/x86/tst-cet-legacy-6.c
|
||
|
+++ b/sysdeps/x86/tst-cet-legacy-6.c
|
||
|
@@ -35,7 +35,8 @@ do_test_1 (const char *modname, bool fail)
|
||
|
if (fail)
|
||
|
{
|
||
|
const char *err = dlerror ();
|
||
|
- if (strstr (err, "shadow stack isn't enabled") == NULL)
|
||
|
+ if (strstr (err, "rebuild shared object with SHSTK support enabled")
|
||
|
+ == NULL)
|
||
|
{
|
||
|
printf ("incorrect dlopen '%s' error: %s\n", modname,
|
||
|
dlerror ());
|
||
|
diff --git a/sysdeps/x86/tst-cet-legacy-7.c b/sysdeps/x86/tst-cet-legacy-7.c
|
||
|
new file mode 100644
|
||
|
index 0000000..58bcb29
|
||
|
--- /dev/null
|
||
|
+++ b/sysdeps/x86/tst-cet-legacy-7.c
|
||
|
@@ -0,0 +1,38 @@
|
||
|
+/* Check compatibility of legacy executable with a JIT engine.
|
||
|
+ Copyright (C) 2020 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 <stdio.h>
|
||
|
+#include <sys/mman.h>
|
||
|
+#include <support/xunistd.h>
|
||
|
+
|
||
|
+/* Check that mmapped legacy code works with -fcf-protection=none. */
|
||
|
+
|
||
|
+static int
|
||
|
+do_test (void)
|
||
|
+{
|
||
|
+ void (*funcp) (void);
|
||
|
+ funcp = xmmap (NULL, 0x1000, PROT_EXEC | PROT_READ | PROT_WRITE,
|
||
|
+ MAP_ANONYMOUS | MAP_PRIVATE, -1);
|
||
|
+ printf ("mmap = %p\n", funcp);
|
||
|
+ /* Write RET instruction. */
|
||
|
+ *(char *) funcp = 0xc3;
|
||
|
+ funcp ();
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+#include <support/test-driver.c>
|
||
|
diff --git a/sysdeps/x86/tst-cet-legacy-8.c b/sysdeps/x86/tst-cet-legacy-8.c
|
||
|
new file mode 100644
|
||
|
index 0000000..11e8115
|
||
|
--- /dev/null
|
||
|
+++ b/sysdeps/x86/tst-cet-legacy-8.c
|
||
|
@@ -0,0 +1,48 @@
|
||
|
+/* Check incompatibility with legacy JIT engine.
|
||
|
+ Copyright (C) 2020 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 <stdio.h>
|
||
|
+#include <stdlib.h>
|
||
|
+#include <x86intrin.h>
|
||
|
+#include <sys/mman.h>
|
||
|
+#include <support/test-driver.h>
|
||
|
+#include <support/xsignal.h>
|
||
|
+#include <support/xunistd.h>
|
||
|
+
|
||
|
+/* Check that mmapped legacy code trigges segfault with -fcf-protection. */
|
||
|
+
|
||
|
+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);
|
||
|
+ printf ("mmap = %p\n", funcp);
|
||
|
+ /* Write RET instruction. */
|
||
|
+ *(char *) funcp = 0xc3;
|
||
|
+ funcp ();
|
||
|
+ return EXIT_FAILURE;
|
||
|
+}
|
||
|
+
|
||
|
+#define EXPECTED_SIGNAL (_get_ssp () == 0 ? 0 : SIGSEGV)
|
||
|
+#include <support/test-driver.c>
|
||
|
|