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

Re: [Xen-devel] [PATCH] XSA-60 security hole: cr0.cd handling



Jan Beulich wrote:
>>>> On 14.10.13 at 11:28, "Liu, Jinsong" <jinsong.liu@xxxxxxxxx> wrote:
>> Jan Beulich wrote:
>>>>>> On 11.10.13 at 20:25, "Liu, Jinsong" <jinsong.liu@xxxxxxxxx>
>>>>>> wrote: 
>>>> +void hvm_handle_cd_traditional(struct vcpu *v, unsigned long
>>>> value) +{ +    if ( (value & X86_CR0_CD) && !(value & X86_CR0_NW)
>>>> ) +    { +        /* Entering no fill cache mode. */
>>>> +        spin_lock(&v->domain->arch.hvm_domain.uc_lock);
>>>> +        v->arch.hvm_vcpu.cache_mode = NO_FILL_CACHE_MODE; +
>>>> +        if ( !v->domain->arch.hvm_domain.is_in_uc_mode ) +       
>>>> { +            /* Flush physical caches. */
>>>> +            on_each_cpu(local_flush_cache, NULL, 1);
>>>> +            hvm_set_uc_mode(v, 1);
>>> 
>>> So you continue to use the problematic function, and you also
>>> don't remove the problematic code from it's VMX backend - what
>>> am I missing here? If there was no room for getting here with
>>> !paging_mode_hap(), the problematic code should be removed
>>> from vmx_set_uc_mode(). And if we still can get here with
>>> !paging_mode_hap(), then what's the purpose of the patch?'
>>> 
>> 
>> The new solution w/ PAT depends on whether Intel processor support
>> 'load IA32_PAT' VM-entry control bit (which in very old Intel
>> processors it indeed didn't support it). 
>> 
>> Though I'm pretty sure Intel processors w/ EPT capability also
>> support 'load IA32_PAT' VM-entry control bit, Intel SDM didn't
>> explicitly guarantee it. Hence we still keep old function, though
>> I'm sure it will never be called, just for safety or logic
>> integration. 
> 
> If any such processor exists, the security issue would still be there
> with the patch as is. Hence either use of EPT needs to be
> suppressed in that case, or some other solution allowing the broken
> code to be deleted (or replaced) needs to be found.
> 

Well, I have to go back to Intel library:) a long search for Intel VT history: 
both 'load IA32_PAT' and 'EPT' features does not exist at Intel SDM Order 
Number: 253669-026US (Feb 2008), but co-exist as early as Intel SDM Order 
Number: 253669-027US (July 2008).

Per my understanding 'load IA32_PAT' co-exist/co-work with EPT:
1. shadow don't need 'load IA32_PAT' feature
2. EPT, from its earliest version, has 'iPAT' bit to control guest PAT and host 
EPT memory type combining -- without 'load IA32_PAT' how can guest PAT memory 
type take effect?

So we have 2 choices for 'load IA32_PAT':
1. aggressive choice: remove vmx_set_uc_mode logic
    if ( shadow )
        drop shadows and new ones would be created on demand;
    else  /* Intel EPT */
        IA32_PAT solution
2. conservative choice: as what the patch did, use if (!cpu_has_vmx_pat) to 
keep logic integration -- it didn't make thing worse.

Thoughts?


>>>> +    /*
>>>> +     * When cr0.cd setting
>>>> +     * 1. For guest w/o VT-d, and for guest with VT-d but snooped,
>>>> Xen need not +     * do anything, since hardware snoop mechanism
>>>> has ensured cache coherency; +     * 2. For guest with VT-d but
>>>> non-snooped, cache coherency cannot be +     * guaranteed by h/w so
>>>> need emulate UC memory type to guest. +     */ +    if ( ((value ^
>>>> old_value) & X86_CR0_CD) && +           has_arch_mmios(v->domain)
>>>> && 
>>> 
>>> has_arch_mmios() has been wrong (too weak) here originally, so I
>>> strongly suggest replacing it here as you modify this logic anyway:
>>> This check must consider not only non-empty iomem_caps, but also
>>> non-empty ioport_caps.
>> 
>> OK, or, how about has_arch_pdevs()?
> 
> Yes, precisely that one.
> 
>>>> +static void vmx_handle_cd(struct vcpu *v, unsigned long value) +{
>>>> +    if ( !paging_mode_hap(v->domain) ||
>>>> +         unlikely(!cpu_has_vmx_pat) )    /* Too old for EPT, just
>>>> for safe */ +    { +        /*
>>>> +         * For shadow, 'load IA32_PAT' VM-entry control is 0, so
>>>> it cannot +         * set guest memory type as UC via IA32_PAT. Xen
>>>> drop all shadows +         * so that any new ones would be created
>>>> on demand. +         */ +        hvm_handle_cd_traditional(v,
>>>> value); +    } +    else
>>>> +    {
>>>> +        u64 *pat = &v->arch.hvm_vcpu.pat_cr;
>>>> +
>>>> +        if ( value & X86_CR0_CD )
>>>> +        {
>>>> +            /*
>>>> +             * For EPT, set guest IA32_PAT fields as UC so that
>>>> guest +             * memory type are all UC.
>>>> +             */
>>>> +            u64 uc_pat =
>>>> +                ((uint64_t)PAT_TYPE_UNCACHABLE)       |       /*
>>>> PAT0 */ +                ((uint64_t)PAT_TYPE_UNCACHABLE << 8)  |
>>>> /* PAT1 */ +                ((uint64_t)PAT_TYPE_UNCACHABLE << 16) |
>>>> /* PAT2 */ +                ((uint64_t)PAT_TYPE_UNCACHABLE << 24) |
>>>> /* PAT3 */ +                ((uint64_t)PAT_TYPE_UNCACHABLE << 32) |
>>>> /* PAT4 */ +                ((uint64_t)PAT_TYPE_UNCACHABLE << 40) |
>>>> /* PAT5 */ +                ((uint64_t)PAT_TYPE_UNCACHABLE << 48) |
>>>> /* PAT6 */ +                ((uint64_t)PAT_TYPE_UNCACHABLE << 56);
>>>> /* PAT7 */ + +            vmx_get_guest_pat(v, pat);
>>>> +            vmx_set_guest_pat(v, uc_pat);
>>>> +
>>>> +            wbinvd();
>>>> +            v->arch.hvm_vcpu.cache_mode = NO_FILL_CACHE_MODE; + }
>>>> +        else +        {
>>>> +            vmx_set_guest_pat(v, *pat);
>>>> +            v->arch.hvm_vcpu.cache_mode = NORMAL_CACHE_MODE;
>>>> +        }
>>> 
>>> All this is done only on the current vCPU, and I don't see any
>>> mechanism by which the other vCPU-s of the domain would
>>> similarly get their PAT overridden (yet the whole domain gets
>>> transitioned to UC mode). This minimally needs more cleanup (i.e.
>>> it should be uniformly just the local vCPU or uniformly the whole
>>> domain that is affected here).
>>> 
>>> And if going the local-vCPU-only route you need to make clear
>>> (via code comment I would think) that this is safe to do when
>>> two of the guest's vCPU-s with different CR0.CD settings run
>>> on two hyperthreads on the same core.
>>> 
>> 
>> For Intel processors CR0.CD operation is per vCPU, not per domain.
>> It's OK running w/ different CR0.CD and different cacheability for
>> different CPUs (For AMD CR0.CD seems should be identical but AMD has
>> not XSA-60 issue we are talking about). 
>> 
>> IA32_PAT is separate MSR per each logic processor, so it's safe
>> running two vCPUs on two hyperthreads on same core. I will add code
>> comments. 
> 
> So are you saying that no conflicts will arise in TLBs getting
> populated with different cachabilty information from the two
> hyperthreads?
> 

No, I meant it's irrelated to hyperthreads/core, 
but yes, we indeed need add TLB flush to invalidate old memory type info 
cached, via hvm_asid_flush_vcpu():

Thanks,
Jinsong
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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