From 545c006a333e05df4931fd42e2596418e9aa5281 Mon Sep 17 00:00:00 2001 From: "Liu,Junming" Date: Thu, 23 Sep 2021 16:59:50 +0000 Subject: [PATCH] hv: inject #GP if guest tries to reprogram pass-thru dev PIO bar In current design, when pass-thru dev, for the PIO bar, need to ensure the guest PIO start address equals to host PIO start address. But malicious guest may reprogram the PIO bar, then hv will pass-thru the reprogramed PIO address to guest. This isn't safe behavior. When guest tries to reprogram pass-thru dev PIO bar, inject #GP to guest directly. Tracked-On: #6508 Signed-off-by: Liu,Junming Reviewed-by: Zhao Yakui Reviewed-by: Fei Li --- hypervisor/dm/vpci/vdev.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/hypervisor/dm/vpci/vdev.c b/hypervisor/dm/vpci/vdev.c index 031070ef5..df55c67ba 100644 --- a/hypervisor/dm/vpci/vdev.c +++ b/hypervisor/dm/vpci/vdev.c @@ -30,6 +30,7 @@ #include #include "vpci_priv.h" #include +#include #include #include @@ -132,8 +133,26 @@ static void pci_vdev_update_vbar_base(struct pci_vdev *vdev, uint32_t idx) } } - if ( (base != 0UL) && (!is_pci_io_bar(vbar))) { - if ((!is_pci_mem_bar_base_valid(vpci2vm(vdev->vpci), base)) || (!mem_aligned_check(base, vdev->vbars[idx].size))) { + if (base != 0UL) { + if (is_pci_io_bar(vbar)) { + /* + * ACRN-DM and acrn-config should ensure the identical mapping of PIO bar of pass-thru devs. + * Currently, we don't support the reprogram of PIO bar of pass-thru devs, + * If guest tries to reprogram, hv will inject #GP to guest. + */ + if ((vdev->pdev != NULL) && ((lo & PCI_BASE_ADDRESS_IO_MASK) != vbar->base_hpa)) { + struct acrn_vcpu *vcpu = vcpu_from_pid(vpci2vm(vdev->vpci), get_pcpu_id()); + if (vcpu != NULL) { + vcpu_inject_gp(vcpu, 0U); + } + pr_err("%s, PCI:%02x:%02x.%x PIO BAR%d couldn't be reprogramed, " + "the valid value is 0x%lx, but the actual value is 0x%lx", + __func__, vdev->bdf.bits.b, vdev->bdf.bits.d, vdev->bdf.bits.f, idx, + vdev->vbars[idx].base_hpa, lo & PCI_BASE_ADDRESS_IO_MASK); + base = 0UL; + } + } else if ((!is_pci_mem_bar_base_valid(vpci2vm(vdev->vpci), base)) + || (!mem_aligned_check(base, vdev->vbars[idx].size))) { res = (base < (1UL << 32UL)) ? &(vdev->vpci->res32): &(vdev->vpci->res64); /* VM tries to reprogram vbar address out of pci mmio bar window, it can be caused by: * 1. For SOS, .xml is misaligned with the actual native platform, and we get wrong mmio window.