lkml.org 
[lkml]   [2018]   [Aug]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 078/107] x86/bugs, kvm: Introduce boot-time control of L1TF mitigations
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Jiri Kosina <jkosina@suse.cz>

    commit d90a7a0ec83fb86622cd7dae23255d3c50a99ec8 upstream

    Introduce the 'l1tf=' kernel command line option to allow for boot-time
    switching of mitigation that is used on processors affected by L1TF.

    The possible values are:

    full
    Provides all available mitigations for the L1TF vulnerability. Disables
    SMT and enables all mitigations in the hypervisors. SMT control via
    /sys/devices/system/cpu/smt/control is still possible after boot.
    Hypervisors will issue a warning when the first VM is started in
    a potentially insecure configuration, i.e. SMT enabled or L1D flush
    disabled.

    full,force
    Same as 'full', but disables SMT control. Implies the 'nosmt=force'
    command line option. sysfs control of SMT and the hypervisor flush
    control is disabled.

    flush
    Leaves SMT enabled and enables the conditional hypervisor mitigation.
    Hypervisors will issue a warning when the first VM is started in a
    potentially insecure configuration, i.e. SMT enabled or L1D flush
    disabled.

    flush,nosmt
    Disables SMT and enables the conditional hypervisor mitigation. SMT
    control via /sys/devices/system/cpu/smt/control is still possible
    after boot. If SMT is reenabled or flushing disabled at runtime
    hypervisors will issue a warning.

    flush,nowarn
    Same as 'flush', but hypervisors will not warn when
    a VM is started in a potentially insecure configuration.

    off
    Disables hypervisor mitigations and doesn't emit any warnings.

    Default is 'flush'.

    Let KVM adhere to these semantics, which means:

    - 'lt1f=full,force' : Performe L1D flushes. No runtime control
    possible.

    - 'l1tf=full'
    - 'l1tf-flush'
    - 'l1tf=flush,nosmt' : Perform L1D flushes and warn on VM start if
    SMT has been runtime enabled or L1D flushing
    has been run-time enabled

    - 'l1tf=flush,nowarn' : Perform L1D flushes and no warnings are emitted.

    - 'l1tf=off' : L1D flushes are not performed and no warnings
    are emitted.

    KVM can always override the L1D flushing behavior using its 'vmentry_l1d_flush'
    module parameter except when lt1f=full,force is set.

    This makes KVM's private 'nosmt' option redundant, and as it is a bit
    non-systematic anyway (this is something to control globally, not on
    hypervisor level), remove that option.

    Add the missing Documentation entry for the l1tf vulnerability sysfs file
    while at it.

    Signed-off-by: Jiri Kosina <jkosina@suse.cz>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Tested-by: Jiri Kosina <jkosina@suse.cz>
    Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
    Link: https://lkml.kernel.org/r/20180713142323.202758176@linutronix.de
    Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    Documentation/ABI/testing/sysfs-devices-system-cpu | 4 +
    Documentation/kernel-parameters.txt | 68 +++++++++++++++++++--
    arch/x86/include/asm/processor.h | 12 +++
    arch/x86/kernel/cpu/bugs.c | 44 +++++++++++++
    arch/x86/kvm/vmx.c | 56 +++++++++++++----
    5 files changed, 165 insertions(+), 19 deletions(-)

    --- a/Documentation/ABI/testing/sysfs-devices-system-cpu
    +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
    @@ -356,6 +356,7 @@ What: /sys/devices/system/cpu/vulnerabi
    /sys/devices/system/cpu/vulnerabilities/spectre_v1
    /sys/devices/system/cpu/vulnerabilities/spectre_v2
    /sys/devices/system/cpu/vulnerabilities/spec_store_bypass
    + /sys/devices/system/cpu/vulnerabilities/l1tf
    Date: January 2018
    Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
    Description: Information about CPU vulnerabilities
    @@ -368,6 +369,9 @@ Description: Information about CPU vulne
    "Vulnerable" CPU is affected and no mitigation in effect
    "Mitigation: $M" CPU is affected and mitigation $M is in effect

    + Details about the l1tf file can be found in
    + Documentation/admin-guide/l1tf.rst
    +
    What: /sys/devices/system/cpu/smt
    /sys/devices/system/cpu/smt/active
    /sys/devices/system/cpu/smt/control
    --- a/Documentation/kernel-parameters.txt
    +++ b/Documentation/kernel-parameters.txt
    @@ -1989,12 +1989,6 @@ bytes respectively. Such letter suffixes
    for all guests.
    Default is 1 (enabled) if in 64-bit or 32-bit PAE mode.

    - kvm-intel.nosmt=[KVM,Intel] If the L1TF CPU bug is present (CVE-2018-3620)
    - and the system has SMT (aka Hyper-Threading) enabled then
    - don't allow guests to be created.
    -
    - Default is 0 (allow guests to be created).
    -
    kvm-intel.ept= [KVM,Intel] Disable extended page tables
    (virtualized MMU) support on capable Intel chips.
    Default is 1 (enabled)
    @@ -2032,6 +2026,68 @@ bytes respectively. Such letter suffixes
    feature (tagged TLBs) on capable Intel chips.
    Default is 1 (enabled)

    + l1tf= [X86] Control mitigation of the L1TF vulnerability on
    + affected CPUs
    +
    + The kernel PTE inversion protection is unconditionally
    + enabled and cannot be disabled.
    +
    + full
    + Provides all available mitigations for the
    + L1TF vulnerability. Disables SMT and
    + enables all mitigations in the
    + hypervisors, i.e. unconditional L1D flush.
    +
    + SMT control and L1D flush control via the
    + sysfs interface is still possible after
    + boot. Hypervisors will issue a warning
    + when the first VM is started in a
    + potentially insecure configuration,
    + i.e. SMT enabled or L1D flush disabled.
    +
    + full,force
    + Same as 'full', but disables SMT and L1D
    + flush runtime control. Implies the
    + 'nosmt=force' command line option.
    + (i.e. sysfs control of SMT is disabled.)
    +
    + flush
    + Leaves SMT enabled and enables the default
    + hypervisor mitigation, i.e. conditional
    + L1D flush.
    +
    + SMT control and L1D flush control via the
    + sysfs interface is still possible after
    + boot. Hypervisors will issue a warning
    + when the first VM is started in a
    + potentially insecure configuration,
    + i.e. SMT enabled or L1D flush disabled.
    +
    + flush,nosmt
    +
    + Disables SMT and enables the default
    + hypervisor mitigation.
    +
    + SMT control and L1D flush control via the
    + sysfs interface is still possible after
    + boot. Hypervisors will issue a warning
    + when the first VM is started in a
    + potentially insecure configuration,
    + i.e. SMT enabled or L1D flush disabled.
    +
    + flush,nowarn
    + Same as 'flush', but hypervisors will not
    + warn when a VM is started in a potentially
    + insecure configuration.
    +
    + off
    + Disables hypervisor mitigations and doesn't
    + emit any warnings.
    +
    + Default is 'flush'.
    +
    + For details see: Documentation/admin-guide/l1tf.rst
    +
    l2cr= [PPC]

    l3cr= [PPC]
    --- a/arch/x86/include/asm/processor.h
    +++ b/arch/x86/include/asm/processor.h
    @@ -860,4 +860,16 @@ bool xen_set_default_idle(void);

    void stop_this_cpu(void *dummy);
    void df_debug(struct pt_regs *regs, long error_code);
    +
    +enum l1tf_mitigations {
    + L1TF_MITIGATION_OFF,
    + L1TF_MITIGATION_FLUSH_NOWARN,
    + L1TF_MITIGATION_FLUSH,
    + L1TF_MITIGATION_FLUSH_NOSMT,
    + L1TF_MITIGATION_FULL,
    + L1TF_MITIGATION_FULL_FORCE
    +};
    +
    +extern enum l1tf_mitigations l1tf_mitigation;
    +
    #endif /* _ASM_X86_PROCESSOR_H */
    --- a/arch/x86/kernel/cpu/bugs.c
    +++ b/arch/x86/kernel/cpu/bugs.c
    @@ -643,7 +643,11 @@ void x86_spec_ctrl_setup_ap(void)
    #undef pr_fmt
    #define pr_fmt(fmt) "L1TF: " fmt

    +/* Default mitigation for L1TF-affected CPUs */
    +enum l1tf_mitigations l1tf_mitigation __ro_after_init = L1TF_MITIGATION_FLUSH;
    #if IS_ENABLED(CONFIG_KVM_INTEL)
    +EXPORT_SYMBOL_GPL(l1tf_mitigation);
    +
    enum vmx_l1d_flush_state l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO;
    EXPORT_SYMBOL_GPL(l1tf_vmx_mitigation);
    #endif
    @@ -655,6 +659,20 @@ static void __init l1tf_select_mitigatio
    if (!boot_cpu_has_bug(X86_BUG_L1TF))
    return;

    + switch (l1tf_mitigation) {
    + case L1TF_MITIGATION_OFF:
    + case L1TF_MITIGATION_FLUSH_NOWARN:
    + case L1TF_MITIGATION_FLUSH:
    + break;
    + case L1TF_MITIGATION_FLUSH_NOSMT:
    + case L1TF_MITIGATION_FULL:
    + cpu_smt_disable(false);
    + break;
    + case L1TF_MITIGATION_FULL_FORCE:
    + cpu_smt_disable(true);
    + break;
    + }
    +
    #if CONFIG_PGTABLE_LEVELS == 2
    pr_warn("Kernel not compiled for PAE. No mitigation for L1TF\n");
    return;
    @@ -673,6 +691,32 @@ static void __init l1tf_select_mitigatio

    setup_force_cpu_cap(X86_FEATURE_L1TF_PTEINV);
    }
    +
    +static int __init l1tf_cmdline(char *str)
    +{
    + if (!boot_cpu_has_bug(X86_BUG_L1TF))
    + return 0;
    +
    + if (!str)
    + return -EINVAL;
    +
    + if (!strcmp(str, "off"))
    + l1tf_mitigation = L1TF_MITIGATION_OFF;
    + else if (!strcmp(str, "flush,nowarn"))
    + l1tf_mitigation = L1TF_MITIGATION_FLUSH_NOWARN;
    + else if (!strcmp(str, "flush"))
    + l1tf_mitigation = L1TF_MITIGATION_FLUSH;
    + else if (!strcmp(str, "flush,nosmt"))
    + l1tf_mitigation = L1TF_MITIGATION_FLUSH_NOSMT;
    + else if (!strcmp(str, "full"))
    + l1tf_mitigation = L1TF_MITIGATION_FULL;
    + else if (!strcmp(str, "full,force"))
    + l1tf_mitigation = L1TF_MITIGATION_FULL_FORCE;
    +
    + return 0;
    +}
    +early_param("l1tf", l1tf_cmdline);
    +
    #undef pr_fmt

    #ifdef CONFIG_SYSFS
    --- a/arch/x86/kvm/vmx.c
    +++ b/arch/x86/kvm/vmx.c
    @@ -69,9 +69,6 @@ static const struct x86_cpu_id vmx_cpu_i
    };
    MODULE_DEVICE_TABLE(x86cpu, vmx_cpu_id);

    -static bool __read_mostly nosmt;
    -module_param(nosmt, bool, S_IRUGO);
    -
    static bool __read_mostly enable_vpid = 1;
    module_param_named(vpid, enable_vpid, bool, 0444);

    @@ -216,15 +213,31 @@ static int vmx_setup_l1d_flush(enum vmx_
    {
    struct page *page;

    - /* If set to 'auto' select 'cond' */
    - if (l1tf == VMENTER_L1D_FLUSH_AUTO)
    - l1tf = VMENTER_L1D_FLUSH_COND;
    -
    if (!enable_ept) {
    l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_EPT_DISABLED;
    return 0;
    }

    + /* If set to auto use the default l1tf mitigation method */
    + if (l1tf == VMENTER_L1D_FLUSH_AUTO) {
    + switch (l1tf_mitigation) {
    + case L1TF_MITIGATION_OFF:
    + l1tf = VMENTER_L1D_FLUSH_NEVER;
    + break;
    + case L1TF_MITIGATION_FLUSH_NOWARN:
    + case L1TF_MITIGATION_FLUSH:
    + case L1TF_MITIGATION_FLUSH_NOSMT:
    + l1tf = VMENTER_L1D_FLUSH_COND;
    + break;
    + case L1TF_MITIGATION_FULL:
    + case L1TF_MITIGATION_FULL_FORCE:
    + l1tf = VMENTER_L1D_FLUSH_ALWAYS;
    + break;
    + }
    + } else if (l1tf_mitigation == L1TF_MITIGATION_FULL_FORCE) {
    + l1tf = VMENTER_L1D_FLUSH_ALWAYS;
    + }
    +
    if (l1tf != VMENTER_L1D_FLUSH_NEVER && !vmx_l1d_flush_pages &&
    !boot_cpu_has(X86_FEATURE_FLUSH_L1D)) {
    page = alloc_pages(GFP_KERNEL, L1D_CACHE_ORDER);
    @@ -9500,16 +9513,33 @@ free_vcpu:
    return ERR_PTR(err);
    }

    -#define L1TF_MSG "SMT enabled with L1TF CPU bug present. Refer to CVE-2018-3620 for details.\n"
    +#define L1TF_MSG_SMT "L1TF CPU bug present and SMT on, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html for details.\n"
    +#define L1TF_MSG_L1D "L1TF CPU bug present and virtualization mitigation disabled, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html for details.\n"

    static int vmx_vm_init(struct kvm *kvm)
    {
    - if (boot_cpu_has(X86_BUG_L1TF) && cpu_smt_control == CPU_SMT_ENABLED) {
    - if (nosmt) {
    - pr_err(L1TF_MSG);
    - return -EOPNOTSUPP;
    + if (boot_cpu_has(X86_BUG_L1TF) && enable_ept) {
    + switch (l1tf_mitigation) {
    + case L1TF_MITIGATION_OFF:
    + case L1TF_MITIGATION_FLUSH_NOWARN:
    + /* 'I explicitly don't care' is set */
    + break;
    + case L1TF_MITIGATION_FLUSH:
    + case L1TF_MITIGATION_FLUSH_NOSMT:
    + case L1TF_MITIGATION_FULL:
    + /*
    + * Warn upon starting the first VM in a potentially
    + * insecure environment.
    + */
    + if (cpu_smt_control == CPU_SMT_ENABLED)
    + pr_warn_once(L1TF_MSG_SMT);
    + if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER)
    + pr_warn_once(L1TF_MSG_L1D);
    + break;
    + case L1TF_MITIGATION_FULL_FORCE:
    + /* Flush is enforced */
    + break;
    }
    - pr_warn(L1TF_MSG);
    }
    return 0;
    }

    \
     
     \ /
      Last update: 2018-08-14 19:53    [W:2.660 / U:0.444 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site