e354a5
commit 674ea88294bfb8d89878a0ebbbcec38a85e118a5
e354a5
Author: H.J. Lu <hjl.tools@gmail.com>
e354a5
Date:   Tue Apr 28 10:05:25 2020 -0700
e354a5
e354a5
    x86: Move CET control to _dl_x86_feature_control [BZ #25887]
e354a5
    
e354a5
    1. Include <dl-procruntime.c> to get architecture specific initializer in
e354a5
    rtld_global.
e354a5
    2. Change _dl_x86_feature_1[2] to _dl_x86_feature_1.
e354a5
    3. Add _dl_x86_feature_control after _dl_x86_feature_1, which is a
e354a5
    struct of 2 bitfields for IBT and SHSTK control
e354a5
    
e354a5
    This fixes [BZ #25887].
e354a5
---
e354a5
e354a5
diff --git a/elf/rtld.c b/elf/rtld.c
e354a5
index e107bd1..7f030f7 100644
e354a5
--- a/elf/rtld.c
e354a5
+++ b/elf/rtld.c
e354a5
@@ -230,6 +230,8 @@ rtld_hidden_def (_dl_starting_up)
e354a5
    (except those which cannot be added for some reason).  */
e354a5
 struct rtld_global _rtld_global =
e354a5
   {
e354a5
+    /* Get architecture specific initializer.  */
e354a5
+#include <dl-procruntime.c>
e354a5
     /* Generally the default presumption without further information is an
e354a5
      * executable stack but this is not true for all platforms.  */
e354a5
     ._dl_stack_flags = DEFAULT_STACK_PERMS,
e354a5
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
e354a5
index f6cfb90..8c959e3 100644
e354a5
--- a/sysdeps/i386/dl-machine.h
e354a5
+++ b/sysdeps/i386/dl-machine.h
e354a5
@@ -71,7 +71,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
e354a5
   extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden;
e354a5
   /* Check if SHSTK is enabled by kernel.  */
e354a5
   bool shstk_enabled
e354a5
-    = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
e354a5
+    = (GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
e354a5
 
e354a5
   if (l->l_info[DT_JMPREL] && lazy)
e354a5
     {
e354a5
diff --git a/sysdeps/unix/sysv/linux/x86/cpu-features.c b/sysdeps/unix/sysv/linux/x86/cpu-features.c
e354a5
index 8566a26..9f40624 100644
e354a5
--- a/sysdeps/unix/sysv/linux/x86/cpu-features.c
e354a5
+++ b/sysdeps/unix/sysv/linux/x86/cpu-features.c
e354a5
@@ -36,7 +36,7 @@ static inline void
e354a5
 x86_setup_tls (void)
e354a5
 {
e354a5
   __libc_setup_tls ();
e354a5
-  THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1)[0]);
e354a5
+  THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1));
e354a5
 }
e354a5
 
e354a5
 #  define ARCH_SETUP_TLS() x86_setup_tls ()
e354a5
diff --git a/sysdeps/x86/cet-control.h b/sysdeps/x86/cet-control.h
e354a5
new file mode 100644
e354a5
index 0000000..7b29f95
e354a5
--- /dev/null
e354a5
+++ b/sysdeps/x86/cet-control.h
e354a5
@@ -0,0 +1,41 @@
e354a5
+/* x86 CET tuning.
e354a5
+   This file is part of the GNU C Library.
e354a5
+   Copyright (C) 2018 Free Software Foundation, Inc.
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
+   <http://www.gnu.org/licenses/>.  */
e354a5
+
e354a5
+#ifndef _CET_CONTROL_H
e354a5
+#define _CET_CONTROL_H
e354a5
+
e354a5
+/* For each CET feature, IBT and SHSTK, valid control values.  */
e354a5
+enum dl_x86_cet_control
e354a5
+{
e354a5
+  /* Enable CET features based on ELF property note.  */
e354a5
+  cet_elf_property = 0,
e354a5
+  /* Always enable CET features.  */
e354a5
+  cet_always_on,
e354a5
+  /* Always disable CET features.  */
e354a5
+  cet_always_off,
e354a5
+  /* Enable CET features permissively.  */
e354a5
+  cet_permissive
e354a5
+};
e354a5
+
e354a5
+struct dl_x86_feature_control
e354a5
+{
e354a5
+  enum dl_x86_cet_control ibt : 2;
e354a5
+  enum dl_x86_cet_control shstk : 2;
e354a5
+};
e354a5
+
e354a5
+#endif /* cet-control.h */
e354a5
diff --git a/sysdeps/x86/cet-tunables.h b/sysdeps/x86/cet-tunables.h
e354a5
deleted file mode 100644
e354a5
index ca02305..0000000
e354a5
--- a/sysdeps/x86/cet-tunables.h
e354a5
+++ /dev/null
e354a5
@@ -1,29 +0,0 @@
e354a5
-/* x86 CET tuning.
e354a5
-   This file is part of the GNU C Library.
e354a5
-   Copyright (C) 2018 Free Software Foundation, Inc.
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
-   <http://www.gnu.org/licenses/>.  */
e354a5
-
e354a5
-/* Valid control values:
e354a5
-   0: Enable CET features based on ELF property note.
e354a5
-   1: Always disable CET features.
e354a5
-   2: Always enable CET features.
e354a5
-   3: Enable CET features permissively.
e354a5
- */
e354a5
-#define CET_ELF_PROPERTY	0
e354a5
-#define CET_ALWAYS_OFF		1
e354a5
-#define CET_ALWAYS_ON		2
e354a5
-#define CET_PERMISSIVE		3
e354a5
-#define CET_MAX			CET_PERMISSIVE
e354a5
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
e354a5
index 4695ac8..ac74f40 100644
e354a5
--- a/sysdeps/x86/cpu-features.c
e354a5
+++ b/sysdeps/x86/cpu-features.c
e354a5
@@ -39,7 +39,6 @@ extern void TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *)
e354a5
 
e354a5
 #if CET_ENABLED
e354a5
 # include <dl-cet.h>
e354a5
-# include <cet-tunables.h>
e354a5
 #endif
e354a5
 
e354a5
 static void
e354a5
@@ -490,7 +489,7 @@ no_cpuid:
e354a5
 
e354a5
   if (cet_status)
e354a5
     {
e354a5
-      GL(dl_x86_feature_1)[0] = cet_status;
e354a5
+      GL(dl_x86_feature_1) = cet_status;
e354a5
 
e354a5
 # ifndef SHARED
e354a5
       /* Check if IBT and SHSTK are enabled by kernel.  */
e354a5
@@ -514,14 +513,13 @@ no_cpuid:
e354a5
 
e354a5
 	      /* Clear the disabled bits in dl_x86_feature_1.  */
e354a5
 	      if (res == 0)
e354a5
-		GL(dl_x86_feature_1)[0] &= ~cet_feature;
e354a5
+		GL(dl_x86_feature_1) &= ~cet_feature;
e354a5
 	    }
e354a5
 
e354a5
 	  /* Lock CET if IBT or SHSTK is enabled in executable.  Don't
e354a5
-	     lock CET if SHSTK is enabled permissively.  */
e354a5
-	  if (((GL(dl_x86_feature_1)[1] >> CET_MAX)
e354a5
-	       & ((1 << CET_MAX) - 1))
e354a5
-	       != CET_PERMISSIVE)
e354a5
+	     lock CET if IBT or SHSTK is enabled permissively.  */
e354a5
+	  if (GL(dl_x86_feature_control).ibt != cet_permissive
e354a5
+	      && GL(dl_x86_feature_control).shstk != cet_permissive)
e354a5
 	    dl_cet_lock_cet ();
e354a5
 	}
e354a5
 # endif
e354a5
diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c
e354a5
index 69155a8..fad6726 100644
e354a5
--- a/sysdeps/x86/cpu-tunables.c
e354a5
+++ b/sysdeps/x86/cpu-tunables.c
e354a5
@@ -336,28 +336,18 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
e354a5
 }
e354a5
 
e354a5
 # if CET_ENABLED
e354a5
-#  include <cet-tunables.h>
e354a5
 
e354a5
 attribute_hidden
e354a5
 void
e354a5
 TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *valp)
e354a5
 {
e354a5
   if (DEFAULT_MEMCMP (valp->strval, "on", sizeof ("on")) == 0)
e354a5
-    {
e354a5
-      GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1);
e354a5
-      GL(dl_x86_feature_1)[1] |= CET_ALWAYS_ON;
e354a5
-    }
e354a5
+    GL(dl_x86_feature_control).ibt = cet_always_on;
e354a5
   else if (DEFAULT_MEMCMP (valp->strval, "off", sizeof ("off")) == 0)
e354a5
-    {
e354a5
-      GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1);
e354a5
-      GL(dl_x86_feature_1)[1] |= CET_ALWAYS_OFF;
e354a5
-    }
e354a5
+    GL(dl_x86_feature_control).ibt = cet_always_off;
e354a5
   else if (DEFAULT_MEMCMP (valp->strval, "permissive",
e354a5
 			   sizeof ("permissive")) == 0)
e354a5
-    {
e354a5
-      GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1);
e354a5
-      GL(dl_x86_feature_1)[1] |= CET_PERMISSIVE;
e354a5
-    }
e354a5
+    GL(dl_x86_feature_control).ibt = cet_permissive;
e354a5
 }
e354a5
 
e354a5
 attribute_hidden
e354a5
@@ -365,21 +355,12 @@ void
e354a5
 TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *valp)
e354a5
 {
e354a5
   if (DEFAULT_MEMCMP (valp->strval, "on", sizeof ("on")) == 0)
e354a5
-    {
e354a5
-      GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX);
e354a5
-      GL(dl_x86_feature_1)[1] |= (CET_ALWAYS_ON << CET_MAX);
e354a5
-    }
e354a5
+    GL(dl_x86_feature_control).shstk = cet_always_on;
e354a5
   else if (DEFAULT_MEMCMP (valp->strval, "off", sizeof ("off")) == 0)
e354a5
-    {
e354a5
-      GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX);
e354a5
-      GL(dl_x86_feature_1)[1] |= (CET_ALWAYS_OFF << CET_MAX);
e354a5
-    }
e354a5
+    GL(dl_x86_feature_control).shstk = cet_always_off;
e354a5
   else if (DEFAULT_MEMCMP (valp->strval, "permissive",
e354a5
 			   sizeof ("permissive")) == 0)
e354a5
-    {
e354a5
-      GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX);
e354a5
-      GL(dl_x86_feature_1)[1] |= (CET_PERMISSIVE << CET_MAX);
e354a5
-    }
e354a5
+    GL(dl_x86_feature_control).shstk = cet_permissive;
e354a5
 }
e354a5
 # endif
e354a5
 #endif
e354a5
diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c
e354a5
index 627d937..ebc0d57 100644
e354a5
--- a/sysdeps/x86/dl-cet.c
e354a5
+++ b/sysdeps/x86/dl-cet.c
e354a5
@@ -20,7 +20,6 @@
e354a5
 #include <libintl.h>
e354a5
 #include <ldsodefs.h>
e354a5
 #include <dl-cet.h>
e354a5
-#include <cet-tunables.h>
e354a5
 
e354a5
 /* GNU_PROPERTY_X86_FEATURE_1_IBT and GNU_PROPERTY_X86_FEATURE_1_SHSTK
e354a5
    are defined in <elf.h>, which are only available for C sources.
e354a5
@@ -39,23 +38,23 @@ static void
e354a5
 dl_cet_check (struct link_map *m, const char *program)
e354a5
 {
e354a5
   /* Check how IBT should be enabled.  */
e354a5
-  unsigned int enable_ibt_type
e354a5
-    = GL(dl_x86_feature_1)[1] & ((1 << CET_MAX) - 1);
e354a5
+  enum dl_x86_cet_control enable_ibt_type
e354a5
+    = GL(dl_x86_feature_control).ibt;
e354a5
   /* Check how SHSTK should be enabled.  */
e354a5
-  unsigned int enable_shstk_type
e354a5
-    = ((GL(dl_x86_feature_1)[1] >> CET_MAX) & ((1 << CET_MAX) - 1));
e354a5
+  enum dl_x86_cet_control enable_shstk_type
e354a5
+    = GL(dl_x86_feature_control).shstk;
e354a5
 
e354a5
   /* No legacy object check if both IBT and SHSTK are always on.  */
e354a5
-  if (enable_ibt_type == CET_ALWAYS_ON
e354a5
-      && enable_shstk_type == CET_ALWAYS_ON)
e354a5
+  if (enable_ibt_type == cet_always_on
e354a5
+      && enable_shstk_type == cet_always_on)
e354a5
     return;
e354a5
 
e354a5
   /* Check if IBT is enabled by kernel.  */
e354a5
   bool ibt_enabled
e354a5
-    = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0;
e354a5
+    = (GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0;
e354a5
   /* Check if SHSTK is enabled by kernel.  */
e354a5
   bool shstk_enabled
e354a5
-    = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
e354a5
+    = (GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
e354a5
 
e354a5
   if (ibt_enabled || shstk_enabled)
e354a5
     {
e354a5
@@ -65,9 +64,9 @@ dl_cet_check (struct link_map *m, const char *program)
e354a5
 
e354a5
       /* Check if IBT and SHSTK are enabled in object.  */
e354a5
       bool enable_ibt = (ibt_enabled
e354a5
-			 && enable_ibt_type != CET_ALWAYS_OFF);
e354a5
+			 && enable_ibt_type != cet_always_off);
e354a5
       bool enable_shstk = (shstk_enabled
e354a5
-			   && enable_shstk_type != CET_ALWAYS_OFF);
e354a5
+			   && enable_shstk_type != cet_always_off);
e354a5
       if (program)
e354a5
 	{
e354a5
 	  /* Enable IBT and SHSTK only if they are enabled in executable.
e354a5
@@ -76,10 +75,10 @@ dl_cet_check (struct link_map *m, const char *program)
e354a5
 	     GLIBC_TUNABLES=glibc.tune.hwcaps=-IBT,-SHSTK
e354a5
 	   */
e354a5
 	  enable_ibt &= (HAS_CPU_FEATURE (IBT)
e354a5
-			 && (enable_ibt_type == CET_ALWAYS_ON
e354a5
+			 && (enable_ibt_type == cet_always_on
e354a5
 			     || (m->l_cet & lc_ibt) != 0));
e354a5
 	  enable_shstk &= (HAS_CPU_FEATURE (SHSTK)
e354a5
-			   && (enable_shstk_type == CET_ALWAYS_ON
e354a5
+			   && (enable_shstk_type == cet_always_on
e354a5
 			       || (m->l_cet & lc_shstk) != 0));
e354a5
 	}
e354a5
 
e354a5
@@ -111,7 +110,7 @@ dl_cet_check (struct link_map *m, const char *program)
e354a5
 
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
+	      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
@@ -121,7 +120,7 @@ dl_cet_check (struct link_map *m, const char *program)
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
+	      enable_shstk &= (enable_shstk_type == cet_always_on
e354a5
 			       || (l->l_cet & lc_shstk) != 0);
e354a5
 	      if (enable_shstk != shstk_enabled)
e354a5
 		{
e354a5
@@ -137,7 +136,7 @@ dl_cet_check (struct link_map *m, const char *program)
e354a5
 	{
e354a5
 	  if (!program)
e354a5
 	    {
e354a5
-	      if (enable_ibt_type != CET_PERMISSIVE)
e354a5
+	      if (enable_ibt_type != cet_permissive)
e354a5
 		{
e354a5
 		  /* When IBT is enabled, we cannot dlopen a shared
e354a5
 		     object without IBT.  */
e354a5
@@ -148,7 +147,7 @@ dl_cet_check (struct link_map *m, const char *program)
e354a5
 				      N_("rebuild shared object with IBT support enabled"));
e354a5
 		}
e354a5
 
e354a5
-	      if (enable_shstk_type != CET_PERMISSIVE)
e354a5
+	      if (enable_shstk_type != cet_permissive)
e354a5
 		{
e354a5
 		  /* When SHSTK is enabled, we cannot dlopen a shared
e354a5
 		     object without SHSTK.  */
e354a5
@@ -159,8 +158,8 @@ dl_cet_check (struct link_map *m, const char *program)
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
+	      if (enable_ibt_type != cet_permissive
e354a5
+		  && enable_shstk_type != cet_permissive)
e354a5
 		return;
e354a5
 	    }
e354a5
 
e354a5
@@ -190,7 +189,7 @@ dl_cet_check (struct link_map *m, const char *program)
e354a5
 	    }
e354a5
 
e354a5
 	  /* Clear the disabled bits in dl_x86_feature_1.  */
e354a5
-	  GL(dl_x86_feature_1)[0] &= ~cet_feature;
e354a5
+	  GL(dl_x86_feature_1) &= ~cet_feature;
e354a5
 
e354a5
 	  cet_feature_changed = true;
e354a5
 	}
e354a5
@@ -199,9 +198,9 @@ dl_cet_check (struct link_map *m, const char *program)
e354a5
       if (program && (ibt_enabled || shstk_enabled))
e354a5
 	{
e354a5
 	  if ((!ibt_enabled
e354a5
-	       || enable_ibt_type != CET_PERMISSIVE)
e354a5
+	       || enable_ibt_type != cet_permissive)
e354a5
 	      && (!shstk_enabled
e354a5
-		  || enable_shstk_type != CET_PERMISSIVE))
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
diff --git a/sysdeps/x86/dl-procruntime.c b/sysdeps/x86/dl-procruntime.c
e354a5
index 920bfe8..26b2b39 100644
e354a5
--- a/sysdeps/x86/dl-procruntime.c
e354a5
+++ b/sysdeps/x86/dl-procruntime.c
e354a5
@@ -47,7 +47,27 @@
e354a5
 # if !defined PROCINFO_DECL && defined SHARED
e354a5
   ._dl_x86_feature_1
e354a5
 # else
e354a5
-PROCINFO_CLASS unsigned int _dl_x86_feature_1[2]
e354a5
+PROCINFO_CLASS unsigned int _dl_x86_feature_1
e354a5
+# endif
e354a5
+# ifndef PROCINFO_DECL
e354a5
+= 0
e354a5
+# endif
e354a5
+# if !defined SHARED || defined PROCINFO_DECL
e354a5
+;
e354a5
+# else
e354a5
+,
e354a5
+# endif
e354a5
+
e354a5
+# if !defined PROCINFO_DECL && defined SHARED
e354a5
+  ._dl_x86_feature_control
e354a5
+# else
e354a5
+PROCINFO_CLASS struct dl_x86_feature_control _dl_x86_feature_control
e354a5
+# endif
e354a5
+# ifndef PROCINFO_DECL
e354a5
+= {
e354a5
+    .ibt = cet_elf_property,
e354a5
+    .shstk = cet_elf_property
e354a5
+  }
e354a5
 # endif
e354a5
 # if !defined SHARED || defined PROCINFO_DECL
e354a5
 ;
e354a5
diff --git a/sysdeps/x86/ldsodefs.h b/sysdeps/x86/ldsodefs.h
e354a5
index 0616215..54f6864 100644
e354a5
--- a/sysdeps/x86/ldsodefs.h
e354a5
+++ b/sysdeps/x86/ldsodefs.h
e354a5
@@ -61,6 +61,7 @@ struct La_x32_retval;
e354a5
 				     struct La_x86_64_retval *,		\
e354a5
 				     const char *)
e354a5
 
e354a5
+#include <cet-control.h>
e354a5
 #include_next <ldsodefs.h>
e354a5
 
e354a5
 #endif
e354a5