On Tue, Apr 11, 2023, Alexey Kardashevskiy wrote: > Currently SVM setup is done sequentially in > init_vmcb() -> sev_init_vmcb() -> sev_es_init_vmcb() > and tries keeping SVM/SEV/SEV-ES bits separated. One of the exceptions > is DR intercepts which is for SEV-ES before sev_es_init_vmcb() runs. > > Move the SEV-ES intercept setup to sev_es_init_vmcb(). From now on > set_dr_intercepts()/clr_dr_intercepts() handle SVM/SEV only. > > No functional change intended. > > Suggested-by: Sean Christopherson <seanjc@xxxxxxxxxx> > Signed-off-by: Alexey Kardashevskiy <aik@xxxxxxx> > Reviewed-by: Santosh Shukla <santosh.shukla@xxxxxxx> > Reviewed-by: Tom Lendacky <thomas.lendacky@xxxxxxx> > --- > Changes: > v5: > * updated the comments > * removed sev_es_guest() checks from set_dr_intercepts()/clr_dr_intercepts() > * removed remaining intercepts from clr_dr_intercepts() > --- > arch/x86/kvm/svm/sev.c | 11 ++++++ > arch/x86/kvm/svm/svm.c | 37 ++++++++------------ > 2 files changed, 25 insertions(+), 23 deletions(-) > > diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c > index b4365622222b..f0885250252d 100644 > --- a/arch/x86/kvm/svm/sev.c > +++ b/arch/x86/kvm/svm/sev.c > @@ -2946,6 +2946,7 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in) > > static void sev_es_init_vmcb(struct vcpu_svm *svm) > { > + struct vmcb *vmcb = svm->vmcb01.ptr; > struct kvm_vcpu *vcpu = &svm->vcpu; > > svm->vmcb->control.nested_ctl |= SVM_NESTED_CTL_SEV_ES_ENABLE; > @@ -2974,6 +2975,16 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm) > svm_set_intercept(svm, TRAP_CR4_WRITE); > svm_set_intercept(svm, TRAP_CR8_WRITE); > > + /* > + * DR7 access must remain intercepted for an SEV-ES guest to disallow > + * the guest kernel enable debugging as otherwise a VM writing to DR7 > + * from the #DB handler may trigger infinite loop of #DB's. This is wrong. The attack isn't writing DR7 in the #DB handler, it's setting up a #DB on memory that's needed to vector a #DB, e.g. the stack, so that the _CPU_ itself gets stuck in an infinite #DB loop[*]. The guest software handler putting itself into an infinite loop is a non-issue because it can be interrupted. [*] https://bugzilla.redhat.com/show_bug.cgi?id=1278496 > + */ > + vmcb->control.intercepts[INTERCEPT_DR] = 0; > + vmcb_set_intercept(&vmcb->control, INTERCEPT_DR7_READ); > + vmcb_set_intercept(&vmcb->control, INTERCEPT_DR7_WRITE); > + recalc_intercepts(svm);