Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d90a7a0e authored by Jiri Kosina's avatar Jiri Kosina Committed by Thomas Gleixner
Browse files

x86/bugs, kvm: Introduce boot-time control of L1TF mitigations



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: default avatarJiri Kosina <jkosina@suse.cz>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: default avatarJiri Kosina <jkosina@suse.cz>
Reviewed-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Link: https://lkml.kernel.org/r/20180713142323.202758176@linutronix.de
parent fee0aede
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -476,6 +476,7 @@ What: /sys/devices/system/cpu/vulnerabilities
		/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
@@ -488,6 +489,9 @@ Description: Information about CPU vulnerabilities
		"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
+62 −6
Original line number Diff line number Diff line
@@ -1946,12 +1946,6 @@
			[KVM,ARM] Allow use of GICv4 for direct injection of
			LPIs.

	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)
@@ -1989,6 +1983,68 @@
			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]
+12 −0
Original line number Diff line number Diff line
@@ -982,4 +982,16 @@ bool xen_set_default_idle(void);
void stop_this_cpu(void *dummy);
void df_debug(struct pt_regs *regs, long error_code);
void microcode_check(void);

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 */
+44 −0
Original line number Diff line number Diff line
@@ -665,7 +665,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
@@ -677,6 +681,20 @@ static void __init l1tf_select_mitigation(void)
	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;
@@ -695,6 +713,32 @@ static void __init l1tf_select_mitigation(void)

	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
+43 −13
Original line number Diff line number Diff line
@@ -71,9 +71,6 @@ static const struct x86_cpu_id vmx_cpu_id[] = {
};
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);

@@ -215,15 +212,31 @@ static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf)
{
	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);
@@ -10571,19 +10584,36 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
	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 (!ple_gap)
		kvm->arch.pause_in_guest = true;

	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;
}