On 11/9/22 00:13, John Johnson wrote:
Signed-off-by: Elena Ufimtseva <elena.ufimts...@oracle.com>
Signed-off-by: John G Johnson <john.g.john...@oracle.com>
Signed-off-by: Jagannathan Raman <jag.ra...@oracle.com>
---
hw/vfio/pci.c | 15 ++++++++++++++
hw/vfio/user-protocol.h | 13 ++++++++++++
hw/vfio/user.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++
hw/vfio/user.h | 2 ++
4 files changed, 85 insertions(+)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index b2534b3..2e0e41d 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -3465,6 +3465,8 @@ static void vfio_user_pci_realize(PCIDevice *pdev, Error
**errp)
VFIODevice *vbasedev = &vdev->vbasedev;
SocketAddress addr;
VFIOProxy *proxy;
+ struct vfio_device_info info;
+ int ret;
Error *err = NULL;
/*
@@ -3503,6 +3505,19 @@ static void vfio_user_pci_realize(PCIDevice *pdev, Error
**errp)
vbasedev->ops = &vfio_user_pci_ops;
vbasedev->type = VFIO_DEVICE_TYPE_PCI;
vbasedev->dev = DEVICE(vdev);
+ vbasedev->io_ops = &vfio_dev_io_sock;
+
+ ret = VDEV_GET_INFO(vbasedev, &info);
We are dealing with a "vfio-user-pci" device since this is being
called from the realize handler.
Is it really useful to go through the ops abstraction layer here ?
Can't we simply call vfio_user_get_info() ? and propagate the
underlying Error while we're at it.
+ if (ret) {
+ error_setg_errno(errp, -ret, "get info failure");
+ goto error;
+ }
+
+ vfio_populate_device(vdev, &err);
+ if (err) {
+ error_propagate(errp, err);
+ goto error;
+ }
return;
diff --git a/hw/vfio/user-protocol.h b/hw/vfio/user-protocol.h
index 5de5b20..43912a5 100644
--- a/hw/vfio/user-protocol.h
+++ b/hw/vfio/user-protocol.h
@@ -113,4 +113,17 @@ typedef struct {
*/
#define VFIO_USER_DEF_MAX_BITMAP (256 * 1024 * 1024)
+/*
+ * VFIO_USER_DEVICE_GET_INFO
+ * imported from struct_device_info
from struct vfio_device_info
Thanks,
C.
+ */
+typedef struct {
+ VFIOUserHdr hdr;
+ uint32_t argsz;
+ uint32_t flags;
+ uint32_t num_regions;
+ uint32_t num_irqs;
+ uint32_t cap_offset;
+} VFIOUserDeviceInfo;
+
#endif /* VFIO_USER_PROTOCOL_H */
diff --git a/hw/vfio/user.c b/hw/vfio/user.c
index 31bcc93..7873534 100644
--- a/hw/vfio/user.c
+++ b/hw/vfio/user.c
@@ -31,6 +31,14 @@
#include "qapi/qmp/qbool.h"
#include "user.h"
+
+/*
+ * These are to defend against a malign server trying
+ * to force us to run out of memory.
+ */
+#define VFIO_USER_MAX_REGIONS 100
+#define VFIO_USER_MAX_IRQS 50
+
static int wait_time = 5000; /* wait up to 5 sec for busy servers */
static IOThread *vfio_user_iothread;
@@ -1075,3 +1083,50 @@ int vfio_user_validate_version(VFIOProxy *proxy, Error **errp)
return 0;
}
+
+static int vfio_user_get_info(VFIOProxy *proxy, struct vfio_device_info *info)
+{
+ VFIOUserDeviceInfo msg;
+
+ memset(&msg, 0, sizeof(msg));
+ vfio_user_request_msg(&msg.hdr, VFIO_USER_DEVICE_GET_INFO, sizeof(msg), 0);
+ msg.argsz = sizeof(struct vfio_device_info);
+
+ vfio_user_send_wait(proxy, &msg.hdr, NULL, 0, false);
+ if (msg.hdr.flags & VFIO_USER_ERROR) {
+ return -msg.hdr.error_reply;
+ }
+
+ memcpy(info, &msg.argsz, sizeof(*info));
+ return 0;
+}
+
+
+/*
+ * Socket-based io_ops
+ */
+
+static int vfio_user_io_get_info(VFIODevice *vbasedev,
+ struct vfio_device_info *info)
+{
+ int ret;
+
+ ret = vfio_user_get_info(vbasedev->proxy, info);
+ if (ret) {
+ return ret;
+ }
+
+ /* defend against a malicious server */
+ if (info->num_regions > VFIO_USER_MAX_REGIONS ||
+ info->num_irqs > VFIO_USER_MAX_IRQS) {
+ error_printf("vfio_user_get_info: invalid reply\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+VFIODevIO vfio_dev_io_sock = {
+ .get_info = vfio_user_io_get_info,
+};
+
diff --git a/hw/vfio/user.h b/hw/vfio/user.h
index 8ce3cd9..2547cf6 100644
--- a/hw/vfio/user.h
+++ b/hw/vfio/user.h
@@ -92,4 +92,6 @@ void vfio_user_set_handler(VFIODevice *vbasedev,
void *reqarg);
int vfio_user_validate_version(VFIOProxy *proxy, Error **errp);
+extern VFIODevIO vfio_dev_io_sock;
+
#endif /* VFIO_USER_H */