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_get_irq_info(VFIODevice *vbasedev, 125 struct vfio_irq_info *info) 126 { 127 VFIOUserProxy *proxy = vbasedev->proxy; 128 Error *local_err = NULL; 129 VFIOUserIRQInfo msg; 130 131 memset(&msg, 0, sizeof(msg)); 132 vfio_user_request_msg(&msg.hdr, VFIO_USER_DEVICE_GET_IRQ_INFO, 133 sizeof(msg), 0); 134 msg.argsz = info->argsz; 135 msg.index = info->index; 136 137 if (!vfio_user_send_wait(proxy, &msg.hdr, NULL, 0, &local_err)) { 138 error_prepend(&local_err, "%s: ", __func__); 139 error_report_err(local_err); 140 return -EFAULT; 141 } 142 143 if (msg.hdr.flags & VFIO_USER_ERROR) { 144 return -msg.hdr.error_reply; 145 } 146 trace_vfio_user_get_irq_info(msg.index, msg.flags, msg.count); 147 148 memcpy(info, &msg.argsz, sizeof(*info)); 149 return 0; 150 } 151 152 static int irq_howmany(int *fdp, uint32_t cur, uint32_t max) 153 { 154 int n = 0; 155 156 if (fdp[cur] != -1) { 157 do { 158 n++; 159 } while (n < max && fdp[cur + n] != -1); 160 } else { 161 do { 162 n++; 163 } while (n < max && fdp[cur + n] == -1); 164 } 165 166 return n; 167 } 168 169 static int vfio_user_device_io_set_irqs(VFIODevice *vbasedev, 170 struct vfio_irq_set *irq) 171 { 172 VFIOUserProxy *proxy = vbasedev->proxy; 173 g_autofree VFIOUserIRQSet *msgp = NULL; 174 uint32_t size, nfds, send_fds, sent_fds, max; 175 Error *local_err = NULL; 176 177 if (irq->argsz < sizeof(*irq)) { 178 error_printf("vfio_user_set_irqs argsz too small\n"); 179 return -EINVAL; 180 } 181 182 /* 183 * Handle simple case 184 */ 185 if ((irq->flags & VFIO_IRQ_SET_DATA_EVENTFD) == 0) { 186 size = sizeof(VFIOUserHdr) + irq->argsz; 187 msgp = g_malloc0(size); 188 189 vfio_user_request_msg(&msgp->hdr, VFIO_USER_DEVICE_SET_IRQS, size, 0); 190 msgp->argsz = irq->argsz; 191 msgp->flags = irq->flags; 192 msgp->index = irq->index; 193 msgp->start = irq->start; 194 msgp->count = irq->count; 195 trace_vfio_user_set_irqs(msgp->index, msgp->start, msgp->count, 196 msgp->flags); 197 198 if (!vfio_user_send_wait(proxy, &msgp->hdr, NULL, 0, &local_err)) { 199 error_prepend(&local_err, "%s: ", __func__); 200 error_report_err(local_err); 201 return -EFAULT; 202 } 203 204 if (msgp->hdr.flags & VFIO_USER_ERROR) { 205 return -msgp->hdr.error_reply; 206 } 207 208 return 0; 209 } 210 211 /* 212 * Calculate the number of FDs to send 213 * and adjust argsz 214 */ 215 nfds = (irq->argsz - sizeof(*irq)) / sizeof(int); 216 irq->argsz = sizeof(*irq); 217 msgp = g_malloc0(sizeof(*msgp)); 218 /* 219 * Send in chunks if over max_send_fds 220 */ 221 for (sent_fds = 0; nfds > sent_fds; sent_fds += send_fds) { 222 VFIOUserFDs *arg_fds, loop_fds; 223 224 /* must send all valid FDs or all invalid FDs in single msg */ 225 max = nfds - sent_fds; 226 if (max > proxy->max_send_fds) { 227 max = proxy->max_send_fds; 228 } 229 send_fds = irq_howmany((int *)irq->data, sent_fds, max); 230 231 vfio_user_request_msg(&msgp->hdr, VFIO_USER_DEVICE_SET_IRQS, 232 sizeof(*msgp), 0); 233 msgp->argsz = irq->argsz; 234 msgp->flags = irq->flags; 235 msgp->index = irq->index; 236 msgp->start = irq->start + sent_fds; 237 msgp->count = send_fds; 238 trace_vfio_user_set_irqs(msgp->index, msgp->start, msgp->count, 239 msgp->flags); 240 241 loop_fds.send_fds = send_fds; 242 loop_fds.recv_fds = 0; 243 loop_fds.fds = (int *)irq->data + sent_fds; 244 arg_fds = loop_fds.fds[0] != -1 ? &loop_fds : NULL; 245 246 if (!vfio_user_send_wait(proxy, &msgp->hdr, arg_fds, 0, &local_err)) { 247 error_prepend(&local_err, "%s: ", __func__); 248 error_report_err(local_err); 249 return -EFAULT; 250 } 251 252 if (msgp->hdr.flags & VFIO_USER_ERROR) { 253 return -msgp->hdr.error_reply; 254 } 255 } 256 257 return 0; 258 } 259 260 static int vfio_user_device_io_region_read(VFIODevice *vbasedev, uint8_t index, 261 off_t off, uint32_t count, 262 void *data) 263 { 264 g_autofree VFIOUserRegionRW *msgp = NULL; 265 VFIOUserProxy *proxy = vbasedev->proxy; 266 int size = sizeof(*msgp) + count; 267 Error *local_err = NULL; 268 269 if (count > proxy->max_xfer_size) { 270 return -EINVAL; 271 } 272 273 msgp = g_malloc0(size); 274 vfio_user_request_msg(&msgp->hdr, VFIO_USER_REGION_READ, sizeof(*msgp), 0); 275 msgp->offset = off; 276 msgp->region = index; 277 msgp->count = count; 278 trace_vfio_user_region_rw(msgp->region, msgp->offset, msgp->count); 279 280 if (!vfio_user_send_wait(proxy, &msgp->hdr, NULL, size, &local_err)) { 281 error_prepend(&local_err, "%s: ", __func__); 282 error_report_err(local_err); 283 return -EFAULT; 284 } 285 286 if (msgp->hdr.flags & VFIO_USER_ERROR) { 287 return -msgp->hdr.error_reply; 288 } else if (msgp->count > count) { 289 return -E2BIG; 290 } else { 291 memcpy(data, &msgp->data, msgp->count); 292 } 293 294 return msgp->count; 295 } 296 297 static int vfio_user_device_io_region_write(VFIODevice *vbasedev, uint8_t index, 298 off_t off, unsigned count, 299 void *data, bool post) 300 { 301 g_autofree VFIOUserRegionRW *msgp = NULL; 302 VFIOUserProxy *proxy = vbasedev->proxy; 303 int size = sizeof(*msgp) + count; 304 Error *local_err = NULL; 305 int ret; 306 307 if (count > proxy->max_xfer_size) { 308 return -EINVAL; 309 } 310 311 msgp = g_malloc0(size); 312 vfio_user_request_msg(&msgp->hdr, VFIO_USER_REGION_WRITE, size, 0); 313 msgp->offset = off; 314 msgp->region = index; 315 msgp->count = count; 316 memcpy(&msgp->data, data, count); 317 trace_vfio_user_region_rw(msgp->region, msgp->offset, msgp->count); 318 319 /* Ignore post: all writes are synchronous/non-posted. */ 320 321 if (!vfio_user_send_wait(proxy, &msgp->hdr, NULL, 0, &local_err)) { 322 error_prepend(&local_err, "%s: ", __func__); 323 error_report_err(local_err); 324 return -EFAULT; 325 } 326 327 if (msgp->hdr.flags & VFIO_USER_ERROR) { 328 ret = -msgp->hdr.error_reply; 329 } else { 330 ret = count; 331 } 332 333 return ret; 334 } 335 336 /* 337 * Socket-based io_ops 338 */ 339 VFIODeviceIOOps vfio_user_device_io_ops_sock = { 340 .get_region_info = vfio_user_device_io_get_region_info, 341 .get_irq_info = vfio_user_device_io_get_irq_info, 342 .set_irqs = vfio_user_device_io_set_irqs, 343 .region_read = vfio_user_device_io_region_read, 344 .region_write = vfio_user_device_io_region_write, 345 346 }; 347