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       | 11 +++++++++++
 3 files changed, 24 insertions(+)

diff --git a/drivers/vfio/device_cdev.c b/drivers/vfio/device_cdev.c
index 0a6e972f322b..f1e54dcc04e7 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 c376a6279de0..93dbbf37ec4c 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -313,6 +313,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)) {
+               ret = -EBUSY;
+               goto err_put_device;
+       }
+
        fdno = get_unused_fd_flags(O_CLOEXEC);
        if (fdno < 0) {
                ret = fdno;
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 4e400a7219ea..040c2b2ee074 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;
@@ -425,4 +426,14 @@ 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);
 
+static inline bool vfio_liveupdate_incoming_is_preserved(struct vfio_device 
*device)
+{
+       struct device *d = device->dev;
+
+       if (dev_is_pci(d))
+               return pci_liveupdate_incoming_is_preserved(to_pci_dev(d));
+
+       return false;
+}
+
 #endif /* VFIO_H */
-- 
2.52.0.487.g5c8c507ade-goog


Reply via email to