[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] VT-x: simplify/clarify vmx_load_pdptrs()



On Thu, Jun 18, 2020 at 08:38:27AM +0200, Jan Beulich wrote:
> * Guests outside of long mode can't have PCID enabled. Drop the
>   respective check to make more obvious that there's no security issue
>   (from potentially accessing past the mapped page's boundary).
> 
> * Only the low 32 bits of CR3 are relevant outside of long mode, even
>   if they remained unchanged after leaving that mode.
> 
> * Drop the unnecessary and badly typed local variable p.
> 
> * Don't open-code hvm_long_mode_active() (and extend this to the related
>   nested VT-x code).
> 
> * Constify guest_pdptes to clarify that we're only reading from the
>   page.
> 
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>

As it's no worse that what was there before, yet I have a question.

> ---
> This is intentionally not addressing any of the other shortcomings of
> the function, as was done by the previously posted
> https://lists.xenproject.org/archives/html/xen-devel/2018-07/msg01790.html.
> This will need to be the subject of a further change.
> 
> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -1312,17 +1312,16 @@ static void vmx_set_interrupt_shadow(str
>  
>  static void vmx_load_pdptrs(struct vcpu *v)
>  {
> -    unsigned long cr3 = v->arch.hvm.guest_cr[3];
> -    uint64_t *guest_pdptes;
> +    uint32_t cr3 = v->arch.hvm.guest_cr[3];
> +    const uint64_t *guest_pdptes;
>      struct page_info *page;
>      p2m_type_t p2mt;
> -    char *p;
>  
>      /* EPT needs to load PDPTRS into VMCS for PAE. */
> -    if ( !hvm_pae_enabled(v) || (v->arch.hvm.guest_efer & EFER_LMA) )
> +    if ( !hvm_pae_enabled(v) || hvm_long_mode_active(v) )
>          return;
>  
> -    if ( (cr3 & 0x1fUL) && !hvm_pcid_enabled(v) )
> +    if ( cr3 & 0x1f )
>          goto crash;

Intel SDM says bits 0 to 4 are ignored, not reserved, so I'm not sure
we need to crash the guest here. I have no reference how real hardware
behaves here, so maybe crashing is the right thing to do.

>  
>      page = get_page_from_gfn(v->domain, cr3 >> PAGE_SHIFT, &p2mt, 
> P2M_UNSHARE);
> @@ -1332,14 +1331,12 @@ static void vmx_load_pdptrs(struct vcpu
>           * queue, but this is the wrong place. We're holding at least
>           * the paging lock */
>          gdprintk(XENLOG_ERR,
> -                 "Bad cr3 on load pdptrs gfn %lx type %d\n",
> +                 "Bad cr3 on load pdptrs gfn %"PRIx32" type %d\n",
>                   cr3 >> PAGE_SHIFT, (int) p2mt);
>          goto crash;
>      }
>  
> -    p = __map_domain_page(page);
> -
> -    guest_pdptes = (uint64_t *)(p + (cr3 & ~PAGE_MASK));
> +    guest_pdptes = __map_domain_page(page) + (cr3 & ~PAGE_MASK);

Instead I think this could be:

guest_pdptes = __map_domain_page(page) + (cr3 & ~(PAGE_MASK | 0x1f));

Thanks, Roger.



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.