Improper MSR range used for x2APIC emulation:

The MSR range specified for APIC use in the x2APIC access model spans 256 MSRs. Hypervisor code emulating read and write accesses to these MSRs erroneously covered 1024 MSRs. While the write emulation path is written such that accesses to the extra MSRs would not have any bad effect (they end up being no-ops), the read path would (attempt to) access memory beyond the single page set up for APIC emulation.

A buggy or malicious HVM guest can crash the host or read data relating to other guests or the hypervisor itself.



但是对于MSR_read,这可能会造成host crash,或者读到hypervisor或者其它虚拟机的相关数据。


logic error (out-of-bound read)



While the write path change appears to be purely cosmetic (but still gets done here for consistency), the read side istake permitted accesses beyond the virtual APIC page.

Note that while this isn’t fully in line with the specification (digesting MSRs 0x800-0xBFF for the x2APIC), this is the minimal possible fix addressing the security issue and getting x2APIC related code into a consistent shape (elsewhere a 256 rather than 1024 wide window is being used too). This will be dealt with subsequently.


int hvm_msr_read_intercept(unsigned int msr, uint64_t *msr_content)
    case MSR_IA32_APICBASE_MSR ... MSR_IA32_APICBASE_MSR + 0x3ff:
        if ( hvm_x2apic_msr_read(v, msr, msr_content) )
            goto gp_fault;

int hvm_x2apic_msr_read(struct vcpu *v, unsigned int msr, uint64_t *msr_content)
    struct vlapic *vlapic = vcpu_vlapic(v);
    uint32_t low, high = 0, offset = (msr - MSR_IA32_APICBASE_MSR) << 4;
    if ( !vlapic_x2apic_mode(vlapic) )
        return X86EMUL_UNHANDLEABLE;
    switch ( offset )
    case APIC_ICR:
        vlapic_read_aligned(vlapic, APIC_ICR2, &high);
        /* Fallthrough. */
    case APIC_ID:
    case APIC_LVR:
    case APIC_TASKPRI:
    case APIC_PROCPRI:
    case APIC_LDR:
    case APIC_SPIV:
    case APIC_ISR ... APIC_ISR + 0x70:
    case APIC_TMR ... APIC_TMR + 0x70:
    case APIC_IRR ... APIC_IRR + 0x70:
    case APIC_ESR:
    case APIC_CMCI:
    case APIC_LVTT:
    case APIC_LVTTHMR:
    case APIC_LVTPC:
    case APIC_LVT0:
    case APIC_LVT1:
    case APIC_LVTERR:
    case APIC_TMICT:
    case APIC_TMCCT:
    case APIC_TDCR:
        vlapic_read_aligned(vlapic, offset, &low);
        return X86EMUL_UNHANDLEABLE;
    *msr_content = (((uint64_t)high) << 32) | low;
    return X86EMUL_OKAY;

代码分析:在 hvmx2apicmsrread 中,offset的最大值为0xff<<4,即0xff0。case语句中,最大的APICTDCR为0x3E0,没有溢出。所以,没看出来有什么问题,这也许是为什么描述中写了attempt to的原因(猜)。

另外,patch中写道,这个fix并没有考虑到x2APIC的范围(0x800-0xBFF ),因此会在后续进一步改进。


A buggy or malicious HVM guest can crash the host or read data relating to other guests or the hypervisor itself.

DoS, information leak