DF-2322 / fix.diff
diff --git a/sys/bus/pci/pci.c b/sys/bus/pci/pci.c --- a/sys/bus/pci/pci.c +++ b/sys/bus/pci/pci.c @@ -1685,6 +1685,30 @@ cfg->msix.msix_table_res = table_res; cfg->msix.msix_pba_res = pba_res; + /* All of msix_msgnum, msix_table_offset and msix_pba_offset come from + device config space and so are attacker-controlled on a malicious PCI + device. Verify the BAR mappings are large enough for the reported + table/PBA layout before pci_mask_msix_allvectors() and later vector + writes can run off the mapping (OOB MMIO read/write). */ + { + u_long table_need = (u_long)msix->msix_table_offset + + (u_long)msix->msix_msgnum * 16; + u_long pba_need = (u_long)msix->msix_pba_offset + + howmany(msix->msix_msgnum, 8); + + if (table_need > rman_get_size(table_res) || + pba_need > rman_get_size(pba_res)) { + device_printf(dev, + "MSI-X table/PBA exceeds BAR size (table %#lx/%#lx, " + "pba %#lx/%#lx)\n", table_need, + (u_long)rman_get_size(table_res), pba_need, + (u_long)rman_get_size(pba_res)); + cfg->msix.msix_table_res = NULL; + cfg->msix.msix_pba_res = NULL; + return (ENXIO); + } + } + pci_mask_msix_allvectors(dev); return 0; |