From: David Matlack Enforce that files for incoming (preserved by previous kernel) VFIO devices are retrieved via LIVEUPDATE_SESSION_RETRIEVE_FD rather than by opening the corresponding VFIO character device or via VFIO_GROUP_GET_DEVICE_FD. Both of these methods would result in VFIO initializing the device without access to the preserved state of the device passed by the previous kernel. Reviewed-by: Pranjal Shrivastava Signed-off-by: David Matlack Co-developed-by: Vipin Sharma Signed-off-by: Vipin Sharma --- drivers/vfio/device_cdev.c | 8 ++++++++ drivers/vfio/group.c | 9 +++++++++ drivers/vfio/pci/vfio_pci_liveupdate.c | 6 ++++++ drivers/vfio/vfio.h | 18 ++++++++++++++++++ 4 files changed, 41 insertions(+) diff --git a/drivers/vfio/device_cdev.c b/drivers/vfio/device_cdev.c index 1ab07ccaf3ab..4df0495941c6 100644 --- a/drivers/vfio/device_cdev.c +++ b/drivers/vfio/device_cdev.c @@ -49,6 +49,14 @@ static int vfio_device_cdev_open(struct vfio_device *device, struct file **filep } *filep = file; + } else if (vfio_liveupdate_incoming_is_preserved(device)) { + /* + * Since it is live update preserved device, it must be + * retrieved via LIVEUPDATE_SESSION_RETRIEVE_FD instead of + * opening /dev/vfio/devices/vfioX. + */ + ret = -EBUSY; + goto err_free_device_file; } file->private_data = df; diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c index b2299e5bc6df..62b4eaabc829 100644 --- a/drivers/vfio/group.c +++ b/drivers/vfio/group.c @@ -316,6 +316,15 @@ static int vfio_group_ioctl_get_device_fd(struct vfio_group *group, if (IS_ERR(device)) return PTR_ERR(device); + /* + * This device was preserved across a Live Update. Accessing it via + * VFIO_GROUP_GET_DEVICE_FD is not allowed. + */ + if (vfio_liveupdate_incoming_is_preserved(device)) { + vfio_device_put_registration(device); + return -EBUSY; + } + fd = FD_ADD(O_CLOEXEC, vfio_device_open_file(device)); if (fd < 0) vfio_device_put_registration(device); diff --git a/drivers/vfio/pci/vfio_pci_liveupdate.c b/drivers/vfio/pci/vfio_pci_liveupdate.c index 11c3bc8a8dcd..731a3e34085f 100644 --- a/drivers/vfio/pci/vfio_pci_liveupdate.c +++ b/drivers/vfio/pci/vfio_pci_liveupdate.c @@ -47,6 +47,12 @@ * ... * ioctl(session_fd, LIVEUPDATE_SESSION_FINISH, ...); * + * .. note:: + * After kexec, if a device was preserved by the previous kernel, attempting + * to open a new file for the device via its character device + * (``/dev/vfio/devices/X``) or via ``VFIO_GROUP_GET_DEVICE_FD`` will fail + * with ``-EBUSY``. + * * Restrictions * ============ * diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h index 0854f3fa1a22..5269fe021ee3 100644 --- a/drivers/vfio/vfio.h +++ b/drivers/vfio/vfio.h @@ -11,6 +11,7 @@ #include #include #include +#include struct iommufd_ctx; struct iommu_group; @@ -461,4 +462,21 @@ static inline void vfio_device_debugfs_init(struct vfio_device *vdev) { } static inline void vfio_device_debugfs_exit(struct vfio_device *vdev) { } #endif /* CONFIG_VFIO_DEBUGFS */ +#ifdef CONFIG_PCI_LIVEUPDATE +static inline bool vfio_liveupdate_incoming_is_preserved(struct vfio_device *device) +{ + struct device *d = device->dev; + + if (dev_is_pci(d)) + return to_pci_dev(d)->liveupdate_incoming; + + return false; +} +#else +static inline bool vfio_liveupdate_incoming_is_preserved(struct vfio_device *device) +{ + return false; +} +#endif /* CONFIG_PCI_LIVEUPDATE */ + #endif -- 2.54.0.563.g4f69b47b94-goog