@@ -778,25 +778,26 @@ static int vfio_pci_count_devs(struct pci_dev *pdev, void *data)
778778}
779779
780780struct vfio_pci_fill_info {
781- struct vfio_pci_dependent_device __user * devices ;
782- struct vfio_pci_dependent_device __user * devices_end ;
783781 struct vfio_device * vdev ;
782+ struct vfio_pci_dependent_device * devices ;
783+ int nr_devices ;
784784 u32 count ;
785785 u32 flags ;
786786};
787787
788788static int vfio_pci_fill_devs (struct pci_dev * pdev , void * data )
789789{
790- struct vfio_pci_dependent_device info = {
791- .segment = pci_domain_nr (pdev -> bus ),
792- .bus = pdev -> bus -> number ,
793- .devfn = pdev -> devfn ,
794- };
790+ struct vfio_pci_dependent_device * info ;
795791 struct vfio_pci_fill_info * fill = data ;
796792
797- fill -> count ++ ;
798- if (fill -> devices >= fill -> devices_end )
799- return 0 ;
793+ /* The topology changed since we counted devices */
794+ if (fill -> count >= fill -> nr_devices )
795+ return - EAGAIN ;
796+
797+ info = & fill -> devices [fill -> count ++ ];
798+ info -> segment = pci_domain_nr (pdev -> bus );
799+ info -> bus = pdev -> bus -> number ;
800+ info -> devfn = pdev -> devfn ;
800801
801802 if (fill -> flags & VFIO_PCI_HOT_RESET_FLAG_DEV_ID ) {
802803 struct iommufd_ctx * iommufd = vfio_iommufd_device_ictx (fill -> vdev );
@@ -809,19 +810,19 @@ static int vfio_pci_fill_devs(struct pci_dev *pdev, void *data)
809810 */
810811 vdev = vfio_find_device_in_devset (dev_set , & pdev -> dev );
811812 if (!vdev ) {
812- info . devid = VFIO_PCI_DEVID_NOT_OWNED ;
813+ info -> devid = VFIO_PCI_DEVID_NOT_OWNED ;
813814 } else {
814815 int id = vfio_iommufd_get_dev_id (vdev , iommufd );
815816
816817 if (id > 0 )
817- info . devid = id ;
818+ info -> devid = id ;
818819 else if (id == - ENOENT )
819- info . devid = VFIO_PCI_DEVID_OWNED ;
820+ info -> devid = VFIO_PCI_DEVID_OWNED ;
820821 else
821- info . devid = VFIO_PCI_DEVID_NOT_OWNED ;
822+ info -> devid = VFIO_PCI_DEVID_NOT_OWNED ;
822823 }
823824 /* If devid is VFIO_PCI_DEVID_NOT_OWNED, clear owned flag. */
824- if (info . devid == VFIO_PCI_DEVID_NOT_OWNED )
825+ if (info -> devid == VFIO_PCI_DEVID_NOT_OWNED )
825826 fill -> flags &= ~VFIO_PCI_HOT_RESET_FLAG_DEV_ID_OWNED ;
826827 } else {
827828 struct iommu_group * iommu_group ;
@@ -830,13 +831,10 @@ static int vfio_pci_fill_devs(struct pci_dev *pdev, void *data)
830831 if (!iommu_group )
831832 return - EPERM ; /* Cannot reset non-isolated devices */
832833
833- info . group_id = iommu_group_id (iommu_group );
834+ info -> group_id = iommu_group_id (iommu_group );
834835 iommu_group_put (iommu_group );
835836 }
836837
837- if (copy_to_user (fill -> devices , & info , sizeof (info )))
838- return - EFAULT ;
839- fill -> devices ++ ;
840838 return 0 ;
841839}
842840
@@ -1258,10 +1256,11 @@ static int vfio_pci_ioctl_get_pci_hot_reset_info(
12581256{
12591257 unsigned long minsz =
12601258 offsetofend (struct vfio_pci_hot_reset_info , count );
1259+ struct vfio_pci_dependent_device * devices = NULL ;
12611260 struct vfio_pci_hot_reset_info hdr ;
12621261 struct vfio_pci_fill_info fill = {};
12631262 bool slot = false;
1264- int ret = 0 ;
1263+ int ret , count ;
12651264
12661265 if (copy_from_user (& hdr , arg , minsz ))
12671266 return - EFAULT ;
@@ -1277,9 +1276,23 @@ static int vfio_pci_ioctl_get_pci_hot_reset_info(
12771276 else if (pci_probe_reset_bus (vdev -> pdev -> bus ))
12781277 return - ENODEV ;
12791278
1280- fill .devices = arg -> devices ;
1281- fill .devices_end = arg -> devices +
1282- (hdr .argsz - sizeof (hdr )) / sizeof (arg -> devices [0 ]);
1279+ ret = vfio_pci_for_each_slot_or_bus (vdev -> pdev , vfio_pci_count_devs ,
1280+ & count , slot );
1281+ if (ret )
1282+ return ret ;
1283+
1284+ if (count > (hdr .argsz - sizeof (hdr )) / sizeof (* devices )) {
1285+ hdr .count = count ;
1286+ ret = - ENOSPC ;
1287+ goto header ;
1288+ }
1289+
1290+ devices = kcalloc (count , sizeof (* devices ), GFP_KERNEL );
1291+ if (!devices )
1292+ return - ENOMEM ;
1293+
1294+ fill .devices = devices ;
1295+ fill .nr_devices = count ;
12831296 fill .vdev = & vdev -> vdev ;
12841297
12851298 if (vfio_device_cdev_opened (& vdev -> vdev ))
@@ -1291,16 +1304,23 @@ static int vfio_pci_ioctl_get_pci_hot_reset_info(
12911304 & fill , slot );
12921305 mutex_unlock (& vdev -> vdev .dev_set -> lock );
12931306 if (ret )
1294- return ret ;
1307+ goto out ;
1308+
1309+ if (copy_to_user (arg -> devices , devices ,
1310+ sizeof (* devices ) * fill .count )) {
1311+ ret = - EFAULT ;
1312+ goto out ;
1313+ }
12951314
12961315 hdr .count = fill .count ;
12971316 hdr .flags = fill .flags ;
1298- if (copy_to_user (arg , & hdr , minsz ))
1299- return - EFAULT ;
13001317
1301- if (fill .count > fill .devices - arg -> devices )
1302- return - ENOSPC ;
1303- return 0 ;
1318+ header :
1319+ if (copy_to_user (arg , & hdr , minsz ))
1320+ ret = - EFAULT ;
1321+ out :
1322+ kfree (devices );
1323+ return ret ;
13041324}
13051325
13061326static int
0 commit comments