Message ID | d0fcc3415ab22bf66bbd86c1d69d4dade8c023bb.1667542066.git.john.g.johnson@oracle.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | vfio-user client | expand |
On Tue, Nov 08, 2022 at 03:13:32PM -0800, John Johnson wrote: > +/* > + * VFIO_USER_DEVICE_GET_INFO > + * imported from struct_device_info > + */ > +typedef struct { > + VFIOUserHdr hdr; > + uint32_t argsz; > + uint32_t flags; > + uint32_t num_regions; > + uint32_t num_irqs; > + uint32_t cap_offset; > +} VFIOUserDeviceInfo; The server doesn't have or populate cap_offset - and this isn't in the protocol either. Looks good otherwise regards john
> On Dec 9, 2022, at 7:57 AM, John Levon <levon@movementarian.org> wrote: > > On Tue, Nov 08, 2022 at 03:13:32PM -0800, John Johnson wrote: > >> +/* >> + * VFIO_USER_DEVICE_GET_INFO >> + * imported from struct_device_info >> + */ >> +typedef struct { >> + VFIOUserHdr hdr; >> + uint32_t argsz; >> + uint32_t flags; >> + uint32_t num_regions; >> + uint32_t num_irqs; >> + uint32_t cap_offset; >> +} VFIOUserDeviceInfo; > > The server doesn't have or populate cap_offset - and this isn't in the protocol > either. > I can just delete it from VFIOUserDeviceInfo JJ
On 11/9/22 00:13, John Johnson wrote: > Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com> > Signed-off-by: John G Johnson <john.g.johnson@oracle.com> > Signed-off-by: Jagannathan Raman <jag.raman@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 */
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); + 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 + */ +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 */