x86-64/cet: Make CET feature check specific to Linux/x86

CET feature bits in TCB, which are Linux specific, are used to check if
CET features are active.  Move CET feature check to Linux/x86 directory.
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
This commit is contained in:
H.J. Lu 2024-01-10 08:48:47 -08:00
parent db57da5be2
commit f2b65a4471
9 changed files with 120 additions and 37 deletions

View File

@ -0,0 +1,48 @@
/* Inline functions for x86 CPU features.
This file is part of the GNU C Library.
Copyright (C) 2024 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/>. */
#ifndef _SYS_PLATFORM_X86_H
# error "Never include <bits/platform/features.h> directly; use <sys/platform/x86.h> instead."
#endif
/* Bits in the feature_1 field in TCB. */
enum
{
x86_feature_1_ibt = 1U << 0,
x86_feature_1_shstk = 1U << 1
};
static __inline__ _Bool
x86_cpu_cet_active (unsigned int __index)
{
#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
}

View File

@ -54,6 +54,14 @@ dl_cet_get_cet_status (void)
return status; return status;
} }
static __always_inline bool
dl_cet_ibt_enabled (void)
{
unsigned int feature_1 = THREAD_GETMEM (THREAD_SELF,
header.feature_1);
return (feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0;
}
/* Enable shadow stack with a macro to avoid shadow stack underflow. */ /* Enable shadow stack with a macro to avoid shadow stack underflow. */
#define ENABLE_X86_CET(cet_feature) \ #define ENABLE_X86_CET(cet_feature) \
if ((cet_feature & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) \ if ((cet_feature & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) \

View File

@ -0,0 +1,24 @@
/* Get CPUID feature leaf. Linux/x86-64 version.
Copyright (C) 2024 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 <sysdeps/x86/get-cpuid-feature-leaf.c>
#ifdef __LP64__
_Static_assert (FEATURE_1_OFFSET == 72, "FEATURE_1_OFFSET != 72");
#else
_Static_assert (FEATURE_1_OFFSET == 40, "FEATURE_1_OFFSET != 40");
#endif

View File

@ -5,7 +5,11 @@ endif
ifeq ($(subdir),elf) ifeq ($(subdir),elf)
sysdep_routines += get-cpuid-feature-leaf sysdep_routines += get-cpuid-feature-leaf
sysdep-dl-routines += dl-get-cpu-features sysdep-dl-routines += dl-get-cpu-features
sysdep_headers += sys/platform/x86.h bits/platform/x86.h sysdep_headers += \
bits/platform/features.h \
bits/platform/x86.h \
sys/platform/x86.h \
# sysdep_headers
CFLAGS-dl-get-cpu-features.os += $(rtld-early-cflags) CFLAGS-dl-get-cpu-features.os += $(rtld-early-cflags)
CFLAGS-get-cpuid-feature-leaf.o += $(no-stack-protector) CFLAGS-get-cpuid-feature-leaf.o += $(no-stack-protector)

View File

@ -0,0 +1,27 @@
/* Inline functions for x86 CPU features.
This file is part of the GNU C Library.
Copyright (C) 2024 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/>. */
#ifndef _SYS_PLATFORM_X86_H
# error "Never include <bits/platform/features.h> directly; use <sys/platform/x86.h> instead."
#endif
static __inline__ _Bool
x86_cpu_cet_active (unsigned int __index)
{
return false;
}

View File

@ -337,11 +337,3 @@ enum
x86_cpu_AVX10_YMM = x86_cpu_index_24_ecx_0_ebx + 17, x86_cpu_AVX10_YMM = x86_cpu_index_24_ecx_0_ebx + 17,
x86_cpu_AVX10_ZMM = x86_cpu_index_24_ecx_0_ebx + 18, x86_cpu_AVX10_ZMM = x86_cpu_index_24_ecx_0_ebx + 18,
}; };
/* Bits in the feature_1 field in TCB. */
enum
{
x86_feature_1_ibt = 1U << 0,
x86_feature_1_shstk = 1U << 1
};

View File

@ -19,14 +19,6 @@
#include <tcb-offsets.h> #include <tcb-offsets.h>
#include <ldsodefs.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 * const struct cpuid_feature *
__x86_get_cpuid_feature_leaf (unsigned int leaf) __x86_get_cpuid_feature_leaf (unsigned int leaf)
{ {

View File

@ -22,6 +22,7 @@
#include <features.h> #include <features.h>
#include <stdbool.h> #include <stdbool.h>
#include <bits/platform/x86.h> #include <bits/platform/x86.h>
#include <bits/platform/features.h>
__BEGIN_DECLS __BEGIN_DECLS
@ -46,22 +47,8 @@ static __inline__ _Bool
x86_cpu_active (unsigned int __index) x86_cpu_active (unsigned int __index)
{ {
if (__index == x86_cpu_IBT || __index == x86_cpu_SHSTK) if (__index == x86_cpu_IBT || __index == x86_cpu_SHSTK)
{ return x86_cpu_cet_active (__index);
#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 const struct cpuid_feature *__ptr = __x86_get_cpuid_feature_leaf
(__index / (8 * sizeof (unsigned int) * 4)); (__index / (8 * sizeof (unsigned int) * 4));
unsigned int __reg unsigned int __reg

View File

@ -587,10 +587,11 @@ x86_64_rewrite_plt (struct link_map *map, ElfW(Addr) plt_rewrite)
const ElfW(Rela) *reloc = (const void *) start; const ElfW(Rela) *reloc = (const void *) start;
const ElfW(Rela) *reloc_end = (const void *) (start + size); const ElfW(Rela) *reloc_end = (const void *) (start + size);
unsigned int feature_1 = THREAD_GETMEM (THREAD_SELF, # ifdef __CET__
header.feature_1); bool ibt_enabled_p = dl_cet_ibt_enabled ();
bool ibt_enabled_p # else
= (feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0; bool ibt_enabled_p = false;
# endif
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
_dl_debug_printf ("\nchanging PLT in '%s' to direct branch\n", _dl_debug_printf ("\nchanging PLT in '%s' to direct branch\n",