Commit 349bd28a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'vfio-v6.19-rc4' of https://github.com/awilliam/linux-vfio

Pull VFIO fixes from Alex Williamson:

 - Restrict ROM access to dword to resolve a regression introduced with
   qword access seen on some Intel NICs. Update VGA region access to the
   same given lack of precedent for 64-bit users (Kevin Tian)

 - Fix missing .get_region_info_caps callback in the xe-vfio-pci variant
   driver due to integration through the DRM tree (Michal Wajdeczko)

 - Add aligned 64-bit access macros to tools/include/linux/types.h,
   allowing removal of uapi/linux/type.h includes from various vfio
   selftest, resolving redefinition warnings for integration with KVM
   selftests (David Matlack)

 - Fix error path memory leak in pds-vfio-pci variant driver (Zilin Guan)

 - Fix error path use-after-free in xe-vfio-pci variant driver (Alper Ak)

* tag 'vfio-v6.19-rc4' of https://github.com/awilliam/linux-vfio:
  vfio/xe: Fix use-after-free in xe_vfio_pci_alloc_file()
  vfio/pds: Fix memory leak in pds_vfio_dirty_enable()
  vfio: selftests: Drop <uapi/linux/types.h> includes
  tools include: Add definitions for __aligned_{l,b}e64
  vfio/xe: Add default handler for .get_region_info_caps
  vfio/pci: Disable qword access to the VGA region
  vfio/pci: Disable qword access to the PCI ROM bar
parents c8ebd433 acf44a23
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -561,7 +561,7 @@ nvgrace_gpu_map_and_read(struct nvgrace_gpu_pci_core_device *nvdev,
		ret = vfio_pci_core_do_io_rw(&nvdev->core_device, false,
					     nvdev->resmem.ioaddr,
					     buf, offset, mem_count,
					     0, 0, false);
					     0, 0, false, VFIO_PCI_IO_WIDTH_8);
	}

	return ret;
@@ -693,7 +693,7 @@ nvgrace_gpu_map_and_write(struct nvgrace_gpu_pci_core_device *nvdev,
		ret = vfio_pci_core_do_io_rw(&nvdev->core_device, false,
					     nvdev->resmem.ioaddr,
					     (char __user *)buf, pos, mem_count,
					     0, 0, true);
					     0, 0, true, VFIO_PCI_IO_WIDTH_8);
	}

	return ret;
+5 −2
Original line number Diff line number Diff line
@@ -292,8 +292,11 @@ static int pds_vfio_dirty_enable(struct pds_vfio_pci_device *pds_vfio,
	len = num_ranges * sizeof(*region_info);

	node = interval_tree_iter_first(ranges, 0, ULONG_MAX);
	if (!node)
		return -EINVAL;
	if (!node) {
		err = -EINVAL;
		goto out_free_region_info;
	}

	for (int i = 0; i < num_ranges; i++) {
		struct pds_lm_dirty_region_info *ri = &region_info[i];
		u64 region_size = node->last - node->start + 1;
+18 −7
Original line number Diff line number Diff line
@@ -135,7 +135,8 @@ VFIO_IORDWR(64)
ssize_t vfio_pci_core_do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem,
			       void __iomem *io, char __user *buf,
			       loff_t off, size_t count, size_t x_start,
			       size_t x_end, bool iswrite)
			       size_t x_end, bool iswrite,
			       enum vfio_pci_io_width max_width)
{
	ssize_t done = 0;
	int ret;
@@ -150,20 +151,19 @@ ssize_t vfio_pci_core_do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem,
		else
			fillable = 0;

		if (fillable >= 8 && !(off % 8)) {
		if (fillable >= 8 && !(off % 8) && max_width >= 8) {
			ret = vfio_pci_iordwr64(vdev, iswrite, test_mem,
						io, buf, off, &filled);
			if (ret)
				return ret;

		} else
		if (fillable >= 4 && !(off % 4)) {
		} else if (fillable >= 4 && !(off % 4) && max_width >= 4) {
			ret = vfio_pci_iordwr32(vdev, iswrite, test_mem,
						io, buf, off, &filled);
			if (ret)
				return ret;

		} else if (fillable >= 2 && !(off % 2)) {
		} else if (fillable >= 2 && !(off % 2) && max_width >= 2) {
			ret = vfio_pci_iordwr16(vdev, iswrite, test_mem,
						io, buf, off, &filled);
			if (ret)
@@ -234,6 +234,7 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
	void __iomem *io;
	struct resource *res = &vdev->pdev->resource[bar];
	ssize_t done;
	enum vfio_pci_io_width max_width = VFIO_PCI_IO_WIDTH_8;

	if (pci_resource_start(pdev, bar))
		end = pci_resource_len(pdev, bar);
@@ -262,6 +263,16 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
		if (!io)
			return -ENOMEM;
		x_end = end;

		/*
		 * Certain devices (e.g. Intel X710) don't support qword
		 * access to the ROM bar. Otherwise PCI AER errors might be
		 * triggered.
		 *
		 * Disable qword access to the ROM bar universally, which
		 * worked reliably for years before qword access is enabled.
		 */
		max_width = VFIO_PCI_IO_WIDTH_4;
	} else {
		int ret = vfio_pci_core_setup_barmap(vdev, bar);
		if (ret) {
@@ -278,7 +289,7 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
	}

	done = vfio_pci_core_do_io_rw(vdev, res->flags & IORESOURCE_MEM, io, buf, pos,
				      count, x_start, x_end, iswrite);
				      count, x_start, x_end, iswrite, max_width);

	if (done >= 0)
		*ppos += done;
@@ -352,7 +363,7 @@ ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
	 * to the memory enable bit in the command register.
	 */
	done = vfio_pci_core_do_io_rw(vdev, false, iomem, buf, off, count,
				      0, 0, iswrite);
				      0, 0, iswrite, VFIO_PCI_IO_WIDTH_4);

	vga_put(vdev->pdev, rsrc);

+4 −1
Original line number Diff line number Diff line
@@ -250,6 +250,7 @@ xe_vfio_pci_alloc_file(struct xe_vfio_pci_core_device *xe_vdev,
	struct xe_vfio_pci_migration_file *migf;
	const struct file_operations *fops;
	int flags;
	int ret;

	migf = kzalloc(sizeof(*migf), GFP_KERNEL_ACCOUNT);
	if (!migf)
@@ -259,8 +260,9 @@ xe_vfio_pci_alloc_file(struct xe_vfio_pci_core_device *xe_vdev,
	flags = type == XE_VFIO_FILE_SAVE ? O_RDONLY : O_WRONLY;
	migf->filp = anon_inode_getfile("xe_vfio_mig", fops, migf, flags);
	if (IS_ERR(migf->filp)) {
		ret = PTR_ERR(migf->filp);
		kfree(migf);
		return ERR_CAST(migf->filp);
		return ERR_PTR(ret);
	}

	mutex_init(&migf->lock);
@@ -504,6 +506,7 @@ static const struct vfio_device_ops xe_vfio_pci_ops = {
	.open_device = xe_vfio_pci_open_device,
	.close_device = xe_vfio_pci_close_device,
	.ioctl = vfio_pci_core_ioctl,
	.get_region_info_caps = vfio_pci_ioctl_get_region_info,
	.device_feature = vfio_pci_core_ioctl_feature,
	.read = vfio_pci_core_read,
	.write = vfio_pci_core_write,
+9 −1
Original line number Diff line number Diff line
@@ -145,6 +145,13 @@ struct vfio_pci_core_device {
	struct list_head	dmabufs;
};

enum vfio_pci_io_width {
	VFIO_PCI_IO_WIDTH_1 = 1,
	VFIO_PCI_IO_WIDTH_2 = 2,
	VFIO_PCI_IO_WIDTH_4 = 4,
	VFIO_PCI_IO_WIDTH_8 = 8,
};

/* Will be exported for vfio pci drivers usage */
int vfio_pci_core_register_dev_region(struct vfio_pci_core_device *vdev,
				      unsigned int type, unsigned int subtype,
@@ -188,7 +195,8 @@ pci_ers_result_t vfio_pci_core_aer_err_detected(struct pci_dev *pdev,
ssize_t vfio_pci_core_do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem,
			       void __iomem *io, char __user *buf,
			       loff_t off, size_t count, size_t x_start,
			       size_t x_end, bool iswrite);
			       size_t x_end, bool iswrite,
			       enum vfio_pci_io_width max_width);
bool __vfio_pci_memory_enabled(struct vfio_pci_core_device *vdev);
bool vfio_pci_core_range_intersect_range(loff_t buf_start, size_t buf_cnt,
					 loff_t reg_start, size_t reg_cnt,
Loading