summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Mooney <pmooney@pfmooney.com>2018-03-29 20:21:43 +0000
committerPatrick Mooney <pmooney@pfmooney.com>2018-04-05 19:33:25 +0000
commit2a4abd31bb5e23749133489fd773b65cc6cb2ff1 (patch)
tree2ca09be829a486e8f7d3885788b5bebc374c3cdd
parentbedbc0c4deaf436a12b78eb482054ca6929f5892 (diff)
downloadillumos-joyent-2a4abd31bb5e23749133489fd773b65cc6cb2ff1.tar.gz
OS-6855 bhyve ppt should verify BAR mappings
Reviewed by: Hans Rosenfeld <hans.rosenfeld@joyent.com> Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: John Levon <john.levon@joyent.com> Approved by: John Levon <john.levon@joyent.com>
-rw-r--r--usr/src/uts/i86pc/io/vmm/io/ppt.c53
1 files changed, 49 insertions, 4 deletions
diff --git a/usr/src/uts/i86pc/io/vmm/io/ppt.c b/usr/src/uts/i86pc/io/vmm/io/ppt.c
index 777d4129e0..f40a5c73cc 100644
--- a/usr/src/uts/i86pc/io/vmm/io/ppt.c
+++ b/usr/src/uts/i86pc/io/vmm/io/ppt.c
@@ -385,6 +385,42 @@ ppt_bar_crawl(struct pptdev *ppt)
return (err);
}
+static boolean_t
+ppt_bar_verify_mmio(struct pptdev *ppt, uint64_t base, uint64_t size)
+{
+ const uint64_t map_end = base + size;
+
+ /* Zero-length or overflow mappings are not valid */
+ if (map_end <= base) {
+ return (B_FALSE);
+ }
+ /* MMIO bounds should be page-aligned */
+ if ((base & PAGEOFFSET) != 0 || (size & PAGEOFFSET) != 0) {
+ return (B_FALSE);
+ }
+
+ for (uint_t i = 0; i < PCI_BASE_NUM; i++) {
+ const struct pptbar *bar = &ppt->pptd_bars[i];
+ const uint64_t bar_end = bar->base + bar->size;
+
+ /* Only memory BARs can be mapped */
+ if (bar->type != PCI_ADDR_MEM32 &&
+ bar->type != PCI_ADDR_MEM64) {
+ continue;
+ }
+
+ /* Does the mapping fit within this BAR? */
+ if (base < bar->base || base >= bar_end ||
+ map_end < bar->base || map_end > bar_end) {
+ continue;
+ }
+
+ /* This BAR satisfies the provided map */
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+
static int
ppt_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
@@ -760,8 +796,8 @@ ppt_unmap_mmio(struct vm *vm, struct pptdev *ppt)
seg = &ppt->mmio[i];
if (seg->len == 0)
continue;
- (void)vm_unmap_mmio(vm, seg->gpa, seg->len);
- bzero(seg, sizeof(struct pptseg));
+ (void) vm_unmap_mmio(vm, seg->gpa, seg->len);
+ bzero(seg, sizeof (struct pptseg));
}
}
@@ -1040,6 +1076,15 @@ ppt_map_mmio(struct vm *vm, int pptfd, vm_paddr_t gpa, size_t len,
goto done;
}
+ /*
+ * Ensure that the host-physical range of the requested mapping fits
+ * within one of the MMIO BARs of the device.
+ */
+ if (!ppt_bar_verify_mmio(ppt, hpa, len)) {
+ err = EINVAL;
+ goto done;
+ }
+
for (uint_t i = 0; i < MAX_MMIOSEGS; i++) {
struct pptseg *seg = &ppt->mmio[i];
@@ -1222,9 +1267,9 @@ ppt_setup_msix(struct vm *vm, int vcpu, int pptfd, int idx, uint64_t addr,
ppt->msix.num_msgs = numvec;
- ppt->msix.arg_sz = numvec * sizeof(ppt->msix.arg[0]);
+ ppt->msix.arg_sz = numvec * sizeof (ppt->msix.arg[0]);
ppt->msix.arg = kmem_zalloc(ppt->msix.arg_sz, KM_SLEEP);
- ppt->msix.inth_sz = numvec * sizeof(ddi_intr_handle_t);
+ ppt->msix.inth_sz = numvec * sizeof (ddi_intr_handle_t);
ppt->msix.inth = kmem_zalloc(ppt->msix.inth_sz, KM_SLEEP);
if (ddi_intr_alloc(dip, ppt->msix.inth, DDI_INTR_TYPE_MSIX, 0,