[PATCH v6 2/2] hv: inject #GP if guest tries to reprogram pass-thru dev PIO bar #gp


Junming Liu <junming.liu@...>
 

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 <junming.liu@intel.com>
Reviewed-by: Zhao Yakui <yakui.zhao@intel.com>
Reviewed-by: Fei Li <fei1.li@intel.com>
---
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 <asm/guest/vm.h>
#include "vpci_priv.h"
#include <asm/guest/ept.h>
+#include <asm/guest/virq.h>
#include <logmsg.h>
#include <hash.h>

@@ -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, <board>.xml is misaligned with the actual native platform, and we get wrong mmio window.
--
2.17.1