1 /* 2 * vfio protocol over a UNIX socket device handling. 3 * 4 * Copyright © 2018, 2021 Oracle and/or its affiliates. 5 * 6 * SPDX-License-Identifier: GPL-2.0-or-later 7 */ 8 9 #include "qemu/osdep.h" 10 #include "qapi/error.h" 11 #include "qemu/error-report.h" 12 13 #include "hw/vfio-user/device.h" 14 #include "hw/vfio-user/trace.h" 15 16 /* 17 * These are to defend against a malign server trying 18 * to force us to run out of memory. 19 */ 20 #define VFIO_USER_MAX_REGIONS 100 21 #define VFIO_USER_MAX_IRQS 50 22 23 bool vfio_user_get_device_info(VFIOUserProxy *proxy, 24 struct vfio_device_info *info, Error **errp) 25 { 26 VFIOUserDeviceInfo msg; 27 uint32_t argsz = sizeof(msg) - sizeof(msg.hdr); 28 29 memset(&msg, 0, sizeof(msg)); 30 vfio_user_request_msg(&msg.hdr, VFIO_USER_DEVICE_GET_INFO, sizeof(msg), 0); 31 msg.argsz = argsz; 32 33 if (!vfio_user_send_wait(proxy, &msg.hdr, NULL, 0, errp)) { 34 return false; 35 } 36 37 if (msg.hdr.flags & VFIO_USER_ERROR) { 38 error_setg_errno(errp, -msg.hdr.error_reply, 39 "VFIO_USER_DEVICE_GET_INFO failed"); 40 return false; 41 } 42 43 trace_vfio_user_get_info(msg.num_regions, msg.num_irqs); 44 45 memcpy(info, &msg.argsz, argsz); 46 47 /* defend against a malicious server */ 48 if (info->num_regions > VFIO_USER_MAX_REGIONS || 49 info->num_irqs > VFIO_USER_MAX_IRQS) { 50 error_setg_errno(errp, EINVAL, "invalid reply"); 51 return false; 52 } 53 54 return true; 55 } 56 57 static int vfio_user_get_region_info(VFIOUserProxy *proxy, 58 struct vfio_region_info *info, 59 VFIOUserFDs *fds) 60 { 61 g_autofree VFIOUserRegionInfo *msgp = NULL; 62 Error *local_err = NULL; 63 uint32_t size; 64 65 /* data returned can be larger than vfio_region_info */ 66 if (info->argsz < sizeof(*info)) { 67 error_printf("vfio_user_get_region_info argsz too small\n"); 68 return -E2BIG; 69 } 70 if (fds != NULL && fds->send_fds != 0) { 71 error_printf("vfio_user_get_region_info can't send FDs\n"); 72 return -EINVAL; 73 } 74 75 size = info->argsz + sizeof(VFIOUserHdr); 76 msgp = g_malloc0(size); 77 78 vfio_user_request_msg(&msgp->hdr, VFIO_USER_DEVICE_GET_REGION_INFO, 79 sizeof(*msgp), 0); 80 msgp->argsz = info->argsz; 81 msgp->index = info->index; 82 83 if (!vfio_user_send_wait(proxy, &msgp->hdr, fds, size, &local_err)) { 84 error_prepend(&local_err, "%s: ", __func__); 85 error_report_err(local_err); 86 return -EFAULT; 87 } 88 89 if (msgp->hdr.flags & VFIO_USER_ERROR) { 90 return -msgp->hdr.error_reply; 91 } 92 trace_vfio_user_get_region_info(msgp->index, msgp->flags, msgp->size); 93 94 memcpy(info, &msgp->argsz, info->argsz); 95 return 0; 96 } 97 98 99 static int vfio_user_device_io_get_region_info(VFIODevice *vbasedev, 100 struct vfio_region_info *info, 101 int *fd) 102 { 103 VFIOUserFDs fds = { 0, 1, fd}; 104 int ret; 105 106 if (info->index > vbasedev->num_regions) { 107 return -EINVAL; 108 } 109 110 ret = vfio_user_get_region_info(vbasedev->proxy, info, &fds); 111 if (ret) { 112 return ret; 113 } 114 115 /* cap_offset in valid area */ 116 if ((info->flags & VFIO_REGION_INFO_FLAG_CAPS) && 117 (info->cap_offset < sizeof(*info) || info->cap_offset > info->argsz)) { 118 return -EINVAL; 119 } 120 121 return 0; 122 } 123 124 static int vfio_user_device_io_region_read(VFIODevice *vbasedev, uint8_t index, 125 off_t off, uint32_t count, 126 void *data) 127 { 128 g_autofree VFIOUserRegionRW *msgp = NULL; 129 VFIOUserProxy *proxy = vbasedev->proxy; 130 int size = sizeof(*msgp) + count; 131 Error *local_err = NULL; 132 133 if (count > proxy->max_xfer_size) { 134 return -EINVAL; 135 } 136 137 msgp = g_malloc0(size); 138 vfio_user_request_msg(&msgp->hdr, VFIO_USER_REGION_READ, sizeof(*msgp), 0); 139 msgp->offset = off; 140 msgp->region = index; 141 msgp->count = count; 142 trace_vfio_user_region_rw(msgp->region, msgp->offset, msgp->count); 143 144 if (!vfio_user_send_wait(proxy, &msgp->hdr, NULL, size, &local_err)) { 145 error_prepend(&local_err, "%s: ", __func__); 146 error_report_err(local_err); 147 return -EFAULT; 148 } 149 150 if (msgp->hdr.flags & VFIO_USER_ERROR) { 151 return -msgp->hdr.error_reply; 152 } else if (msgp->count > count) { 153 return -E2BIG; 154 } else { 155 memcpy(data, &msgp->data, msgp->count); 156 } 157 158 return msgp->count; 159 } 160 161 static int vfio_user_device_io_region_write(VFIODevice *vbasedev, uint8_t index, 162 off_t off, unsigned count, 163 void *data, bool post) 164 { 165 g_autofree VFIOUserRegionRW *msgp = NULL; 166 VFIOUserProxy *proxy = vbasedev->proxy; 167 int size = sizeof(*msgp) + count; 168 Error *local_err = NULL; 169 int ret; 170 171 if (count > proxy->max_xfer_size) { 172 return -EINVAL; 173 } 174 175 msgp = g_malloc0(size); 176 vfio_user_request_msg(&msgp->hdr, VFIO_USER_REGION_WRITE, size, 0); 177 msgp->offset = off; 178 msgp->region = index; 179 msgp->count = count; 180 memcpy(&msgp->data, data, count); 181 trace_vfio_user_region_rw(msgp->region, msgp->offset, msgp->count); 182 183 /* Ignore post: all writes are synchronous/non-posted. */ 184 185 if (!vfio_user_send_wait(proxy, &msgp->hdr, NULL, 0, &local_err)) { 186 error_prepend(&local_err, "%s: ", __func__); 187 error_report_err(local_err); 188 return -EFAULT; 189 } 190 191 if (msgp->hdr.flags & VFIO_USER_ERROR) { 192 ret = -msgp->hdr.error_reply; 193 } else { 194 ret = count; 195 } 196 197 return ret; 198 } 199 200 /* 201 * Socket-based io_ops 202 */ 203 VFIODeviceIOOps vfio_user_device_io_ops_sock = { 204 .get_region_info = vfio_user_device_io_get_region_info, 205 .region_read = vfio_user_device_io_region_read, 206 .region_write = vfio_user_device_io_region_write, 207 208 }; 209