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 void vfio_user_device_reset(VFIOUserProxy *proxy) 58 { 59 Error *local_err = NULL; 60 VFIOUserHdr hdr; 61 62 vfio_user_request_msg(&hdr, VFIO_USER_DEVICE_RESET, sizeof(hdr), 0); 63 64 if (!vfio_user_send_wait(proxy, &hdr, NULL, 0, &local_err)) { 65 error_prepend(&local_err, "%s: ", __func__); 66 error_report_err(local_err); 67 return; 68 } 69 70 if (hdr.flags & VFIO_USER_ERROR) { 71 error_printf("reset reply error %d\n", hdr.error_reply); 72 } 73 } 74 75 static int vfio_user_get_region_info(VFIOUserProxy *proxy, 76 struct vfio_region_info *info, 77 VFIOUserFDs *fds) 78 { 79 g_autofree VFIOUserRegionInfo *msgp = NULL; 80 Error *local_err = NULL; 81 uint32_t size; 82 83 /* data returned can be larger than vfio_region_info */ 84 if (info->argsz < sizeof(*info)) { 85 error_printf("vfio_user_get_region_info argsz too small\n"); 86 return -E2BIG; 87 } 88 if (fds != NULL && fds->send_fds != 0) { 89 error_printf("vfio_user_get_region_info can't send FDs\n"); 90 return -EINVAL; 91 } 92 93 size = info->argsz + sizeof(VFIOUserHdr); 94 msgp = g_malloc0(size); 95 96 vfio_user_request_msg(&msgp->hdr, VFIO_USER_DEVICE_GET_REGION_INFO, 97 sizeof(*msgp), 0); 98 msgp->argsz = info->argsz; 99 msgp->index = info->index; 100 101 if (!vfio_user_send_wait(proxy, &msgp->hdr, fds, size, &local_err)) { 102 error_prepend(&local_err, "%s: ", __func__); 103 error_report_err(local_err); 104 return -EFAULT; 105 } 106 107 if (msgp->hdr.flags & VFIO_USER_ERROR) { 108 return -msgp->hdr.error_reply; 109 } 110 trace_vfio_user_get_region_info(msgp->index, msgp->flags, msgp->size); 111 112 memcpy(info, &msgp->argsz, info->argsz); 113 114 /* 115 * If at least one region is directly mapped into the VM, then we can no 116 * longer rely on the sequential nature of vfio-user request handling to 117 * ensure that posted writes are completed before a subsequent read. In this 118 * case, disable posted write support. This is a per-device property, not 119 * per-region. 120 */ 121 if (info->flags & VFIO_REGION_INFO_FLAG_MMAP) { 122 vfio_user_disable_posted_writes(proxy); 123 } 124 125 return 0; 126 } 127 128 static int vfio_user_device_io_get_region_info(VFIODevice *vbasedev, 129 struct vfio_region_info *info, 130 int *fd) 131 { 132 VFIOUserFDs fds = { 0, 1, fd}; 133 int ret; 134 135 if (info->index > vbasedev->num_regions) { 136 return -EINVAL; 137 } 138 139 ret = vfio_user_get_region_info(vbasedev->proxy, info, &fds); 140 if (ret) { 141 return ret; 142 } 143 144 /* cap_offset in valid area */ 145 if ((info->flags & VFIO_REGION_INFO_FLAG_CAPS) && 146 (info->cap_offset < sizeof(*info) || info->cap_offset > info->argsz)) { 147 return -EINVAL; 148 } 149 150 return 0; 151 } 152 153 static int vfio_user_device_io_get_irq_info(VFIODevice *vbasedev, 154 struct vfio_irq_info *info) 155 { 156 VFIOUserProxy *proxy = vbasedev->proxy; 157 Error *local_err = NULL; 158 VFIOUserIRQInfo msg; 159 160 memset(&msg, 0, sizeof(msg)); 161 vfio_user_request_msg(&msg.hdr, VFIO_USER_DEVICE_GET_IRQ_INFO, 162 sizeof(msg), 0); 163 msg.argsz = info->argsz; 164 msg.index = info->index; 165 166 if (!vfio_user_send_wait(proxy, &msg.hdr, NULL, 0, &local_err)) { 167 error_prepend(&local_err, "%s: ", __func__); 168 error_report_err(local_err); 169 return -EFAULT; 170 } 171 172 if (msg.hdr.flags & VFIO_USER_ERROR) { 173 return -msg.hdr.error_reply; 174 } 175 trace_vfio_user_get_irq_info(msg.index, msg.flags, msg.count); 176 177 memcpy(info, &msg.argsz, sizeof(*info)); 178 return 0; 179 } 180 181 static int irq_howmany(int *fdp, uint32_t cur, uint32_t max) 182 { 183 int n = 0; 184 185 if (fdp[cur] != -1) { 186 do { 187 n++; 188 } while (n < max && fdp[cur + n] != -1); 189 } else { 190 do { 191 n++; 192 } while (n < max && fdp[cur + n] == -1); 193 } 194 195 return n; 196 } 197 198 static int vfio_user_device_io_set_irqs(VFIODevice *vbasedev, 199 struct vfio_irq_set *irq) 200 { 201 VFIOUserProxy *proxy = vbasedev->proxy; 202 g_autofree VFIOUserIRQSet *msgp = NULL; 203 uint32_t size, nfds, send_fds, sent_fds, max; 204 Error *local_err = NULL; 205 206 if (irq->argsz < sizeof(*irq)) { 207 error_printf("vfio_user_set_irqs argsz too small\n"); 208 return -EINVAL; 209 } 210 211 /* 212 * Handle simple case 213 */ 214 if ((irq->flags & VFIO_IRQ_SET_DATA_EVENTFD) == 0) { 215 size = sizeof(VFIOUserHdr) + irq->argsz; 216 msgp = g_malloc0(size); 217 218 vfio_user_request_msg(&msgp->hdr, VFIO_USER_DEVICE_SET_IRQS, size, 0); 219 msgp->argsz = irq->argsz; 220 msgp->flags = irq->flags; 221 msgp->index = irq->index; 222 msgp->start = irq->start; 223 msgp->count = irq->count; 224 trace_vfio_user_set_irqs(msgp->index, msgp->start, msgp->count, 225 msgp->flags); 226 227 if (!vfio_user_send_wait(proxy, &msgp->hdr, NULL, 0, &local_err)) { 228 error_prepend(&local_err, "%s: ", __func__); 229 error_report_err(local_err); 230 return -EFAULT; 231 } 232 233 if (msgp->hdr.flags & VFIO_USER_ERROR) { 234 return -msgp->hdr.error_reply; 235 } 236 237 return 0; 238 } 239 240 /* 241 * Calculate the number of FDs to send 242 * and adjust argsz 243 */ 244 nfds = (irq->argsz - sizeof(*irq)) / sizeof(int); 245 irq->argsz = sizeof(*irq); 246 msgp = g_malloc0(sizeof(*msgp)); 247 /* 248 * Send in chunks if over max_send_fds 249 */ 250 for (sent_fds = 0; nfds > sent_fds; sent_fds += send_fds) { 251 VFIOUserFDs *arg_fds, loop_fds; 252 253 /* must send all valid FDs or all invalid FDs in single msg */ 254 max = nfds - sent_fds; 255 if (max > proxy->max_send_fds) { 256 max = proxy->max_send_fds; 257 } 258 send_fds = irq_howmany((int *)irq->data, sent_fds, max); 259 260 vfio_user_request_msg(&msgp->hdr, VFIO_USER_DEVICE_SET_IRQS, 261 sizeof(*msgp), 0); 262 msgp->argsz = irq->argsz; 263 msgp->flags = irq->flags; 264 msgp->index = irq->index; 265 msgp->start = irq->start + sent_fds; 266 msgp->count = send_fds; 267 trace_vfio_user_set_irqs(msgp->index, msgp->start, msgp->count, 268 msgp->flags); 269 270 loop_fds.send_fds = send_fds; 271 loop_fds.recv_fds = 0; 272 loop_fds.fds = (int *)irq->data + sent_fds; 273 arg_fds = loop_fds.fds[0] != -1 ? &loop_fds : NULL; 274 275 if (!vfio_user_send_wait(proxy, &msgp->hdr, arg_fds, 0, &local_err)) { 276 error_prepend(&local_err, "%s: ", __func__); 277 error_report_err(local_err); 278 return -EFAULT; 279 } 280 281 if (msgp->hdr.flags & VFIO_USER_ERROR) { 282 return -msgp->hdr.error_reply; 283 } 284 } 285 286 return 0; 287 } 288 289 static int vfio_user_device_io_region_read(VFIODevice *vbasedev, uint8_t index, 290 off_t off, uint32_t count, 291 void *data) 292 { 293 g_autofree VFIOUserRegionRW *msgp = NULL; 294 VFIOUserProxy *proxy = vbasedev->proxy; 295 int size = sizeof(*msgp) + count; 296 Error *local_err = NULL; 297 298 if (count > proxy->max_xfer_size) { 299 return -EINVAL; 300 } 301 302 msgp = g_malloc0(size); 303 vfio_user_request_msg(&msgp->hdr, VFIO_USER_REGION_READ, sizeof(*msgp), 0); 304 msgp->offset = off; 305 msgp->region = index; 306 msgp->count = count; 307 trace_vfio_user_region_rw(msgp->region, msgp->offset, msgp->count); 308 309 if (!vfio_user_send_wait(proxy, &msgp->hdr, NULL, size, &local_err)) { 310 error_prepend(&local_err, "%s: ", __func__); 311 error_report_err(local_err); 312 return -EFAULT; 313 } 314 315 if (msgp->hdr.flags & VFIO_USER_ERROR) { 316 return -msgp->hdr.error_reply; 317 } else if (msgp->count > count) { 318 return -E2BIG; 319 } else { 320 memcpy(data, &msgp->data, msgp->count); 321 } 322 323 return msgp->count; 324 } 325 326 /* 327 * If this is a posted write, and VFIO_PROXY_NO_POST is not set, then we are OK 328 * to send the write to the socket without waiting for the server's reply: 329 * a subsequent read (of any region) will not pass the posted write, as all 330 * messages are handled sequentially. 331 */ 332 static int vfio_user_device_io_region_write(VFIODevice *vbasedev, uint8_t index, 333 off_t off, unsigned count, 334 void *data, bool post) 335 { 336 VFIOUserRegionRW *msgp = NULL; 337 VFIOUserProxy *proxy = vbasedev->proxy; 338 int size = sizeof(*msgp) + count; 339 Error *local_err = NULL; 340 int flags = 0; 341 int ret; 342 343 if (count > proxy->max_xfer_size) { 344 return -EINVAL; 345 } 346 347 if (proxy->flags & VFIO_PROXY_NO_POST) { 348 post = false; 349 } 350 351 if (post) { 352 flags |= VFIO_USER_NO_REPLY; 353 } 354 355 msgp = g_malloc0(size); 356 vfio_user_request_msg(&msgp->hdr, VFIO_USER_REGION_WRITE, size, flags); 357 msgp->offset = off; 358 msgp->region = index; 359 msgp->count = count; 360 memcpy(&msgp->data, data, count); 361 trace_vfio_user_region_rw(msgp->region, msgp->offset, msgp->count); 362 363 /* async send will free msg after it's sent */ 364 if (post) { 365 if (!vfio_user_send_async(proxy, &msgp->hdr, NULL, &local_err)) { 366 error_prepend(&local_err, "%s: ", __func__); 367 error_report_err(local_err); 368 return -EFAULT; 369 } 370 371 return count; 372 } 373 374 if (!vfio_user_send_wait(proxy, &msgp->hdr, NULL, 0, &local_err)) { 375 error_prepend(&local_err, "%s: ", __func__); 376 error_report_err(local_err); 377 g_free(msgp); 378 return -EFAULT; 379 } 380 381 if (msgp->hdr.flags & VFIO_USER_ERROR) { 382 ret = -msgp->hdr.error_reply; 383 } else { 384 ret = count; 385 } 386 387 g_free(msgp); 388 return ret; 389 } 390 391 /* 392 * Socket-based io_ops 393 */ 394 VFIODeviceIOOps vfio_user_device_io_ops_sock = { 395 .get_region_info = vfio_user_device_io_get_region_info, 396 .get_irq_info = vfio_user_device_io_get_irq_info, 397 .set_irqs = vfio_user_device_io_set_irqs, 398 .region_read = vfio_user_device_io_region_read, 399 .region_write = vfio_user_device_io_region_write, 400 401 }; 402