mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-21 13:08:42 +00:00
HV: vpci: check if address is in VM BAR MMIO space
When guest doing BAR re-programming, we should check whether the base address of the BAR is valid.This patch does this check by: 1. whether the gpa is located in the responding MMIO window 2. whether the gpa is aligned with the BAR size Tracked-On: #6011 Signed-off-by: Tao Yuhong <yuhong.tao@intel.com> Reviewed-by: Eddie Dong <eddie.dong@intel.com> Reviewed-by: Li Fei <fei1.li@intel.com>
This commit is contained in:
parent
8cf4ac944d
commit
ae9b4fcb0a
@ -106,11 +106,20 @@ uint32_t pci_vdev_read_vbar(const struct pci_vdev *vdev, uint32_t idx)
|
|||||||
return bar;
|
return bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_pci_mem_bar_base_valid(struct acrn_vm *vm, uint64_t base)
|
||||||
|
{
|
||||||
|
struct acrn_vpci *vpci = &vm->vpci;
|
||||||
|
struct pci_mmio_res *res = (base < (1UL << 32UL)) ? &(vpci->res32): &(vpci->res64);
|
||||||
|
|
||||||
|
return ((base >= res->start) && (base <= res->end));
|
||||||
|
}
|
||||||
|
|
||||||
static void pci_vdev_update_vbar_base(struct pci_vdev *vdev, uint32_t idx)
|
static void pci_vdev_update_vbar_base(struct pci_vdev *vdev, uint32_t idx)
|
||||||
{
|
{
|
||||||
struct pci_vbar *vbar;
|
struct pci_vbar *vbar;
|
||||||
uint64_t base = 0UL;
|
uint64_t base = 0UL;
|
||||||
uint32_t lo, hi, offset;
|
uint32_t lo, hi, offset;
|
||||||
|
struct pci_mmio_res *res;
|
||||||
|
|
||||||
vbar = &vdev->vbars[idx];
|
vbar = &vdev->vbars[idx];
|
||||||
offset = pci_bar_offset(idx);
|
offset = pci_bar_offset(idx);
|
||||||
@ -137,7 +146,19 @@ static void pci_vdev_update_vbar_base(struct pci_vdev *vdev, uint32_t idx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: 1. check whether the address locate in the MMIO windows 2. base must aligned with size */
|
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))) {
|
||||||
|
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. Malicious operation from VM, it tries to reprogram vbar address out of pci mmio bar window
|
||||||
|
*/
|
||||||
|
pr_err("%s reprogram PCI:%02x:%02x.%x BAR%d to addr:0x%lx,"
|
||||||
|
" which is out of mmio window[0x%lx - 0x%lx] or not aligned with size: 0x%lx",
|
||||||
|
__func__, vdev->bdf.bits.b, vdev->bdf.bits.d, vdev->bdf.bits.f, idx, base, res->start,
|
||||||
|
res->end, vdev->vbars[idx].size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vdev->vbars[idx].base_gpa = base;
|
vdev->vbars[idx].base_gpa = base;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
#include "vpci_priv.h"
|
#include "vpci_priv.h"
|
||||||
#include <asm/pci_dev.h>
|
#include <asm/pci_dev.h>
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
|
#include <board_info.h>
|
||||||
|
|
||||||
|
|
||||||
static void vpci_init_vdevs(struct acrn_vm *vm);
|
static void vpci_init_vdevs(struct acrn_vm *vm);
|
||||||
static int32_t vpci_read_cfg(struct acrn_vpci *vpci, union pci_bdf bdf, uint32_t offset, uint32_t bytes, uint32_t *val);
|
static int32_t vpci_read_cfg(struct acrn_vpci *vpci, union pci_bdf bdf, uint32_t offset, uint32_t bytes, uint32_t *val);
|
||||||
@ -227,10 +229,18 @@ void init_vpci(struct acrn_vm *vm)
|
|||||||
if (vm_config->load_order == SOS_VM) {
|
if (vm_config->load_order == SOS_VM) {
|
||||||
pci_mmcfg = get_mmcfg_region();
|
pci_mmcfg = get_mmcfg_region();
|
||||||
vm->vpci.pci_mmcfg = *pci_mmcfg;
|
vm->vpci.pci_mmcfg = *pci_mmcfg;
|
||||||
|
vm->vpci.res32.start = MMIO32_START;
|
||||||
|
vm->vpci.res32.end = MMIO32_END;
|
||||||
|
vm->vpci.res64.start = MMIO64_START;
|
||||||
|
vm->vpci.res64.end = MMIO64_END;
|
||||||
} else {
|
} else {
|
||||||
vm->vpci.pci_mmcfg.address = UOS_VIRT_PCI_MMCFG_BASE;
|
vm->vpci.pci_mmcfg.address = UOS_VIRT_PCI_MMCFG_BASE;
|
||||||
vm->vpci.pci_mmcfg.start_bus = UOS_VIRT_PCI_MMCFG_START_BUS;
|
vm->vpci.pci_mmcfg.start_bus = UOS_VIRT_PCI_MMCFG_START_BUS;
|
||||||
vm->vpci.pci_mmcfg.end_bus = UOS_VIRT_PCI_MMCFG_END_BUS;
|
vm->vpci.pci_mmcfg.end_bus = UOS_VIRT_PCI_MMCFG_END_BUS;
|
||||||
|
vm->vpci.res32.start = UOS_VIRT_PCI_MEMBASE32;
|
||||||
|
vm->vpci.res32.end = UOS_VIRT_PCI_MEMLIMIT32;
|
||||||
|
vm->vpci.res64.start = UOS_VIRT_PCI_MEMBASE64;
|
||||||
|
vm->vpci.res64.end = UOS_VIRT_PCI_MEMLIMIT64;
|
||||||
}
|
}
|
||||||
|
|
||||||
register_mmio_emulation_handler(vm, vpci_mmio_cfg_access, vm->vpci.pci_mmcfg.address,
|
register_mmio_emulation_handler(vm, vpci_mmio_cfg_access, vm->vpci.pci_mmcfg.address,
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
#define UOS_VIRT_PCI_MMCFG_BASE 0xE0000000UL
|
#define UOS_VIRT_PCI_MMCFG_BASE 0xE0000000UL
|
||||||
#define UOS_VIRT_PCI_MMCFG_START_BUS 0x0U
|
#define UOS_VIRT_PCI_MMCFG_START_BUS 0x0U
|
||||||
#define UOS_VIRT_PCI_MMCFG_END_BUS 0xFFU
|
#define UOS_VIRT_PCI_MMCFG_END_BUS 0xFFU
|
||||||
|
#define UOS_VIRT_PCI_MEMBASE32 0x80000000UL /* 2GB */
|
||||||
|
#define UOS_VIRT_PCI_MEMLIMIT32 0xE0000000UL /* 3.5GB */
|
||||||
|
#define UOS_VIRT_PCI_MEMBASE64 0x4000000000UL /* 256GB */
|
||||||
|
#define UOS_VIRT_PCI_MEMLIMIT64 0x8000000000UL /* 512GB */
|
||||||
|
|
||||||
void build_vrsdp(struct acrn_vm *vm);
|
void build_vrsdp(struct acrn_vm *vm);
|
||||||
|
|
||||||
|
@ -163,11 +163,19 @@ union pci_cfg_addr_reg {
|
|||||||
} bits;
|
} bits;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* start address & end address of MMIO BAR */
|
||||||
|
struct pci_mmio_res {
|
||||||
|
uint64_t start;
|
||||||
|
uint64_t end;
|
||||||
|
};
|
||||||
|
|
||||||
struct acrn_vpci {
|
struct acrn_vpci {
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
union pci_cfg_addr_reg addr;
|
union pci_cfg_addr_reg addr;
|
||||||
struct pci_mmcfg_region pci_mmcfg;
|
struct pci_mmcfg_region pci_mmcfg;
|
||||||
uint32_t pci_vdev_cnt;
|
uint32_t pci_vdev_cnt;
|
||||||
|
struct pci_mmio_res res32; /* 32-bit mmio start/end address */
|
||||||
|
struct pci_mmio_res res64; /* 64-bit mmio start/end address */
|
||||||
struct pci_vdev pci_vdevs[CONFIG_MAX_PCI_DEV_NUM];
|
struct pci_vdev pci_vdevs[CONFIG_MAX_PCI_DEV_NUM];
|
||||||
struct hlist_head vdevs_hlist_heads [VDEV_LIST_HASHSIZE];
|
struct hlist_head vdevs_hlist_heads [VDEV_LIST_HASHSIZE];
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user