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. Signed-off-by: David Matlack <[email protected]> --- drivers/vfio/device_cdev.c | 4 ++++ drivers/vfio/group.c | 9 +++++++++ include/linux/vfio.h | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/drivers/vfio/device_cdev.c b/drivers/vfio/device_cdev.c index 935f84a35875..355447e2add3 100644 --- a/drivers/vfio/device_cdev.c +++ b/drivers/vfio/device_cdev.c @@ -57,6 +57,10 @@ int vfio_device_fops_cdev_open(struct inode *inode, struct file *filep) struct vfio_device *device = container_of(inode->i_cdev, struct vfio_device, cdev); + /* Device file must be retrieved via LIVEUPDATE_SESSION_RETRIEVE_FD */ + if (vfio_liveupdate_incoming_is_preserved(device)) + return -EBUSY; + return __vfio_device_fops_cdev_open(device, filep); } diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c index d47ffada6912..63fc4d656215 100644 --- a/drivers/vfio/group.c +++ b/drivers/vfio/group.c @@ -311,6 +311,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/include/linux/vfio.h b/include/linux/vfio.h index dc592dc00f89..0921847b18b5 100644 --- a/include/linux/vfio.h +++ b/include/linux/vfio.h @@ -16,6 +16,7 @@ #include <linux/cdev.h> #include <uapi/linux/vfio.h> #include <linux/iova_bitmap.h> +#include <linux/pci.h> struct kvm; struct iommufd_ctx; @@ -431,4 +432,21 @@ static inline int __vfio_device_fops_cdev_open(struct vfio_device *device, struct vfio_device *vfio_find_device(const void *data, device_match_t match); +#ifdef CONFIG_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 + #endif /* VFIO_H */ -- 2.53.0.rc1.225.gd81095ad13-goog
