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