x86: Move CET control to _dl_x86_feature_control [BZ #25887]

1. Include <dl-procruntime.c> to get architecture specific initializer in
rtld_global.
2. Change _dl_x86_feature_1[2] to _dl_x86_feature_1.
3. Add _dl_x86_feature_control after _dl_x86_feature_1, which is a
struct of 2 bitfields for IBT and SHSTK control

This fixes [BZ #25887].
This commit is contained in:
H.J. Lu 2020-04-28 10:05:25 -07:00
parent cbfc16122e
commit 674ea88294
9 changed files with 81 additions and 68 deletions

View file

@ -315,6 +315,8 @@ rtld_hidden_def (_dl_starting_up)
(except those which cannot be added for some reason). */
struct rtld_global _rtld_global =
{
/* Get architecture specific initializer. */
#include <dl-procruntime.c>
/* Generally the default presumption without further information is an
* executable stack but this is not true for all platforms. */
._dl_stack_flags = DEFAULT_STACK_PERMS,

View file

@ -71,7 +71,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden;
/* Check if SHSTK is enabled by kernel. */
bool shstk_enabled
= (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
= (GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
if (l->l_info[DT_JMPREL] && lazy)
{

View file

@ -34,7 +34,7 @@ static inline void
x86_setup_tls (void)
{
__libc_setup_tls ();
THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1)[0]);
THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1));
}
# define ARCH_SETUP_TLS() x86_setup_tls ()

View file

@ -16,14 +16,26 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* Valid control values:
0: Enable CET features based on ELF property note.
1: Always disable CET features.
2: Always enable CET features.
3: Enable CET features permissively.
*/
#define CET_ELF_PROPERTY 0
#define CET_ALWAYS_OFF 1
#define CET_ALWAYS_ON 2
#define CET_PERMISSIVE 3
#define CET_MAX CET_PERMISSIVE
#ifndef _CET_CONTROL_H
#define _CET_CONTROL_H
/* For each CET feature, IBT and SHSTK, valid control values. */
enum dl_x86_cet_control
{
/* Enable CET features based on ELF property note. */
cet_elf_property = 0,
/* Always enable CET features. */
cet_always_on,
/* Always disable CET features. */
cet_always_off,
/* Enable CET features permissively. */
cet_permissive
};
struct dl_x86_feature_control
{
enum dl_x86_cet_control ibt : 2;
enum dl_x86_cet_control shstk : 2;
};
#endif /* cet-control.h */

View file

@ -39,7 +39,6 @@ extern void TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *)
#if CET_ENABLED
# include <dl-cet.h>
# include <cet-tunables.h>
#endif
static void
@ -620,7 +619,7 @@ no_cpuid:
if (cet_status)
{
GL(dl_x86_feature_1)[0] = cet_status;
GL(dl_x86_feature_1) = cet_status;
# ifndef SHARED
/* Check if IBT and SHSTK are enabled by kernel. */
@ -644,14 +643,13 @@ no_cpuid:
/* Clear the disabled bits in dl_x86_feature_1. */
if (res == 0)
GL(dl_x86_feature_1)[0] &= ~cet_feature;
GL(dl_x86_feature_1) &= ~cet_feature;
}
/* Lock CET if IBT or SHSTK is enabled in executable. Don't
lock CET if SHSTK is enabled permissively. */
if (((GL(dl_x86_feature_1)[1] >> CET_MAX)
& ((1 << CET_MAX) - 1))
!= CET_PERMISSIVE)
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 ();
}
# endif

View file

@ -336,28 +336,18 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
}
# if CET_ENABLED
# include <cet-tunables.h>
attribute_hidden
void
TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *valp)
{
if (DEFAULT_MEMCMP (valp->strval, "on", sizeof ("on")) == 0)
{
GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1);
GL(dl_x86_feature_1)[1] |= CET_ALWAYS_ON;
}
GL(dl_x86_feature_control).ibt = cet_always_on;
else if (DEFAULT_MEMCMP (valp->strval, "off", sizeof ("off")) == 0)
{
GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1);
GL(dl_x86_feature_1)[1] |= CET_ALWAYS_OFF;
}
GL(dl_x86_feature_control).ibt = cet_always_off;
else if (DEFAULT_MEMCMP (valp->strval, "permissive",
sizeof ("permissive")) == 0)
{
GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1);
GL(dl_x86_feature_1)[1] |= CET_PERMISSIVE;
}
GL(dl_x86_feature_control).ibt = cet_permissive;
}
attribute_hidden
@ -365,21 +355,12 @@ void
TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *valp)
{
if (DEFAULT_MEMCMP (valp->strval, "on", sizeof ("on")) == 0)
{
GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX);
GL(dl_x86_feature_1)[1] |= (CET_ALWAYS_ON << CET_MAX);
}
GL(dl_x86_feature_control).shstk = cet_always_on;
else if (DEFAULT_MEMCMP (valp->strval, "off", sizeof ("off")) == 0)
{
GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX);
GL(dl_x86_feature_1)[1] |= (CET_ALWAYS_OFF << CET_MAX);
}
GL(dl_x86_feature_control).shstk = cet_always_off;
else if (DEFAULT_MEMCMP (valp->strval, "permissive",
sizeof ("permissive")) == 0)
{
GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX);
GL(dl_x86_feature_1)[1] |= (CET_PERMISSIVE << CET_MAX);
}
GL(dl_x86_feature_control).shstk = cet_permissive;
}
# endif
#endif

View file

@ -20,7 +20,6 @@
#include <libintl.h>
#include <ldsodefs.h>
#include <dl-cet.h>
#include <cet-tunables.h>
/* GNU_PROPERTY_X86_FEATURE_1_IBT and GNU_PROPERTY_X86_FEATURE_1_SHSTK
are defined in <elf.h>, which are only available for C sources.
@ -39,23 +38,23 @@ static void
dl_cet_check (struct link_map *m, const char *program)
{
/* Check how IBT should be enabled. */
unsigned int enable_ibt_type
= GL(dl_x86_feature_1)[1] & ((1 << CET_MAX) - 1);
enum dl_x86_cet_control enable_ibt_type
= GL(dl_x86_feature_control).ibt;
/* Check how SHSTK should be enabled. */
unsigned int enable_shstk_type
= ((GL(dl_x86_feature_1)[1] >> CET_MAX) & ((1 << CET_MAX) - 1));
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)
if (enable_ibt_type == cet_always_on
&& enable_shstk_type == cet_always_on)
return;
/* Check if IBT is enabled by kernel. */
bool ibt_enabled
= (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0;
= (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)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
= (GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
if (ibt_enabled || shstk_enabled)
{
@ -65,9 +64,9 @@ dl_cet_check (struct link_map *m, const char *program)
/* Check if IBT and SHSTK are enabled in object. */
bool enable_ibt = (ibt_enabled
&& enable_ibt_type != CET_ALWAYS_OFF);
&& enable_ibt_type != cet_always_off);
bool enable_shstk = (shstk_enabled
&& enable_shstk_type != CET_ALWAYS_OFF);
&& enable_shstk_type != cet_always_off);
if (program)
{
/* Enable IBT and SHSTK only if they are enabled in executable.
@ -76,10 +75,10 @@ dl_cet_check (struct link_map *m, const char *program)
GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK
*/
enable_ibt &= (HAS_CPU_FEATURE (IBT)
&& (enable_ibt_type == CET_ALWAYS_ON
&& (enable_ibt_type == cet_always_on
|| (m->l_cet & lc_ibt) != 0));
enable_shstk &= (HAS_CPU_FEATURE (SHSTK)
&& (enable_shstk_type == CET_ALWAYS_ON
&& (enable_shstk_type == cet_always_on
|| (m->l_cet & lc_shstk) != 0));
}
@ -111,7 +110,7 @@ dl_cet_check (struct link_map *m, const char *program)
/* IBT is enabled only if it is enabled in executable as
well as all shared objects. */
enable_ibt &= (enable_ibt_type == CET_ALWAYS_ON
enable_ibt &= (enable_ibt_type == cet_always_on
|| (l->l_cet & lc_ibt) != 0);
if (!found_ibt_legacy && enable_ibt != ibt_enabled)
{
@ -121,7 +120,7 @@ dl_cet_check (struct link_map *m, const char *program)
/* SHSTK is enabled only if it is enabled in executable as
well as all shared objects. */
enable_shstk &= (enable_shstk_type == CET_ALWAYS_ON
enable_shstk &= (enable_shstk_type == cet_always_on
|| (l->l_cet & lc_shstk) != 0);
if (enable_shstk != shstk_enabled)
{
@ -137,7 +136,7 @@ dl_cet_check (struct link_map *m, const char *program)
{
if (!program)
{
if (enable_ibt_type != CET_PERMISSIVE)
if (enable_ibt_type != cet_permissive)
{
/* When IBT is enabled, we cannot dlopen a shared
object without IBT. */
@ -148,7 +147,7 @@ dl_cet_check (struct link_map *m, const char *program)
N_("rebuild shared object with IBT support enabled"));
}
if (enable_shstk_type != CET_PERMISSIVE)
if (enable_shstk_type != cet_permissive)
{
/* When SHSTK is enabled, we cannot dlopen a shared
object without SHSTK. */
@ -159,8 +158,8 @@ dl_cet_check (struct link_map *m, const char *program)
N_("rebuild shared object with SHSTK support enabled"));
}
if (enable_ibt_type != CET_PERMISSIVE
&& enable_shstk_type != CET_PERMISSIVE)
if (enable_ibt_type != cet_permissive
&& enable_shstk_type != cet_permissive)
return;
}
@ -190,7 +189,7 @@ dl_cet_check (struct link_map *m, const char *program)
}
/* Clear the disabled bits in dl_x86_feature_1. */
GL(dl_x86_feature_1)[0] &= ~cet_feature;
GL(dl_x86_feature_1) &= ~cet_feature;
cet_feature_changed = true;
}
@ -199,9 +198,9 @@ dl_cet_check (struct link_map *m, const char *program)
if (program && (ibt_enabled || shstk_enabled))
{
if ((!ibt_enabled
|| enable_ibt_type != CET_PERMISSIVE)
|| enable_ibt_type != cet_permissive)
&& (!shstk_enabled
|| enable_shstk_type != CET_PERMISSIVE))
|| enable_shstk_type != cet_permissive))
{
/* Lock CET if IBT or SHSTK is enabled in executable unless
IBT or SHSTK is enabled permissively. */

View file

@ -47,7 +47,27 @@
# if !defined PROCINFO_DECL && defined SHARED
._dl_x86_feature_1
# else
PROCINFO_CLASS unsigned int _dl_x86_feature_1[2]
PROCINFO_CLASS unsigned int _dl_x86_feature_1
# endif
# ifndef PROCINFO_DECL
= 0
# endif
# if !defined SHARED || defined PROCINFO_DECL
;
# else
,
# endif
# if !defined PROCINFO_DECL && defined SHARED
._dl_x86_feature_control
# else
PROCINFO_CLASS struct dl_x86_feature_control _dl_x86_feature_control
# endif
# ifndef PROCINFO_DECL
= {
.ibt = cet_elf_property,
.shstk = cet_elf_property
}
# endif
# if !defined SHARED || defined PROCINFO_DECL
;

View file

@ -61,6 +61,7 @@ struct La_x32_retval;
struct La_x86_64_retval *, \
const char *)
#include <cet-control.h>
#include_next <ldsodefs.h>
#endif