All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] x86/speculation, KVM: only IBPB for switch_mm_always_ibpb on vCPU load
@ 2022-04-19  2:00 Jon Kohler
  2022-04-21 15:20 ` Sean Christopherson
  0 siblings, 1 reply; 3+ messages in thread
From: Jon Kohler @ 2022-04-19  2:00 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Paolo Bonzini, Sean Christopherson,
	Vitaly Kuznetsov, Wanpeng Li, Jim Mattson, Joerg Roedel,
	Jon Kohler, Josh Poimboeuf, Peter Zijlstra, Balbir Singh,
	Andrea Arcangeli, Kim Phillips, linux-kernel, kvm
  Cc: Kees Cook, Waiman Long

On vmx_vcpu_load_vmcs and svm_vcpu_load, respect user controlled
configuration for conditional IBPB and only attempt IBPB MSR when
switching between different guest vCPUs IFF switch_mm_always_ibpb,
which fixes a situation where the kernel will issue IBPB
unconditionally even when conditional IBPB is enabled.

If a user has spectre_v2_user mitigation enabled, in any
configuration, and the underlying processor supports X86_FEATURE_IBPB,
X86_FEATURE_USE_IBPB is set and any calls to
indirect_branch_prediction_barrier() will issue IBPB MSR.

Depending on the spectre_v2_user configuration, either
switch_mm_always_ibpb key or switch_mm_cond_ibpb key will be set.

Both switch_mm_always_ibpb and switch_mm_cond_ibpb are handled by
switch_mm() -> cond_mitigation(), which works well in cases where
switching vCPUs (i.e. switching tasks) also switches mm_struct;
however, this misses a paranoid case where user space may be running
multiple guests in a single process (i.e. single mm_struct).

This paranoid case is already covered by vmx_vcpu_load_vmcs and
svm_vcpu_load; however, this is done by calling
indirect_branch_prediction_barrier() and thus the kernel
unconditionally issues IBPB if X86_FEATURE_USE_IBPB is set.

Fix by using intermediary call to x86_virt_guest_switch_ibpb(), which
gates IBPB MSR IFF switch_mm_always_ibpb is true. This is useful for
security paranoid VMMs in either single process or multi-process VMM
configurations.

switch_mm_always_ibpb key is user controlled via spectre_v2_user and
will be true for the following configurations:
  spectre_v2_user=on
  spectre_v2_user=prctl,ibpb
  spectre_v2_user=seccomp,ibpb

Signed-off-by: Jon Kohler <jon@nutanix.com>
Cc: Sean Christopherson <seanjc@google.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Waiman Long <longman@redhat.com>
---
v1 -> v2:
 - Addressed comments on approach from Sean.

 arch/x86/include/asm/spec-ctrl.h | 15 +++++++++++++++
 arch/x86/kernel/cpu/bugs.c       |  6 +++++-
 arch/x86/kvm/svm/svm.c           |  2 +-
 arch/x86/kvm/vmx/vmx.c           |  2 +-
 4 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/spec-ctrl.h b/arch/x86/include/asm/spec-ctrl.h
index 5393babc0598..1ad140b17ad7 100644
--- a/arch/x86/include/asm/spec-ctrl.h
+++ b/arch/x86/include/asm/spec-ctrl.h
@@ -85,4 +85,19 @@ static inline void speculative_store_bypass_ht_init(void) { }
 extern void speculation_ctrl_update(unsigned long tif);
 extern void speculation_ctrl_update_current(void);

+/*
+ * Issue IBPB when switching guest vCPUs IFF if switch_mm_always_ibpb.
+ * Primarily useful for security paranoid (or naive) user space VMMs
+ * that may run multiple VMs within a single process.
+ * For multi-process VMMs, switching vCPUs, i.e. switching tasks,
+ * will also switch mm_structs and thus do IPBP via cond_mitigation();
+ * however, in the always_ibpb case, take a paranoid approach and issue
+ * IBPB on both switch_mm() and vCPU switch.
+ */
+static inline void x86_virt_guest_switch_ibpb(void)
+{
+	if (static_branch_unlikely(&switch_mm_always_ibpb))
+		indirect_branch_prediction_barrier();
+}
+
 #endif
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 6296e1ebed1d..6aafb0279cbc 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -68,8 +68,12 @@ u64 __ro_after_init x86_amd_ls_cfg_ssbd_mask;
 DEFINE_STATIC_KEY_FALSE(switch_to_cond_stibp);
 /* Control conditional IBPB in switch_mm() */
 DEFINE_STATIC_KEY_FALSE(switch_mm_cond_ibpb);
-/* Control unconditional IBPB in switch_mm() */
+/* Control unconditional IBPB in both switch_mm() and
+ * x86_virt_guest_switch_ibpb().
+ * See notes on x86_virt_guest_switch_ibpb() for KVM use case details.
+ */
 DEFINE_STATIC_KEY_FALSE(switch_mm_always_ibpb);
+EXPORT_SYMBOL_GPL(switch_mm_always_ibpb);

 /* Control MDS CPU buffer clear before returning to user space */
 DEFINE_STATIC_KEY_FALSE(mds_user_clear);
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index bd4c64b362d2..fc08c94df888 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1302,7 +1302,7 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)

 	if (sd->current_vmcb != svm->vmcb) {
 		sd->current_vmcb = svm->vmcb;
-		indirect_branch_prediction_barrier();
+		x86_virt_guest_switch_ibpb();
 	}
 	if (kvm_vcpu_apicv_active(vcpu))
 		__avic_vcpu_load(vcpu, cpu);
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 04d170c4b61e..a8eed9b8221b 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -1270,7 +1270,7 @@ void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu,
 		 * The L1 VMM can protect itself with retpolines, IBPB or IBRS.
 		 */
 		if (!buddy || WARN_ON_ONCE(buddy->vmcs != prev))
-			indirect_branch_prediction_barrier();
+			x86_virt_guest_switch_ibpb();
 	}

 	if (!already_loaded) {
--
2.30.1 (Apple Git-130)


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] x86/speculation, KVM: only IBPB for switch_mm_always_ibpb on vCPU load
  2022-04-19  2:00 [PATCH v2] x86/speculation, KVM: only IBPB for switch_mm_always_ibpb on vCPU load Jon Kohler
@ 2022-04-21 15:20 ` Sean Christopherson
  2022-04-21 16:09   ` Jon Kohler
  0 siblings, 1 reply; 3+ messages in thread
From: Sean Christopherson @ 2022-04-21 15:20 UTC (permalink / raw)
  To: Jon Kohler
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Paolo Bonzini, Vitaly Kuznetsov, Wanpeng Li,
	Jim Mattson, Joerg Roedel, Josh Poimboeuf, Peter Zijlstra,
	Balbir Singh, Andrea Arcangeli, Kim Phillips, linux-kernel, kvm,
	Kees Cook, Waiman Long

On Mon, Apr 18, 2022, Jon Kohler wrote:
> On vmx_vcpu_load_vmcs and svm_vcpu_load, respect user controlled
> configuration for conditional IBPB and only attempt IBPB MSR when
> switching between different guest vCPUs IFF switch_mm_always_ibpb,
> which fixes a situation where the kernel will issue IBPB
> unconditionally even when conditional IBPB is enabled.
> 
> If a user has spectre_v2_user mitigation enabled, in any
> configuration, and the underlying processor supports X86_FEATURE_IBPB,
> X86_FEATURE_USE_IBPB is set and any calls to
> indirect_branch_prediction_barrier() will issue IBPB MSR.
> 
> Depending on the spectre_v2_user configuration, either
> switch_mm_always_ibpb key or switch_mm_cond_ibpb key will be set.
> 
> Both switch_mm_always_ibpb and switch_mm_cond_ibpb are handled by
> switch_mm() -> cond_mitigation(), which works well in cases where
> switching vCPUs (i.e. switching tasks) also switches mm_struct;
> however, this misses a paranoid case where user space may be running
> multiple guests in a single process (i.e. single mm_struct).
> 
> This paranoid case is already covered by vmx_vcpu_load_vmcs and
> svm_vcpu_load; however, this is done by calling
> indirect_branch_prediction_barrier() and thus the kernel
> unconditionally issues IBPB if X86_FEATURE_USE_IBPB is set.

The changelog should call out that switch_mm_cond_ibpb is intentionally "ignored"
for the virt case, and explain why it's nonsensical to emit IBPB in that scenario.

> Fix by using intermediary call to x86_virt_guest_switch_ibpb(), which
> gates IBPB MSR IFF switch_mm_always_ibpb is true. This is useful for
> security paranoid VMMs in either single process or multi-process VMM
> configurations.

Multi-process VMM?  KVM doesn't allow "sharing" a VM across processes.  Userspace
can share guest memory across processes, but that's not relevant to an IBPB on
guest switch.  I suspect you're loosely referring to all of userspace as a single
VMM.  That's inaccurate, or at least unnecessarily confusing, from a kernel
perspective.  I am not aware of a VMM that runs as a monolithic "daemon" and forks
a new process for every VM.  And even in such a case, I would argue that most
people would refer to each process as a separate VMM.

If there's a blurb about the switch_mm_cond_ibpb case being nonsensical, there's
probably a good segue into stating the new behavior.

> switch_mm_always_ibpb key is user controlled via spectre_v2_user and
> will be true for the following configurations:
>   spectre_v2_user=on
>   spectre_v2_user=prctl,ibpb
>   spectre_v2_user=seccomp,ibpb
> 
> Signed-off-by: Jon Kohler <jon@nutanix.com>
> Cc: Sean Christopherson <seanjc@google.com>
> Cc: Andrea Arcangeli <aarcange@redhat.com>
> Cc: Kees Cook <keescook@chromium.org>
> Cc: Josh Poimboeuf <jpoimboe@redhat.com>
> Cc: Waiman Long <longman@redhat.com>
> ---
> v1 -> v2:
>  - Addressed comments on approach from Sean.
> 
>  arch/x86/include/asm/spec-ctrl.h | 15 +++++++++++++++
>  arch/x86/kernel/cpu/bugs.c       |  6 +++++-
>  arch/x86/kvm/svm/svm.c           |  2 +-
>  arch/x86/kvm/vmx/vmx.c           |  2 +-
>  4 files changed, 22 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/include/asm/spec-ctrl.h b/arch/x86/include/asm/spec-ctrl.h
> index 5393babc0598..1ad140b17ad7 100644
> --- a/arch/x86/include/asm/spec-ctrl.h
> +++ b/arch/x86/include/asm/spec-ctrl.h
> @@ -85,4 +85,19 @@ static inline void speculative_store_bypass_ht_init(void) { }
>  extern void speculation_ctrl_update(unsigned long tif);
>  extern void speculation_ctrl_update_current(void);
> 
> +/*
> + * Issue IBPB when switching guest vCPUs IFF if switch_mm_always_ibpb.

Extra "if" there.

> + * Primarily useful for security paranoid (or naive) user space VMMs
> + * that may run multiple VMs within a single process.
> + * For multi-process VMMs, switching vCPUs, i.e. switching tasks,

As above, "multi-process VMMs" is very confusing, they're really just separate VMMs.
Something like this?

 * For the more common case of running VMs in their own dedicated process,
 * switching vCPUs that belong to different VMs, i.e. switching tasks, will also
 * ...

> + * will also switch mm_structs and thus do IPBP via cond_mitigation();
> + * however, in the always_ibpb case, take a paranoid approach and issue
> + * IBPB on both switch_mm() and vCPU switch.
> + */
> +static inline void x86_virt_guest_switch_ibpb(void)
> +{
> +	if (static_branch_unlikely(&switch_mm_always_ibpb))
> +		indirect_branch_prediction_barrier();
> +}
> +
>  #endif
> diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
> index 6296e1ebed1d..6aafb0279cbc 100644

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] x86/speculation, KVM: only IBPB for switch_mm_always_ibpb on vCPU load
  2022-04-21 15:20 ` Sean Christopherson
@ 2022-04-21 16:09   ` Jon Kohler
  0 siblings, 0 replies; 3+ messages in thread
From: Jon Kohler @ 2022-04-21 16:09 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Jon Kohler, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, X86 ML, H. Peter Anvin, Paolo Bonzini,
	Vitaly Kuznetsov, Wanpeng Li, Jim Mattson, Joerg Roedel,
	Josh Poimboeuf, Peter Zijlstra, Balbir Singh, Andrea Arcangeli,
	Kim Phillips, LKML, kvm @ vger . kernel . org, Kees Cook,
	Waiman Long



> On Apr 21, 2022, at 11:20 AM, Sean Christopherson <seanjc@google.com> wrote:
> 
> On Mon, Apr 18, 2022, Jon Kohler wrote:
>> On vmx_vcpu_load_vmcs and svm_vcpu_load, respect user controlled
>> configuration for conditional IBPB and only attempt IBPB MSR when
>> switching between different guest vCPUs IFF switch_mm_always_ibpb,
>> which fixes a situation where the kernel will issue IBPB
>> unconditionally even when conditional IBPB is enabled.
>> 
>> If a user has spectre_v2_user mitigation enabled, in any
>> configuration, and the underlying processor supports X86_FEATURE_IBPB,
>> X86_FEATURE_USE_IBPB is set and any calls to
>> indirect_branch_prediction_barrier() will issue IBPB MSR.
>> 
>> Depending on the spectre_v2_user configuration, either
>> switch_mm_always_ibpb key or switch_mm_cond_ibpb key will be set.
>> 
>> Both switch_mm_always_ibpb and switch_mm_cond_ibpb are handled by
>> switch_mm() -> cond_mitigation(), which works well in cases where
>> switching vCPUs (i.e. switching tasks) also switches mm_struct;
>> however, this misses a paranoid case where user space may be running
>> multiple guests in a single process (i.e. single mm_struct).
>> 
>> This paranoid case is already covered by vmx_vcpu_load_vmcs and
>> svm_vcpu_load; however, this is done by calling
>> indirect_branch_prediction_barrier() and thus the kernel
>> unconditionally issues IBPB if X86_FEATURE_USE_IBPB is set.
> 
> The changelog should call out that switch_mm_cond_ibpb is intentionally "ignored"
> for the virt case, and explain why it's nonsensical to emit IBPB in that scenario.

Ok will do, thanks

> 
>> Fix by using intermediary call to x86_virt_guest_switch_ibpb(), which
>> gates IBPB MSR IFF switch_mm_always_ibpb is true. This is useful for
>> security paranoid VMMs in either single process or multi-process VMM
>> configurations.
> 
> Multi-process VMM?  KVM doesn't allow "sharing" a VM across processes.  Userspace
> can share guest memory across processes, but that's not relevant to an IBPB on
> guest switch.  I suspect you're loosely referring to all of userspace as a single
> VMM.  That's inaccurate, or at least unnecessarily confusing, from a kernel
> perspective.  I am not aware of a VMM that runs as a monolithic "daemon" and forks
> a new process for every VM.  And even in such a case, I would argue that most
> people would refer to each process as a separate VMM.
> 
> If there's a blurb about the switch_mm_cond_ibpb case being nonsensical, there's
> probably a good segue into stating the new behavior.

Yea, thats what I was getting at but failed to wordsmith it nicely. I’ll sharpen it up
and integrate your feedback into a v3

> 
>> switch_mm_always_ibpb key is user controlled via spectre_v2_user and
>> will be true for the following configurations:
>>  spectre_v2_user=on
>>  spectre_v2_user=prctl,ibpb
>>  spectre_v2_user=seccomp,ibpb
>> 
>> Signed-off-by: Jon Kohler <jon@nutanix.com>
>> Cc: Sean Christopherson <seanjc@google.com>
>> Cc: Andrea Arcangeli <aarcange@redhat.com>
>> Cc: Kees Cook <keescook@chromium.org>
>> Cc: Josh Poimboeuf <jpoimboe@redhat.com>
>> Cc: Waiman Long <longman@redhat.com>
>> ---
>> v1 -> v2:
>> - Addressed comments on approach from Sean.
>> 
>> arch/x86/include/asm/spec-ctrl.h | 15 +++++++++++++++
>> arch/x86/kernel/cpu/bugs.c       |  6 +++++-
>> arch/x86/kvm/svm/svm.c           |  2 +-
>> arch/x86/kvm/vmx/vmx.c           |  2 +-
>> 4 files changed, 22 insertions(+), 3 deletions(-)
>> 
>> diff --git a/arch/x86/include/asm/spec-ctrl.h b/arch/x86/include/asm/spec-ctrl.h
>> index 5393babc0598..1ad140b17ad7 100644
>> --- a/arch/x86/include/asm/spec-ctrl.h
>> +++ b/arch/x86/include/asm/spec-ctrl.h
>> @@ -85,4 +85,19 @@ static inline void speculative_store_bypass_ht_init(void) { }
>> extern void speculation_ctrl_update(unsigned long tif);
>> extern void speculation_ctrl_update_current(void);
>> 
>> +/*
>> + * Issue IBPB when switching guest vCPUs IFF if switch_mm_always_ibpb.
> 
> Extra "if" there.
> 
>> + * Primarily useful for security paranoid (or naive) user space VMMs
>> + * that may run multiple VMs within a single process.
>> + * For multi-process VMMs, switching vCPUs, i.e. switching tasks,
> 
> As above, "multi-process VMMs" is very confusing, they're really just separate VMMs.
> Something like this?
> 
> * For the more common case of running VMs in their own dedicated process,
> * switching vCPUs that belong to different VMs, i.e. switching tasks, will also
> * ...
> 
>> + * will also switch mm_structs and thus do IPBP via cond_mitigation();
>> + * however, in the always_ibpb case, take a paranoid approach and issue
>> + * IBPB on both switch_mm() and vCPU switch.
>> + */
>> +static inline void x86_virt_guest_switch_ibpb(void)
>> +{
>> +	if (static_branch_unlikely(&switch_mm_always_ibpb))
>> +		indirect_branch_prediction_barrier();
>> +}
>> +
>> #endif
>> diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
>> index 6296e1ebed1d..6aafb0279cbc 100644


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-04-21 16:26 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-19  2:00 [PATCH v2] x86/speculation, KVM: only IBPB for switch_mm_always_ibpb on vCPU load Jon Kohler
2022-04-21 15:20 ` Sean Christopherson
2022-04-21 16:09   ` Jon Kohler

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.