git: c1434fd2deaf - stable/13 - bhyve: Validate host PAs used to map passthrough BARs.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 25 Aug 2022 17:31:43 UTC
The branch stable/13 has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=c1434fd2deaf66a0004cabd4d893584652b24f80 commit c1434fd2deaf66a0004cabd4d893584652b24f80 Author: John Baldwin <jhb@FreeBSD.org> AuthorDate: 2022-08-19 21:59:44 +0000 Commit: John Baldwin <jhb@FreeBSD.org> CommitDate: 2022-08-25 16:38:56 +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 (cherry picked from commit c94f30ea85b745a5137471876013f79689e0af03) --- 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 a936326e8df3..3782b7b510f6 100644 --- a/sys/amd64/vmm/io/ppt.c +++ b/sys/amd64/vmm/io/ppt.c @@ -440,6 +440,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) @@ -448,10 +465,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) {