Commit 6ecf6566 authored by Kunkun Jiang's avatar Kunkun Jiang
Browse files

vfio-pci: Match specific devices with vendor id and device id

virt inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I7QPGW


CVE: NA

------------------------------------------------------------------

In probe_vendor_drivers, all registered vendor drivers are traversed.
This is not a good idea. If a vendor driver is not implemented well
enough, it may cause the system to panic. Use the vendor id and
device id to select a proper driver.

In the pervious device registration logic, since the live migration
operation ops of the three accelerator devices is the same.
Therefore, only one driver entity will be registered. As a result,
only the first sec will be loaded successfully, while hpre and zip
cannot be loaded.

The acc live migration driver needs to be adapted.

Signed-off-by: default avatarLongfang Liu <liulongfang@huawei.com>
Signed-off-by: default avatarKunkun Jiang <jiangkunkun@huawei.com>
parent 75cd4528
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -1739,6 +1739,8 @@ static void acc_vf_remove(void *vendor_data)
static struct vfio_pci_vendor_driver_ops  sec_vf_mig_ops = {
	.owner		= THIS_MODULE,
	.name		= "hisi_sec2",
	.vendor		= PCI_VENDOR_ID_HUAWEI,
	.device		= PCI_DEVICE_ID_HUAWEI_SEC_VF,
	.probe		= acc_vf_probe,
	.remove		= acc_vf_remove,
	.device_ops	= &acc_vf_device_ops_node,
@@ -1747,6 +1749,8 @@ static struct vfio_pci_vendor_driver_ops sec_vf_mig_ops = {
static struct vfio_pci_vendor_driver_ops  hpre_vf_mig_ops = {
	.owner		= THIS_MODULE,
	.name		= "hisi_hpre",
	.vendor		= PCI_VENDOR_ID_HUAWEI,
	.device		= PCI_DEVICE_ID_HUAWEI_HPRE_VF,
	.probe		= acc_vf_probe,
	.remove		= acc_vf_remove,
	.device_ops	= &acc_vf_device_ops_node,
@@ -1755,6 +1759,8 @@ static struct vfio_pci_vendor_driver_ops hpre_vf_mig_ops = {
static struct vfio_pci_vendor_driver_ops  zip_vf_mig_ops = {
	.owner		= THIS_MODULE,
	.name		= "hisi_zip",
	.vendor		= PCI_VENDOR_ID_HUAWEI,
	.device		= PCI_DEVICE_ID_HUAWEI_ZIP_VF,
	.probe		= acc_vf_probe,
	.remove		= acc_vf_remove,
	.device_ops	= &acc_vf_device_ops_node,
@@ -1773,7 +1779,9 @@ static int __init acc_vf_module_init(void)

static void __exit acc_vf_module_exit(void)
{
	vfio_pci_unregister_vendor_driver(&acc_vf_device_ops_node);
	vfio_pci_unregister_vendor_driver(&sec_vf_mig_ops);
	vfio_pci_unregister_vendor_driver(&hpre_vf_mig_ops);
	vfio_pci_unregister_vendor_driver(&zip_vf_mig_ops);
};
module_init(acc_vf_module_init);
module_exit(acc_vf_module_exit);
+9 −3
Original line number Diff line number Diff line
@@ -2077,6 +2077,10 @@ static int probe_vendor_drivers(struct vfio_pci_device *vdev)
	list_for_each_entry(driver, &vfio_pci.vendor_drivers_list, next) {
		void *data;

		if (vdev->pdev->vendor != driver->ops->vendor ||
		    vdev->pdev->device != driver->ops->device)
			continue;

		if (!try_module_get(driver->ops->owner))
			continue;

@@ -2604,7 +2608,8 @@ int __vfio_pci_register_vendor_driver(struct vfio_pci_vendor_driver_ops *ops)

	/* Check for duplicates */
	list_for_each_entry(tmp, &vfio_pci.vendor_drivers_list, next) {
		if (tmp->ops->device_ops == ops->device_ops) {
		if (tmp->ops->vendor == ops->vendor &&
		    tmp->ops->vendor == ops->device) {
			mutex_unlock(&vfio_pci.vendor_drivers_lock);
			kfree(driver);
			return -EINVAL;
@@ -2622,14 +2627,15 @@ int __vfio_pci_register_vendor_driver(struct vfio_pci_vendor_driver_ops *ops)
}
EXPORT_SYMBOL_GPL(__vfio_pci_register_vendor_driver);

void vfio_pci_unregister_vendor_driver(struct vfio_device_ops *device_ops)
void vfio_pci_unregister_vendor_driver(struct vfio_pci_vendor_driver_ops *ops)
{
	struct vfio_pci_vendor_driver *driver, *tmp;

	mutex_lock(&vfio_pci.vendor_drivers_lock);
	list_for_each_entry_safe(driver, tmp,
				 &vfio_pci.vendor_drivers_list, next) {
		if (driver->ops->device_ops == device_ops) {
		if (driver->ops->vendor == ops->vendor &&
		    driver->ops->device == ops->device) {
			list_del(&driver->next);
			mutex_unlock(&vfio_pci.vendor_drivers_lock);
			kfree(driver);
+4 −1
Original line number Diff line number Diff line
@@ -253,12 +253,15 @@ extern int vfio_pci_set_vendor_regions(void *device_data,
struct vfio_pci_vendor_driver_ops {
	char			*name;
	struct module		*owner;
	/* Used to match device */
	unsigned short		vendor;
	unsigned short		device;
	void			*(*probe)(struct pci_dev *pdev);
	void			(*remove)(void *vendor_data);
	struct vfio_device_ops *device_ops;
};
int __vfio_pci_register_vendor_driver(struct vfio_pci_vendor_driver_ops *ops);
void vfio_pci_unregister_vendor_driver(struct vfio_device_ops *device_ops);
void vfio_pci_unregister_vendor_driver(struct vfio_pci_vendor_driver_ops *ops);

#define vfio_pci_register_vendor_driver(__name, __probe, __remove,	\
					__device_ops)			\