kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andy Lutomirski <luto@kernel.org>
To: Jon Kohler <jon@nutanix.com>
Cc: Babu Moger <babu.moger@amd.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	X86 ML <x86@kernel.org>, "H. Peter Anvin" <hpa@zytor.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Sean Christopherson <seanjc@google.com>,
	Vitaly Kuznetsov <vkuznets@redhat.com>,
	Wanpeng Li <wanpengli@tencent.com>,
	Jim Mattson <jmattson@google.com>, Joerg Roedel <joro@8bytes.org>,
	Dave Hansen <dave.hansen@intel.com>,
	Fenghua Yu <fenghua.yu@intel.com>,
	Yu-cheng Yu <yu-cheng.yu@intel.com>,
	Tony Luck <tony.luck@intel.com>, Uros Bizjak <ubizjak@gmail.com>,
	Petteri Aimonen <jpa@git.mail.kapsi.fi>,
	Kan Liang <kan.liang@linux.intel.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Mike Rapoport <rppt@kernel.org>,
	Benjamin Thiel <b.thiel@posteo.de>,
	Fan Yang <Fan_Yang@sjtu.edu.cn>, Juergen Gross <jgross@suse.com>,
	Dave Jiang <dave.jiang@intel.com>,
	"Peter Zijlstra (Intel)" <peterz@infradead.org>,
	Ricardo Neri <ricardo.neri-calderon@linux.intel.com>,
	Arvind Sankar <nivedita@alum.mit.edu>,
	LKML <linux-kernel@vger.kernel.org>,
	kvm list <kvm@vger.kernel.org>
Subject: Re: [PATCH] KVM: x86: add hint to skip hidden rdpkru under kvm_load_host_xsave_state
Date: Thu, 13 May 2021 22:11:36 -0700	[thread overview]
Message-ID: <CALCETrW0_vwpbVVpc+85MvoGqg3qJA+FV=9tmUiZz6an7dQrGg@mail.gmail.com> (raw)
In-Reply-To: <20210507164456.1033-1-jon@nutanix.com>

On Fri, May 7, 2021 at 9:45 AM Jon Kohler <jon@nutanix.com> wrote:
>
> kvm_load_host_xsave_state handles xsave on vm exit, part of which is
> managing memory protection key state. The latest arch.pkru is updated
> with a rdpkru, and if that doesn't match the base host_pkru (which
> about 70% of the time), we issue a __write_pkru.

This thread caused me to read the code, and I don't get how it's even
remotely correct.

First, kvm_load_guest_fpu() has this delight:

    /*
     * Guests with protected state can't have it set by the hypervisor,
     * so skip trying to set it.
     */
    if (vcpu->arch.guest_fpu)
        /* PKRU is separately restored in kvm_x86_ops.run. */
        __copy_kernel_to_fpregs(&vcpu->arch.guest_fpu->state,
                    ~XFEATURE_MASK_PKRU);

That's nice, but it fails to restore XINUSE[PKRU].  As far as I know,
that bit is live, and the only way to restore it to 0 is with
XRSTOR(S).

> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index cebdaa1e3cf5..cd95adbd140c 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -912,10 +912,10 @@ void kvm_load_guest_xsave_state(struct kvm_vcpu *vcpu)
>         }
>
>         if (static_cpu_has(X86_FEATURE_PKU) &&
> -           (kvm_read_cr4_bits(vcpu, X86_CR4_PKE) ||
> -            (vcpu->arch.xcr0 & XFEATURE_MASK_PKRU)) &&
> -           vcpu->arch.pkru != vcpu->arch.host_pkru)
> -               __write_pkru(vcpu->arch.pkru);
> +           vcpu->arch.pkru != vcpu->arch.host_pkru &&
> +           ((vcpu->arch.xcr0 & XFEATURE_MASK_PKRU) ||
> +            kvm_read_cr4_bits(vcpu, X86_CR4_PKE)))
> +               __write_pkru(vcpu->arch.pkru, false);

Please tell me I'm missing something (e.g. KVM very cleverly managing
the PKRU register using intercepts) that makes this reliably load the
guest value.  An innocent or malicious guest could easily make that
condition evaluate to false, thus allowing the host PKRU value to be
live in guest mode.  (Or is something fancy going on here?)

I don't even want to think about what happens if a perf NMI hits and
accesses host user memory while the guest PKRU is live (on VMX -- I
think this can't happen on SVM).

>  }
>  EXPORT_SYMBOL_GPL(kvm_load_guest_xsave_state);
>
> @@ -925,11 +925,11 @@ void kvm_load_host_xsave_state(struct kvm_vcpu *vcpu)
>                 return;
>
>         if (static_cpu_has(X86_FEATURE_PKU) &&
> -           (kvm_read_cr4_bits(vcpu, X86_CR4_PKE) ||
> -            (vcpu->arch.xcr0 & XFEATURE_MASK_PKRU))) {
> +           ((vcpu->arch.xcr0 & XFEATURE_MASK_PKRU) ||
> +            kvm_read_cr4_bits(vcpu, X86_CR4_PKE))) {
>                 vcpu->arch.pkru = rdpkru();
>                 if (vcpu->arch.pkru != vcpu->arch.host_pkru)
> -                       __write_pkru(vcpu->arch.host_pkru);
> +                       __write_pkru(vcpu->arch.host_pkru, true);
>         }

Suppose the guest writes to PKRU and then, without exiting, sets PKE =
0 and XCR0[PKRU] = 0.  (Or are the intercepts such that this can't
happen except on SEV where maybe SEV magic makes the problem go away?)

I admit I'm fairly mystified as to why KVM doesn't handle PKRU like
the rest of guest XSTATE.

  parent reply	other threads:[~2021-05-14  5:12 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-07 16:44 [PATCH] KVM: x86: add hint to skip hidden rdpkru under kvm_load_host_xsave_state Jon Kohler
2021-05-07 16:52 ` Paolo Bonzini
2021-05-07 16:58   ` Dave Hansen
2021-05-07 17:13     ` Jon Kohler
2021-05-14  5:11 ` Andy Lutomirski [this message]
2021-05-17  2:50   ` Jon Kohler
2021-05-17 16:35     ` Tom Lendacky
2021-05-17  7:46   ` Paolo Bonzini
2021-05-17 17:39     ` Sean Christopherson
2021-05-17 17:55       ` Dave Hansen
2021-05-17 18:02         ` Sean Christopherson
     [not found]       ` <4e6f7056-6b66-46b9-9eac-922ae1c7b526@www.fastmail.com>
2021-05-17 17:59         ` Dave Hansen
2021-05-17 18:04           ` Sean Christopherson
2021-05-17 18:15             ` Jim Mattson
2021-05-17 18:34               ` Sean Christopherson
2021-05-19 22:44     ` Dave Hansen
2021-05-19 23:15       ` Andy Lutomirski
2021-05-17 13:54   ` Dave Hansen
2021-05-17 16:43     ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CALCETrW0_vwpbVVpc+85MvoGqg3qJA+FV=9tmUiZz6an7dQrGg@mail.gmail.com' \
    --to=luto@kernel.org \
    --cc=Fan_Yang@sjtu.edu.cn \
    --cc=akpm@linux-foundation.org \
    --cc=b.thiel@posteo.de \
    --cc=babu.moger@amd.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@intel.com \
    --cc=dave.jiang@intel.com \
    --cc=fenghua.yu@intel.com \
    --cc=hpa@zytor.com \
    --cc=jgross@suse.com \
    --cc=jmattson@google.com \
    --cc=jon@nutanix.com \
    --cc=joro@8bytes.org \
    --cc=jpa@git.mail.kapsi.fi \
    --cc=kan.liang@linux.intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=nivedita@alum.mit.edu \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=ricardo.neri-calderon@linux.intel.com \
    --cc=rppt@kernel.org \
    --cc=seanjc@google.com \
    --cc=tglx@linutronix.de \
    --cc=tony.luck@intel.com \
    --cc=ubizjak@gmail.com \
    --cc=vkuznets@redhat.com \
    --cc=wanpengli@tencent.com \
    --cc=x86@kernel.org \
    --cc=yu-cheng.yu@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).