[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 2/2] x86/shskt: Disable CET-SS on parts succeptable to fractured updates



On Sat, Dec 31, 2022 at 12:30:07AM +0000, Andrew Cooper wrote:
> Refer to Intel SDM Rev 70 (Dec 2022), Vol3 17.2.3 "Supervisor Shadow Stack
> Token".
> 
> Architecturally, an event delivery which starts in CPL>3 and switches shadow
> stack will first validate the Supervisor Shstk Token and set the busy bit,
> then pushes LIP/CS/SSP.  One example of this is an NMI interrupting Xen.
> 
> Some CPUs suffer from an issue called fracturing, whereby a fault/vmexit/etc
> between setting the busy bit and completing the event injection renders the
> action non-restartable, because when it comes time to restart, the busy bit is
> found to be already set.
> 
> This is far more easily encountered under virt, yet it is not the fault of the
> hypervisor, nor the fault of the guest kernel.  The fault lies somewhere
> between the architectural specification, and the uarch behaviour.
> 
> Intel have allocated CPUID.7[1].ecx[18] CET_SSS to enumerate that supervisor
> shadow stacks are safe to use.  Because of how Xen lays out its shadow stacks,
> fracturing is not expected to be a problem on native.
> 
> Detect this case on boot and default to not using shstk if virtualised.
> Specifying `cet=shstk` on the command line will override this heurstic and
> enable shadow stacks irrespective.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
> ---
> CC: Jan Beulich <JBeulich@xxxxxxxx>
> CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
> CC: Wei Liu <wl@xxxxxxx>
> 
> I've got a query out with AMD, but so far it is only Intel CPUs known to be
> impacted.
> 
> This ideally wants backporting to Xen 4.14.  I have no idea how likely it is
> to need to backport the prerequisite patch for new feature words, but we've
> already had to do that once for security patches...
> ---
>  docs/misc/xen-command-line.pandoc           |  7 +++++-
>  tools/libs/light/libxl_cpuid.c              |  2 ++
>  tools/misc/xen-cpuid.c                      |  1 +
>  xen/arch/x86/cpu/common.c                   | 11 +++++++--
>  xen/arch/x86/setup.c                        | 37 
> ++++++++++++++++++++++++++---
>  xen/include/public/arch-x86/cpufeatureset.h |  1 +
>  6 files changed, 53 insertions(+), 6 deletions(-)
> 
> diff --git a/docs/misc/xen-command-line.pandoc 
> b/docs/misc/xen-command-line.pandoc
> index 923910f553c5..19d4d815bdee 100644
> --- a/docs/misc/xen-command-line.pandoc
> +++ b/docs/misc/xen-command-line.pandoc
> @@ -287,10 +287,15 @@ can be maintained with the pv-shim mechanism.
>      protection.
>  
>      The option is available when `CONFIG_XEN_SHSTK` is compiled in, and
> -    defaults to `true` on hardware supporting CET-SS.  Specifying
> +    generally defaults to `true` on hardware supporting CET-SS.  Specifying
>      `cet=no-shstk` will cause Xen not to use Shadow Stacks even when support
>      is available in hardware.
>  
> +    Some hardware suffers from an issue known as Supervisor Shadow Stack
> +    Fracturing.  On such hardware, Xen will default to not using Shadow 
> Stacks
> +    when virtualised.  Specifying `cet=shstk` will override this heuristic 
> and
> +    enable Shadow Stacks unilaterally.
> +
>  *   The `ibt=` boolean controls whether Xen uses Indirect Branch Tracking for
>      its own protection.
>  
> diff --git a/tools/libs/light/libxl_cpuid.c b/tools/libs/light/libxl_cpuid.c
> index 2aa23225f42c..d97a2f3338bc 100644
> --- a/tools/libs/light/libxl_cpuid.c
> +++ b/tools/libs/light/libxl_cpuid.c
> @@ -235,6 +235,8 @@ int libxl_cpuid_parse_config(libxl_cpuid_policy_list 
> *cpuid, const char* str)
>          {"fsrs",         0x00000007,  1, CPUID_REG_EAX, 11,  1},
>          {"fsrcs",        0x00000007,  1, CPUID_REG_EAX, 12,  1},
>  
> +        {"cet-sss",      0x00000007,  1, CPUID_REG_EDX, 18,  1},
> +
>          {"intel-psfd",   0x00000007,  2, CPUID_REG_EDX,  0,  1},
>          {"mcdt-no",      0x00000007,  2, CPUID_REG_EDX,  5,  1},
>  
> diff --git a/tools/misc/xen-cpuid.c b/tools/misc/xen-cpuid.c
> index 0091a11a67bc..ea33b587665d 100644
> --- a/tools/misc/xen-cpuid.c
> +++ b/tools/misc/xen-cpuid.c
> @@ -208,6 +208,7 @@ static const char *const str_7c1[32] =
>  
>  static const char *const str_7d1[32] =
>  {
> +    [18] = "cet-sss",
>  };
>  
>  static const char *const str_7d2[32] =
> diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
> index b3fcf4680f3a..d962f384a995 100644
> --- a/xen/arch/x86/cpu/common.c
> +++ b/xen/arch/x86/cpu/common.c
> @@ -346,11 +346,18 @@ void __init early_cpu_init(void)
>              x86_cpuid_vendor_to_str(c->x86_vendor), c->x86, c->x86,
>              c->x86_model, c->x86_model, c->x86_mask, eax);
>  
> -     if (c->cpuid_level >= 7)
> -             cpuid_count(7, 0, &eax, &ebx,
> +     if (c->cpuid_level >= 7) {
> +             uint32_t max_subleaf;
> +
> +             cpuid_count(7, 0, &max_subleaf, &ebx,
>                           &c->x86_capability[FEATURESET_7c0],
>                           &c->x86_capability[FEATURESET_7d0]);
>  
> +                if (max_subleaf >= 1)

tabs vs spaces ...

Is this file imported from Linux? It uses tabs for indentation, contrary
to the rest of the Xen code base.

> +                     cpuid_count(7, 1, &eax, &ebx, &ecx,
> +                                 &c->x86_capability[FEATURESET_7d1]);
> +        }
> +
>       eax = cpuid_eax(0x80000000);
>       if ((eax >> 16) == 0x8000 && eax >= 0x80000008) {
>               ebx = eax >= 0x8000001f ? cpuid_ebx(0x8000001f) : 0;
> diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
> index 566422600d94..e052b7b748fa 100644
> --- a/xen/arch/x86/setup.c
> +++ b/xen/arch/x86/setup.c
> @@ -96,7 +96,7 @@ size_param("highmem-start", highmem_start);
>  #endif
>  
>  #ifdef CONFIG_XEN_SHSTK
> -static bool __initdata opt_xen_shstk = true;
> +static int8_t __initdata opt_xen_shstk = -1;
>  #else
>  #define opt_xen_shstk false
>  #endif
> @@ -1101,9 +1101,40 @@ void __init noreturn __start_xen(unsigned long mbi_p)
>      /* Choose shadow stack early, to set infrastructure up appropriately. */
>      if ( opt_xen_shstk && boot_cpu_has(X86_FEATURE_CET_SS) )
>      {
> -        printk("Enabling Supervisor Shadow Stacks\n");
> +        /*
> +         * Some CPUs suffer from Shadow Stack Fracturing, an issue whereby a
> +         * fault/VMExit/etc between setting a Supervisor Busy bit and the
> +         * event delivery completing renders the operation non-restartable.
> +         * On restart, event delivery will find the Busy bit already set.
> +         *
> +         * This is a problem on native, but outside of synthetic cases, only
> +         * with #MC against a stack access (in which case we're dead anyway).
> +         * It is a much bigger problem under virt, because we can VMExit for 
> a
> +         * number of legitimate reasons and tickle this bug.
> +         *
> +         * CPUs with this addressed enumerate CET-SSS to indicate that
> +         * supervisor shadow stacks are now safe to use.
> +         */
> +        bool cpu_has_bug_shstk_fracture =
> +            boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
> +            !boot_cpu_has(X86_FEATURE_CET_SSS);
> +
> +        /*
> +         * On native, assume that Xen won't be impacted by shstk fracturing
> +         * problems.  Under virt, be more conservative and disable shstk by
> +         * default.
> +         */
> +        if ( opt_xen_shstk == -1 )
> +            opt_xen_shstk =
> +                cpu_has_hypervisor ? !cpu_has_bug_shstk_fracture
> +                                   : true;
> +
> +        if ( opt_xen_shstk )
> +        {
> +            printk("Enabling Supervisor Shadow Stacks\n");
>  
> -        setup_force_cpu_cap(X86_FEATURE_XEN_SHSTK);
> +            setup_force_cpu_cap(X86_FEATURE_XEN_SHSTK);
> +        }
>      }
>  
>      if ( opt_xen_ibt && boot_cpu_has(X86_FEATURE_CET_IBT) )
> diff --git a/xen/include/public/arch-x86/cpufeatureset.h 
> b/xen/include/public/arch-x86/cpufeatureset.h
> index 7a896f0e2d92..f6a46f62a549 100644
> --- a/xen/include/public/arch-x86/cpufeatureset.h
> +++ b/xen/include/public/arch-x86/cpufeatureset.h
> @@ -290,6 +290,7 @@ XEN_CPUFEATURE(INTEL_PPIN,         12*32+ 0) /*   
> Protected Processor Inventory
>  
>  /* Intel-defined CPU features, CPUID level 0x00000007:1.ecx, word 14 */
>  /* Intel-defined CPU features, CPUID level 0x00000007:1.edx, word 15 */
> +XEN_CPUFEATURE(CET_SSS,            15*32+18) /*   CET Supervisor Shadow 
> Stacks safe to use */
>  
>  /* Intel-defined CPU features, CPUID level 0x00000007:2.edx, word 13 */
>  XEN_CPUFEATURE(INTEL_PSFD,         13*32+ 0) /*A  MSR_SPEC_CTRL.PSFD */
> -- 
> 2.11.0
> 
> 

-- 
Best Regards,
Marek Marczykowski-Górecki
Invisible Things Lab

Attachment: signature.asc
Description: PGP signature


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.