xref: /qemu/hw/vfio-user/device.c (revision 3bdb738b734c77f93f93f8119c8f6ba8a9c5947c)
1*3bdb738bSJohn Levon /*
2*3bdb738bSJohn Levon  * vfio protocol over a UNIX socket device handling.
3*3bdb738bSJohn Levon  *
4*3bdb738bSJohn Levon  * Copyright © 2018, 2021 Oracle and/or its affiliates.
5*3bdb738bSJohn Levon  *
6*3bdb738bSJohn Levon  * SPDX-License-Identifier: GPL-2.0-or-later
7*3bdb738bSJohn Levon  */
8*3bdb738bSJohn Levon 
9*3bdb738bSJohn Levon #include "qemu/osdep.h"
10*3bdb738bSJohn Levon #include "qapi/error.h"
11*3bdb738bSJohn Levon #include "qemu/error-report.h"
12*3bdb738bSJohn Levon 
13*3bdb738bSJohn Levon #include "hw/vfio-user/device.h"
14*3bdb738bSJohn Levon #include "hw/vfio-user/trace.h"
15*3bdb738bSJohn Levon 
16*3bdb738bSJohn Levon /*
17*3bdb738bSJohn Levon  * These are to defend against a malign server trying
18*3bdb738bSJohn Levon  * to force us to run out of memory.
19*3bdb738bSJohn Levon  */
20*3bdb738bSJohn Levon #define VFIO_USER_MAX_REGIONS   100
21*3bdb738bSJohn Levon #define VFIO_USER_MAX_IRQS      50
22*3bdb738bSJohn Levon 
23*3bdb738bSJohn Levon bool vfio_user_get_device_info(VFIOUserProxy *proxy,
24*3bdb738bSJohn Levon                                struct vfio_device_info *info, Error **errp)
25*3bdb738bSJohn Levon {
26*3bdb738bSJohn Levon     VFIOUserDeviceInfo msg;
27*3bdb738bSJohn Levon     uint32_t argsz = sizeof(msg) - sizeof(msg.hdr);
28*3bdb738bSJohn Levon 
29*3bdb738bSJohn Levon     memset(&msg, 0, sizeof(msg));
30*3bdb738bSJohn Levon     vfio_user_request_msg(&msg.hdr, VFIO_USER_DEVICE_GET_INFO, sizeof(msg), 0);
31*3bdb738bSJohn Levon     msg.argsz = argsz;
32*3bdb738bSJohn Levon 
33*3bdb738bSJohn Levon     if (!vfio_user_send_wait(proxy, &msg.hdr, NULL, 0, errp)) {
34*3bdb738bSJohn Levon         return false;
35*3bdb738bSJohn Levon     }
36*3bdb738bSJohn Levon 
37*3bdb738bSJohn Levon     if (msg.hdr.flags & VFIO_USER_ERROR) {
38*3bdb738bSJohn Levon         error_setg_errno(errp, -msg.hdr.error_reply,
39*3bdb738bSJohn Levon                          "VFIO_USER_DEVICE_GET_INFO failed");
40*3bdb738bSJohn Levon         return false;
41*3bdb738bSJohn Levon     }
42*3bdb738bSJohn Levon 
43*3bdb738bSJohn Levon     trace_vfio_user_get_info(msg.num_regions, msg.num_irqs);
44*3bdb738bSJohn Levon 
45*3bdb738bSJohn Levon     memcpy(info, &msg.argsz, argsz);
46*3bdb738bSJohn Levon 
47*3bdb738bSJohn Levon     /* defend against a malicious server */
48*3bdb738bSJohn Levon     if (info->num_regions > VFIO_USER_MAX_REGIONS ||
49*3bdb738bSJohn Levon         info->num_irqs > VFIO_USER_MAX_IRQS) {
50*3bdb738bSJohn Levon         error_setg_errno(errp, EINVAL, "invalid reply");
51*3bdb738bSJohn Levon         return false;
52*3bdb738bSJohn Levon     }
53*3bdb738bSJohn Levon 
54*3bdb738bSJohn Levon     return true;
55*3bdb738bSJohn Levon }
56