git: c94f30ea85b7 - main - bhyve: Validate host PAs used to map passthrough BARs.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 19 Aug 2022 22:25:36 UTC
The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=c94f30ea85b745a5137471876013f79689e0af03 commit c94f30ea85b745a5137471876013f79689e0af03 Author: John Baldwin <jhb@FreeBSD.org> AuthorDate: 2022-08-19 21:59:44 +0000 Commit: John Baldwin <jhb@FreeBSD.org> CommitDate: 2022-08-19 22:03:01 +0000 bhyve: Validate host PAs used to map passthrough BARs. Reject attempts to map host physical address ranges that are not subsets of a passthrough device's BAR into a guest. Reviewed by: markj, emaste MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D36238 --- sys/amd64/vmm/io/ppt.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c index 6bcd8f78bbab..6621c0ba2996 100644 --- a/sys/amd64/vmm/io/ppt.c +++ b/sys/amd64/vmm/io/ppt.c @@ -439,6 +439,23 @@ ppt_unassign_all(struct vm *vm) return (0); } +static bool +ppt_valid_bar_mapping(struct pptdev *ppt, vm_paddr_t hpa, size_t len) +{ + struct pci_map *pm; + pci_addr_t base, size; + + for (pm = pci_first_bar(ppt->dev); pm != NULL; pm = pci_next_bar(pm)) { + if (!PCI_BAR_MEM(pm->pm_value)) + continue; + base = pm->pm_value & PCIM_BAR_MEM_BASE; + size = (pci_addr_t)1 << pm->pm_size; + if (hpa >= base && hpa + len <= base + size) + return (true); + } + return (false); +} + int ppt_map_mmio(struct vm *vm, int bus, int slot, int func, vm_paddr_t gpa, size_t len, vm_paddr_t hpa) @@ -447,10 +464,17 @@ ppt_map_mmio(struct vm *vm, int bus, int slot, int func, struct pptseg *seg; struct pptdev *ppt; + if (len % PAGE_SIZE != 0 || len == 0 || gpa % PAGE_SIZE != 0 || + hpa % PAGE_SIZE != 0 || gpa + len < gpa || hpa + len < hpa) + return (EINVAL); + error = ppt_find(vm, bus, slot, func, &ppt); if (error) return (error); + if (!ppt_valid_bar_mapping(ppt, hpa, len)) + return (EINVAL); + for (i = 0; i < MAX_MMIOSEGS; i++) { seg = &ppt->mmio[i]; if (seg->len == 0) {