@@ -778,25 +778,26 @@ static int vfio_pci_count_devs(struct pci_dev *pdev, void *data)
778
778
}
779
779
780
780
struct vfio_pci_fill_info {
781
- struct vfio_pci_dependent_device __user * devices ;
782
- struct vfio_pci_dependent_device __user * devices_end ;
783
781
struct vfio_device * vdev ;
782
+ struct vfio_pci_dependent_device * devices ;
783
+ int nr_devices ;
784
784
u32 count ;
785
785
u32 flags ;
786
786
};
787
787
788
788
static int vfio_pci_fill_devs (struct pci_dev * pdev , void * data )
789
789
{
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 ;
795
791
struct vfio_pci_fill_info * fill = data ;
796
792
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 ;
800
801
801
802
if (fill -> flags & VFIO_PCI_HOT_RESET_FLAG_DEV_ID ) {
802
803
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)
809
810
*/
810
811
vdev = vfio_find_device_in_devset (dev_set , & pdev -> dev );
811
812
if (!vdev ) {
812
- info . devid = VFIO_PCI_DEVID_NOT_OWNED ;
813
+ info -> devid = VFIO_PCI_DEVID_NOT_OWNED ;
813
814
} else {
814
815
int id = vfio_iommufd_get_dev_id (vdev , iommufd );
815
816
816
817
if (id > 0 )
817
- info . devid = id ;
818
+ info -> devid = id ;
818
819
else if (id == - ENOENT )
819
- info . devid = VFIO_PCI_DEVID_OWNED ;
820
+ info -> devid = VFIO_PCI_DEVID_OWNED ;
820
821
else
821
- info . devid = VFIO_PCI_DEVID_NOT_OWNED ;
822
+ info -> devid = VFIO_PCI_DEVID_NOT_OWNED ;
822
823
}
823
824
/* 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 )
825
826
fill -> flags &= ~VFIO_PCI_HOT_RESET_FLAG_DEV_ID_OWNED ;
826
827
} else {
827
828
struct iommu_group * iommu_group ;
@@ -830,13 +831,10 @@ static int vfio_pci_fill_devs(struct pci_dev *pdev, void *data)
830
831
if (!iommu_group )
831
832
return - EPERM ; /* Cannot reset non-isolated devices */
832
833
833
- info . group_id = iommu_group_id (iommu_group );
834
+ info -> group_id = iommu_group_id (iommu_group );
834
835
iommu_group_put (iommu_group );
835
836
}
836
837
837
- if (copy_to_user (fill -> devices , & info , sizeof (info )))
838
- return - EFAULT ;
839
- fill -> devices ++ ;
840
838
return 0 ;
841
839
}
842
840
@@ -1258,10 +1256,11 @@ static int vfio_pci_ioctl_get_pci_hot_reset_info(
1258
1256
{
1259
1257
unsigned long minsz =
1260
1258
offsetofend (struct vfio_pci_hot_reset_info , count );
1259
+ struct vfio_pci_dependent_device * devices = NULL ;
1261
1260
struct vfio_pci_hot_reset_info hdr ;
1262
1261
struct vfio_pci_fill_info fill = {};
1263
1262
bool slot = false;
1264
- int ret = 0 ;
1263
+ int ret , count ;
1265
1264
1266
1265
if (copy_from_user (& hdr , arg , minsz ))
1267
1266
return - EFAULT ;
@@ -1277,9 +1276,23 @@ static int vfio_pci_ioctl_get_pci_hot_reset_info(
1277
1276
else if (pci_probe_reset_bus (vdev -> pdev -> bus ))
1278
1277
return - ENODEV ;
1279
1278
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 ;
1283
1296
fill .vdev = & vdev -> vdev ;
1284
1297
1285
1298
if (vfio_device_cdev_opened (& vdev -> vdev ))
@@ -1291,16 +1304,23 @@ static int vfio_pci_ioctl_get_pci_hot_reset_info(
1291
1304
& fill , slot );
1292
1305
mutex_unlock (& vdev -> vdev .dev_set -> lock );
1293
1306
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
+ }
1295
1314
1296
1315
hdr .count = fill .count ;
1297
1316
hdr .flags = fill .flags ;
1298
- if (copy_to_user (arg , & hdr , minsz ))
1299
- return - EFAULT ;
1300
1317
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 ;
1304
1324
}
1305
1325
1306
1326
static int
0 commit comments