public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Sean Christopherson <seanjc@google.com>
To: mlevitsk@redhat.com
Cc: kvm@vger.kernel.org, Ingo Molnar <mingo@redhat.com>,
	x86@kernel.org,  Paolo Bonzini <pbonzini@redhat.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	 Dave Hansen <dave.hansen@linux.intel.com>,
	Borislav Petkov <bp@alien8.de>,
	linux-kernel@vger.kernel.org,  "H. Peter Anvin" <hpa@zytor.com>,
	Chao Gao <chao.gao@intel.com>
Subject: Re: [PATCH v3 1/4] KVM: x86: relax canonical check for some x86 architectural msrs
Date: Fri, 23 Aug 2024 06:59:39 -0700	[thread overview]
Message-ID: <ZsiVy5Z3q-7NmNab@google.com> (raw)
In-Reply-To: <8a88f4e6208803c52eba946313804f682dadc5ee.camel@redhat.com>

On Fri, Aug 23, 2024, mlevitsk@redhat.com wrote:
> У ср, 2024-08-21 у 09:04 -0700, Sean Christopherson пише:
> > > static inline bool is_noncanonical_address(u64 la, struct kvm_vcpu *vcpu,
> > >                                            unsigned int flags)
> > > {
> > >         if (flags & (X86EMUL_F_INVLPG | X86EMUL_F_MSR | X86EMUL_F_DT_LOAD))
> > >                 return !__is_canonical_address(la, max_host_virt_addr_bits());
> > >         else
> > >                 return !__is_canonical_address(la, vcpu_virt_addr_bits(vcpu));
> > > }
> 
> This can work in principle, although are you OK with using these emulator flags
> outside of the emulator code?

Yep, they're already used in VMX's vmx_get_untagged_addr().  

> I am asking because the is_noncanonical_address is used in various places across KVM.

...

> > > We wouldn't want wrapper for everything, e.g. to minimize the risk of creating a
> > > de factor implicit default, but I think those three, and maybe a code/fetch
> > > variant, will cover all but a few users.
> > > 
> > > > > About fixing the emulator this is what see:
> > > > > 
> > > > >         emul_is_noncanonical_address
> > > > >                 __load_segment_descriptor
> > > > >                         load_segment_descriptor
> > > > >                                 em_lldt
> > > > >                                 em_ltr
> > > > > 
> > > > >                 em_lgdt_lidt
> > > > > 
> > > > > 
> > > > > 
> > > > > While em_lgdt_lidt should be easy to fix because it calls
> > > > > emul_is_noncanonical_address directly,
> > > 
> > > Those don't need to be fixed, they are validating the memory operand, not the
> > > base of the descriptor, i.e. aren't exempt from CR4.LA57.
> 
> Are you sure?

Nope.  Re-reading what I wrote, I have no idea what code past me was looking at.

I even contradicted myself later on:

  So the explicit emul_is_noncanonical_address() check in __load_segment_descriptor()
  needs to be tagged X86EMUL_F_BASE, but otherwise it all should Just Work (knock wood).

so yeah, ignore this.

> em_lgdt_lidt reads its memory operands (and checks that it is canonical through
> linearize) with read_descriptor and that is fine because this is memory fetch, 
> and then it checks that the base address within the operand is canonical.
> 
> This check needs to be updated, as it is possible to load non canonical GDT and IDT
> base via lgdt/lidt (I tested this).
> 
> For em_lldt, em_ltr, the check on the system segment descriptor base is
> in __load_segment_descriptor:
> 
> ...
>  ret = linear_read_system(ctxt, desc_addr+8, &base3, sizeof(base3));
>  if (ret != X86EMUL_CONTINUE)
>  return ret;
>  if (emul_is_noncanonical_address(get_desc_base(&seg_desc) |
>  ((u64)base3 << 32), ctxt))
>  return emulate_gp(ctxt, err_code);
> 
> ...
> 
> 
> 64 bases are possible only for system segments, which are
> TSS, LDT, and call gates/IDT descriptors.
> 
> 
> We don't emulate IDT fetches in protected mode, and as I found out the hard way after
> I wrote a unit test to do a call through a call gate, the emulator doesn't
> support call gates either)
> 
> Thus I can safely patch __load_segment_descriptor.

Agreed.

And thinking more about how this is likely implemented in ucode, this is probably
working as intended.  The the SDM gives CPUs a _lot_ of leeway:

  In 64-bit mode, an address is considered to be in canonical form if address
  bits 63 through to the most-significant implemented bit by the microarchitecture
  are set to either all ones or all zeros.

as does the APM:

  Long mode defines 64 bits of virtual address, but implementations of the AMD64
  architecture may support fewer bits of virtual address. Although implementations
  might not use all 64 bits of the virtual address, they check bits 63 through the
  most-significant implemented bit to see if those bits are all zeros or all ones.
  An address that complies with this property is said to be in canonical address
  form. If a virtual-memory reference is not in canonical form, the implementation
  causes a general-protection exception or stack fault.

I suspect that CR4.LA_57 is only consulted when the CPU is actually consuming the
address, i.e. is (or is about to, e.g. for code fetches) generating a memory
access.

Heh, and for MPX, the SDM kinda sorta confirms that LA57 is ignored, though I
doubt the author of this section intended their words to be taken this way :-)

  WRMSR to BNDCFGS will #GP if any of the reserved bits of BNDCFGS is not zero or
  if the base address of the bound directory is not canonical. XRSTOR of BNDCFGU
  ignores the reserved bits and does not fault if any is non-zero; similarly, it
  ignores the upper bits of the base address of the bound directory and sign-extends
  the highest implemented bit of the linear address to guarantee the canonicality
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  of this address.

> > > There _is_ an indirect canonical check on the _descriptor_ (the actual descriptor
> > > pointed at by the selector, not the memory operand).  The SDM is calls this case
> > > out in the LFS/LDS docs:
> > > 
> > >   If the FS, or GS register is being loaded with a non-NULL segment selector and
> > >   any of the following is true: the segment selector index is not within descriptor
> > >   table limits, the memory address of the descriptor is non-canonical
> > >                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 
> I tested that both ltr and lldt do ignore CR4.LA57 by loading from a descriptor
> which had a non canonical value and CR4.LA57 clear.

  reply	other threads:[~2024-08-23 13:59 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-15 12:33 [PATCH v3 0/4] Relax canonical checks on some arch msrs Maxim Levitsky
2024-08-15 12:33 ` [PATCH v3 1/4] KVM: x86: relax canonical check for some x86 architectural msrs Maxim Levitsky
2024-08-16 21:49   ` Sean Christopherson
2024-08-16 22:02     ` Sean Christopherson
2024-08-20 12:13     ` mlevitsk
2024-08-21 12:04       ` mlevitsk
2024-08-21 16:04         ` Sean Christopherson
2024-08-23 11:14           ` mlevitsk
2024-08-23 13:59             ` Sean Christopherson [this message]
2025-09-12 20:28               ` Jim Mattson
2025-09-16 20:47                 ` Sean Christopherson
2024-08-15 12:33 ` [PATCH v3 2/4] KVM: x86: add X86_FEATURE_LA57 to governed_features Maxim Levitsky
2024-08-15 12:33 ` [PATCH v3 3/4] KVM: nVMX: relax canonical checks on some x86 registers in vmx host state Maxim Levitsky
2024-08-16 10:40   ` mlevitsk
2024-08-16 22:03     ` Sean Christopherson
2024-08-20 12:19       ` mlevitsk
2024-08-15 12:33 ` [PATCH v3 4/4] KVM: SVM: fix emulation of msr reads/writes of MSR_FS_BASE and MSR_GS_BASE Maxim Levitsky
2024-08-16 22:04   ` Sean Christopherson
2024-08-24  0:07     ` Sean Christopherson

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=ZsiVy5Z3q-7NmNab@google.com \
    --to=seanjc@google.com \
    --cc=bp@alien8.de \
    --cc=chao.gao@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=mlevitsk@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.org \
    /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