Message ID | 20201229213053.16395-5-yu-cheng.yu@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Control-flow Enforcement: Shadow Stack | expand |
On Tue, Dec 29, 2020 at 01:30:31PM -0800, Yu-cheng Yu wrote: > @@ -895,6 +903,12 @@ static void init_speculation_control(struct cpuinfo_x86 *c) > } > } > > +static void init_cet_features(struct cpuinfo_x86 *c) > +{ > + if (cpu_has(c, X86_FEATURE_SHSTK) || cpu_has(c, X86_FEATURE_IBT)) > + set_cpu_cap(c, X86_FEATURE_CET); > +} No need for that function - just add this two-liner to bsp_init_intel() and not in get_cpu_cap(). > +static void adjust_combined_cpu_features(void) > +{ > +#ifdef CONFIG_X86_CET_USER > + if (test_bit(X86_FEATURE_SHSTK, (unsigned long *)cpu_caps_cleared) && > + test_bit(X86_FEATURE_IBT, (unsigned long *)cpu_caps_cleared)) > + setup_clear_cpu_cap(X86_FEATURE_CET); > +#endif There's no need for this function... > +} > + > /* > * We parse cpu parameters early because fpu__init_system() is executed > * before parse_early_param(). > @@ -1252,9 +1276,19 @@ static void __init cpu_parse_early_param(void) > if (cmdline_find_option_bool(boot_command_line, "noxsaves")) > setup_clear_cpu_cap(X86_FEATURE_XSAVES); > > + /* > + * CET states are XSAVES states and options must be parsed early. > + */ > +#ifdef CONFIG_X86_CET_USER > + if (cmdline_find_option_bool(boot_command_line, "no_user_shstk")) > + setup_clear_cpu_cap(X86_FEATURE_SHSTK); ... when you can do setup_clear_cpu_cap(X86_FEATURE_CET); here and... > + if (cmdline_find_option_bool(boot_command_line, "no_user_ibt")) > + setup_clear_cpu_cap(X86_FEATURE_IBT); ... here. Thx.
On 1/11/2021 9:56 AM, Borislav Petkov wrote: > On Tue, Dec 29, 2020 at 01:30:31PM -0800, Yu-cheng Yu wrote: >> @@ -895,6 +903,12 @@ static void init_speculation_control(struct cpuinfo_x86 *c) >> } >> } >> >> +static void init_cet_features(struct cpuinfo_x86 *c) >> +{ >> + if (cpu_has(c, X86_FEATURE_SHSTK) || cpu_has(c, X86_FEATURE_IBT)) >> + set_cpu_cap(c, X86_FEATURE_CET); >> +} > > No need for that function - just add this two-liner to bsp_init_intel() > and not in get_cpu_cap(). > I will move these to bsp_init_intel(), and change to: if (cpu_has(c, X86_FEATURE_SHSTK) || cpu_has(c, X86_FEATURE_IBT)) setup_force_cpu_cap(X86_FEATURE_CET); >> +static void adjust_combined_cpu_features(void) >> +{ >> +#ifdef CONFIG_X86_CET_USER >> + if (test_bit(X86_FEATURE_SHSTK, (unsigned long *)cpu_caps_cleared) && >> + test_bit(X86_FEATURE_IBT, (unsigned long *)cpu_caps_cleared)) >> + setup_clear_cpu_cap(X86_FEATURE_CET); >> +#endif > > There's no need for this function... > >> +} >> + >> /* >> * We parse cpu parameters early because fpu__init_system() is executed >> * before parse_early_param(). >> @@ -1252,9 +1276,19 @@ static void __init cpu_parse_early_param(void) >> if (cmdline_find_option_bool(boot_command_line, "noxsaves")) >> setup_clear_cpu_cap(X86_FEATURE_XSAVES); >> >> + /* >> + * CET states are XSAVES states and options must be parsed early. >> + */ >> +#ifdef CONFIG_X86_CET_USER >> + if (cmdline_find_option_bool(boot_command_line, "no_user_shstk")) >> + setup_clear_cpu_cap(X86_FEATURE_SHSTK); > > ... when you can do > > setup_clear_cpu_cap(X86_FEATURE_CET); > > here and... > >> + if (cmdline_find_option_bool(boot_command_line, "no_user_ibt")) >> + setup_clear_cpu_cap(X86_FEATURE_IBT); > > ... here. > Two problems here. X86_FEATURE_CET indicates either CET features is enabled, not both. Also, "clearcpuid" can has CET features. However, since X86_FEATURE_CET is now set in bsp_init_intel() (after cpu_parse_early_params()), I think, adjust_combined_cpu_features() can be removed. I will test it. -- Thanks, Yu-cheng
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 292fe87b26b3..d1866659edbd 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -108,7 +108,7 @@ #define X86_FEATURE_EXTD_APICID ( 3*32+26) /* Extended APICID (8 bits) */ #define X86_FEATURE_AMD_DCM ( 3*32+27) /* AMD multi-node processor */ #define X86_FEATURE_APERFMPERF ( 3*32+28) /* P-State hardware coordination feedback capability (APERF/MPERF MSRs) */ -/* free ( 3*32+29) */ +#define X86_FEATURE_CET ( 3*32+29) /* Control-flow enforcement */ #define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */ #define X86_FEATURE_TSC_KNOWN_FREQ ( 3*32+31) /* TSC has known frequency */ diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h index 4d3b7ce509e5..86ac4a1c6d81 100644 --- a/arch/x86/include/asm/disabled-features.h +++ b/arch/x86/include/asm/disabled-features.h @@ -71,9 +71,11 @@ #ifdef CONFIG_X86_CET_USER #define DISABLE_SHSTK 0 #define DISABLE_IBT 0 +#define DISABLE_CET 0 #else #define DISABLE_SHSTK (1 << (X86_FEATURE_SHSTK & 31)) #define DISABLE_IBT (1 << (X86_FEATURE_IBT & 31)) +#define DISABLE_CET (1 << (X86_FEATURE_CET & 31)) #endif /* @@ -82,7 +84,8 @@ #define DISABLED_MASK0 (DISABLE_VME) #define DISABLED_MASK1 0 #define DISABLED_MASK2 0 -#define DISABLED_MASK3 (DISABLE_CYRIX_ARR|DISABLE_CENTAUR_MCR|DISABLE_K6_MTRR) +#define DISABLED_MASK3 (DISABLE_CYRIX_ARR|DISABLE_CENTAUR_MCR|DISABLE_K6_MTRR| \ + DISABLE_CET) #define DISABLED_MASK4 (DISABLE_PCID) #define DISABLED_MASK5 0 #define DISABLED_MASK6 0 diff --git a/arch/x86/include/uapi/asm/processor-flags.h b/arch/x86/include/uapi/asm/processor-flags.h index bcba3c643e63..a8df907e8017 100644 --- a/arch/x86/include/uapi/asm/processor-flags.h +++ b/arch/x86/include/uapi/asm/processor-flags.h @@ -130,6 +130,8 @@ #define X86_CR4_SMAP _BITUL(X86_CR4_SMAP_BIT) #define X86_CR4_PKE_BIT 22 /* enable Protection Keys support */ #define X86_CR4_PKE _BITUL(X86_CR4_PKE_BIT) +#define X86_CR4_CET_BIT 23 /* enable Control-flow Enforcement */ +#define X86_CR4_CET _BITUL(X86_CR4_CET_BIT) /* * x86-64 Task Priority Register, CR8 diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 35ad8480c464..03c367f79adc 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -510,6 +510,14 @@ static __init int setup_disable_pku(char *arg) __setup("nopku", setup_disable_pku); #endif /* CONFIG_X86_64 */ +static __always_inline void setup_cet(struct cpuinfo_x86 *c) +{ + if (!cpu_feature_enabled(X86_FEATURE_CET)) + return; + + cr4_set_bits(X86_CR4_CET); +} + /* * Some CPU features depend on higher CPUID levels, which may not always * be available due to CPUID level capping or broken virtualization @@ -895,6 +903,12 @@ static void init_speculation_control(struct cpuinfo_x86 *c) } } +static void init_cet_features(struct cpuinfo_x86 *c) +{ + if (cpu_has(c, X86_FEATURE_SHSTK) || cpu_has(c, X86_FEATURE_IBT)) + set_cpu_cap(c, X86_FEATURE_CET); +} + void get_cpu_cap(struct cpuinfo_x86 *c) { u32 eax, ebx, ecx, edx; @@ -960,6 +974,7 @@ void get_cpu_cap(struct cpuinfo_x86 *c) if (c->extended_cpuid_level >= 0x8000000a) c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a); + init_cet_features(c); init_scattered_cpuid_features(c); init_speculation_control(c); @@ -1221,6 +1236,15 @@ static void detect_nopl(void) #endif } +static void adjust_combined_cpu_features(void) +{ +#ifdef CONFIG_X86_CET_USER + if (test_bit(X86_FEATURE_SHSTK, (unsigned long *)cpu_caps_cleared) && + test_bit(X86_FEATURE_IBT, (unsigned long *)cpu_caps_cleared)) + setup_clear_cpu_cap(X86_FEATURE_CET); +#endif +} + /* * We parse cpu parameters early because fpu__init_system() is executed * before parse_early_param(). @@ -1252,9 +1276,19 @@ static void __init cpu_parse_early_param(void) if (cmdline_find_option_bool(boot_command_line, "noxsaves")) setup_clear_cpu_cap(X86_FEATURE_XSAVES); + /* + * CET states are XSAVES states and options must be parsed early. + */ +#ifdef CONFIG_X86_CET_USER + if (cmdline_find_option_bool(boot_command_line, "no_user_shstk")) + setup_clear_cpu_cap(X86_FEATURE_SHSTK); + if (cmdline_find_option_bool(boot_command_line, "no_user_ibt")) + setup_clear_cpu_cap(X86_FEATURE_IBT); +#endif + arglen = cmdline_find_option(boot_command_line, "clearcpuid", arg, sizeof(arg)); if (arglen <= 0) - return; + goto done; pr_info("Clearing CPUID bits:"); do { @@ -1272,6 +1306,9 @@ static void __init cpu_parse_early_param(void) } } while (res == 2); pr_cont("\n"); + +done: + adjust_combined_cpu_features(); } /* @@ -1591,6 +1628,7 @@ static void identify_cpu(struct cpuinfo_x86 *c) x86_init_rdrand(c); setup_pku(c); + setup_cet(c); /* * Clear/Set all flags overridden by options, need do it
Introduce a software-defined X86_FEATURE_CET, which indicates either Shadow Stack or Indirect Branch Tracking (or both) is present. Also introduce related cpu init/setup functions. Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com> --- arch/x86/include/asm/cpufeatures.h | 2 +- arch/x86/include/asm/disabled-features.h | 5 ++- arch/x86/include/uapi/asm/processor-flags.h | 2 ++ arch/x86/kernel/cpu/common.c | 40 ++++++++++++++++++++- 4 files changed, 46 insertions(+), 3 deletions(-)