On Mon, Aug 16, 2021 at 09:42:43AM -0700, Elena Ufimtseva wrote: > @@ -3423,6 +3478,91 @@ static void vfio_user_pci_realize(PCIDevice *pdev, Error **errp) > goto error; > } > > + /* Get a copy of config space */ > + ret = vfio_user_region_read(vbasedev, VFIO_PCI_CONFIG_REGION_INDEX, 0, > + MIN(pci_config_size(pdev), vdev->config_size), > + pdev->config); > + if (ret < (int)MIN(pci_config_size(&vdev->pdev), vdev->config_size)) { > + error_setg_errno(errp, -ret, "failed to read device config space"); > + goto error; > + } > + > + /* vfio emulates a lot for us, but some bits need extra love */ > + vdev->emulated_config_bits = g_malloc0(vdev->config_size); > + > + /* QEMU can choose to expose the ROM or not */ > + memset(vdev->emulated_config_bits + PCI_ROM_ADDRESS, 0xff, 4); > + /* QEMU can also add or extend BARs */ > + memset(vdev->emulated_config_bits + PCI_BASE_ADDRESS_0, 0xff, 6 * 4); > + vdev->vendor_id = pci_get_word(pdev->config + PCI_VENDOR_ID); > + vdev->device_id = pci_get_word(pdev->config + PCI_DEVICE_ID); > + > + /* QEMU can change multi-function devices to single function, or reverse */ > + vdev->emulated_config_bits[PCI_HEADER_TYPE] = > + PCI_HEADER_TYPE_MULTI_FUNCTION; > + > + /* Restore or clear multifunction, this is always controlled by QEMU */ > + if (vdev->pdev.cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { > + vdev->pdev.config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION; > + } else { > + vdev->pdev.config[PCI_HEADER_TYPE] &= ~PCI_HEADER_TYPE_MULTI_FUNCTION; > + } > + > + /* > + * Clear host resource mapping info. If we choose not to register a > + * BAR, such as might be the case with the option ROM, we can get > + * confusing, unwritable, residual addresses from the host here. > + */ > + memset(&vdev->pdev.config[PCI_BASE_ADDRESS_0], 0, 24); > + memset(&vdev->pdev.config[PCI_ROM_ADDRESS], 0, 4); > + > + vfio_pci_size_rom(vdev); > + > + vfio_bars_prepare(vdev); > + > + vfio_msix_early_setup(vdev, &err); > + if (err) { > + error_propagate(errp, err); > + goto error; > + } > + > + vfio_bars_register(vdev); > + > + ret = vfio_add_capabilities(vdev, errp); > + if (ret) { > + goto out_teardown; > + } I haven't audited the common code to find places where the contents of the PCI Configuration Space are trusted. Input validation may need to be performed on offsets and other inputs that we read from the device. Otherwise: Reviewed-by: Stefan Hajnoczi