From ce494a969ba2c9a13ae21dcc05e242cb41c2adb9 Mon Sep 17 00:00:00 2001 From: Kunkun Jiang Date: Mon, 12 Jun 2023 22:22:27 +0800 Subject: [PATCH] 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. Tips: This bugfix is consistent with the one for the olk-5.10 branch. Signed-off-by: Longfang Liu Signed-off-by: Kunkun Jiang --- .../crypto/hisilicon/migration/acc_vf_migration.c | 10 +++++++++- drivers/vfio/pci/vfio_pci.c | 12 +++++++++--- include/linux/vfio.h | 5 ++++- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/hisilicon/migration/acc_vf_migration.c b/drivers/crypto/hisilicon/migration/acc_vf_migration.c index cd38254c6598..cdaa55aa8716 100644 --- a/drivers/crypto/hisilicon/migration/acc_vf_migration.c +++ b/drivers/crypto/hisilicon/migration/acc_vf_migration.c @@ -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); diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 6d7ae4e3b983..c04b34247067 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -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); diff --git a/include/linux/vfio.h b/include/linux/vfio.h index 9a2217f13753..f516784e0356 100644 --- a/include/linux/vfio.h +++ b/include/linux/vfio.h @@ -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) \ -- GitLab