master
c 529 lines 15.6 KB
Raw
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 #include "qemu/lockable.h"
13 #include "qemu/thread.h"
14
15 #include "hw/vfio-user/device.h"
16 #include "hw/vfio-user/trace.h"
17
18 /*
19 * These are to defend against a malign server trying
20 * to force us to run out of memory.
21 */
22 #define VFIO_USER_MAX_REGIONS 100
23 #define VFIO_USER_MAX_IRQS 50
24
25 bool vfio_user_get_device_info(VFIOUserProxy *proxy,
26 struct vfio_device_info *info, Error **errp)
27 {
28 VFIOUserDeviceInfo msg;
29 uint32_t argsz = sizeof(msg) - sizeof(msg.hdr);
30
31 memset(&msg, 0, sizeof(msg));
32 vfio_user_request_msg(&msg.hdr, VFIO_USER_DEVICE_GET_INFO, sizeof(msg), 0);
33 msg.argsz = argsz;
34
35 if (!vfio_user_send_wait(proxy, &msg.hdr, NULL, 0, errp)) {
36 return false;
37 }
38
39 if (msg.hdr.flags & VFIO_USER_ERROR) {
40 error_setg_errno(errp, -msg.hdr.error_reply,
41 "VFIO_USER_DEVICE_GET_INFO failed");
42 return false;
43 }
44
45 trace_vfio_user_get_info(msg.num_regions, msg.num_irqs);
46
47 memcpy(info, &msg.argsz, argsz);
48
49 /* defend against a malicious server */
50 if (info->num_regions > VFIO_USER_MAX_REGIONS ||
51 info->num_irqs > VFIO_USER_MAX_IRQS) {
52 error_setg_errno(errp, EINVAL, "invalid reply");
53 return false;
54 }
55
56 return true;
57 }
58
59 void vfio_user_device_reset(VFIOUserProxy *proxy)
60 {
61 Error *local_err = NULL;
62 VFIOUserHdr hdr;
63
64 vfio_user_request_msg(&hdr, VFIO_USER_DEVICE_RESET, sizeof(hdr), 0);
65
66 if (!vfio_user_send_wait(proxy, &hdr, NULL, 0, &local_err)) {
67 error_prepend(&local_err, "%s: ", __func__);
68 error_report_err(local_err);
69 return;
70 }
71
72 if (hdr.flags & VFIO_USER_ERROR) {
73 error_printf("reset reply error %d\n", hdr.error_reply);
74 }
75 }
76
77 static int
78 vfio_user_device_io_device_feature(VFIODevice *vbasedev,
79 struct vfio_device_feature *feature)
80 {
81 g_autofree VFIOUserDeviceFeature *msgp = NULL;
82 VFIOUserProxy *proxy = vbasedev->proxy;
83 Error *local_err = NULL;
84 int size;
85
86 if (__builtin_add_overflow(feature->argsz, sizeof(VFIOUserHdr), &size)) {
87 error_printf("vfio_user_device_io_device_feature argsz too large\n");
88 return -E2BIG;
89 }
90 if (size > proxy->max_xfer_size) {
91 error_printf("vfio_user_device_io_device_feature argsz too large\n");
92 return -E2BIG;
93 }
94
95 msgp = g_malloc0(size);
96
97 vfio_user_request_msg(&msgp->hdr, VFIO_USER_DEVICE_FEATURE, size, 0);
98
99 memcpy(&msgp->argsz, &feature->argsz, feature->argsz);
100
101 if (!vfio_user_send_wait(proxy, &msgp->hdr, NULL, 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 /*
109 * Client expects ENOTTY for "not supported", but the protocol may
110 * return EINVAL (which should only occur in the case the feature isn't
111 * actually supported on the server).
112 */
113 if (msgp->hdr.error_reply == EINVAL) {
114 return -ENOTTY;
115 }
116
117 return -msgp->hdr.error_reply;
118 }
119
120 memcpy(feature, &msgp->argsz, feature->argsz);
121
122 trace_vfio_user_device_io_device_feature(msgp->argsz, msgp->flags);
123
124 return 0;
125 }
126
127 static int vfio_user_get_region_info(VFIOUserProxy *proxy,
128 struct vfio_region_info *info,
129 VFIOUserFDs *fds)
130 {
131 g_autofree VFIOUserRegionInfo *msgp = NULL;
132 Error *local_err = NULL;
133 uint32_t size;
134
135 /* data returned can be larger than vfio_region_info */
136 if (info->argsz < sizeof(*info)) {
137 error_printf("vfio_user_get_region_info argsz too small\n");
138 return -E2BIG;
139 }
140
141 /*
142 * Ensure that size doesn't overflow, otherwise we'll allocate a much
143 * smaller buffer than we need.
144 */
145 if (__builtin_add_overflow(info->argsz, sizeof(VFIOUserHdr), &size)) {
146 error_printf("vfio_user_get_region_info argsz too large\n");
147 return -E2BIG;
148 }
149 if (size > proxy->max_xfer_size) {
150 error_printf("vfio_user_get_region_info argsz too large\n");
151 return -E2BIG;
152 }
153
154 if (fds != NULL && fds->send_fds != 0) {
155 error_printf("vfio_user_get_region_info can't send FDs\n");
156 return -EINVAL;
157 }
158
159 msgp = g_malloc0(size);
160
161 vfio_user_request_msg(&msgp->hdr, VFIO_USER_DEVICE_GET_REGION_INFO,
162 sizeof(*msgp), 0);
163 msgp->argsz = info->argsz;
164 msgp->index = info->index;
165
166 if (!vfio_user_send_wait(proxy, &msgp->hdr, fds, size, &local_err)) {
167 error_prepend(&local_err, "%s: ", __func__);
168 error_report_err(local_err);
169 return -EFAULT;
170 }
171
172 if (msgp->hdr.flags & VFIO_USER_ERROR) {
173 return -msgp->hdr.error_reply;
174 }
175 trace_vfio_user_get_region_info(msgp->index, msgp->flags, msgp->size);
176
177 if (msgp->argsz < sizeof(*info)) {
178 error_printf("vfio_user_get_region_info reply argsz too small\n");
179 return -EINVAL;
180 }
181
182 /*
183 * The server can respond with a larger argsz in the reply to request a
184 * larger buffer on the next iteration via vfio_device_get_region_info().
185 * Reject values that would trigger an oversized realloc.
186 */
187 if (msgp->argsz > proxy->max_xfer_size) {
188 error_printf("vfio_user_get_region_info reply argsz too large\n");
189 return -E2BIG;
190 }
191
192 memcpy(info, &msgp->argsz, info->argsz);
193
194 /*
195 * If at least one region is directly mapped into the VM, then we can no
196 * longer rely on the sequential nature of vfio-user request handling to
197 * ensure that posted writes are completed before a subsequent read. In this
198 * case, disable posted write support. This is a per-device property, not
199 * per-region.
200 */
201 if (info->flags & VFIO_REGION_INFO_FLAG_MMAP) {
202 vfio_user_disable_posted_writes(proxy);
203 }
204
205 return 0;
206 }
207
208 static int vfio_user_device_io_get_region_info(VFIODevice *vbasedev,
209 struct vfio_region_info *info,
210 int *fd)
211 {
212 VFIOUserFDs fds = { 0, 1, fd};
213 int ret;
214
215 if (info->index > vbasedev->num_initial_regions) {
216 return -EINVAL;
217 }
218
219 ret = vfio_user_get_region_info(vbasedev->proxy, info, &fds);
220 if (ret) {
221 return ret;
222 }
223
224 /* cap_offset in valid area */
225 if ((info->flags & VFIO_REGION_INFO_FLAG_CAPS) &&
226 (info->cap_offset < sizeof(*info)
227 || info->cap_offset + sizeof(struct vfio_info_cap_header) > info->argsz)) {
228 return -EINVAL;
229 }
230
231 return 0;
232 }
233
234 static int vfio_user_device_io_get_irq_info(VFIODevice *vbasedev,
235 struct vfio_irq_info *info)
236 {
237 VFIOUserProxy *proxy = vbasedev->proxy;
238 Error *local_err = NULL;
239 VFIOUserIRQInfo msg;
240
241 memset(&msg, 0, sizeof(msg));
242 vfio_user_request_msg(&msg.hdr, VFIO_USER_DEVICE_GET_IRQ_INFO,
243 sizeof(msg), 0);
244 msg.argsz = info->argsz;
245 msg.index = info->index;
246
247 if (!vfio_user_send_wait(proxy, &msg.hdr, NULL, 0, &local_err)) {
248 error_prepend(&local_err, "%s: ", __func__);
249 error_report_err(local_err);
250 return -EFAULT;
251 }
252
253 if (msg.hdr.flags & VFIO_USER_ERROR) {
254 return -msg.hdr.error_reply;
255 }
256 trace_vfio_user_get_irq_info(msg.index, msg.flags, msg.count);
257
258 memcpy(info, &msg.argsz, sizeof(*info));
259 return 0;
260 }
261
262 static int irq_howmany(int *fdp, uint32_t cur, uint32_t max)
263 {
264 int n = 0;
265
266 if (fdp[cur] != -1) {
267 do {
268 n++;
269 } while (n < max && fdp[cur + n] != -1);
270 } else {
271 do {
272 n++;
273 } while (n < max && fdp[cur + n] == -1);
274 }
275
276 return n;
277 }
278
279 static int vfio_user_device_io_set_irqs(VFIODevice *vbasedev,
280 struct vfio_irq_set *irq)
281 {
282 VFIOUserProxy *proxy = vbasedev->proxy;
283 g_autofree VFIOUserIRQSet *msgp = NULL;
284 uint32_t size, nfds, send_fds, sent_fds, max;
285 Error *local_err = NULL;
286
287 if (irq->argsz < sizeof(*irq)) {
288 error_printf("vfio_user_set_irqs argsz too small\n");
289 return -EINVAL;
290 }
291
292 /*
293 * Handle simple case
294 */
295 if ((irq->flags & VFIO_IRQ_SET_DATA_EVENTFD) == 0) {
296 if (__builtin_add_overflow(irq->argsz, sizeof(VFIOUserHdr), &size)) {
297 error_printf("vfio_user_set_irqs argsz too large\n");
298 return -E2BIG;
299 }
300 if (size > proxy->max_xfer_size) {
301 error_printf("vfio_user_device_io_set_irqs argsz too large\n");
302 return -E2BIG;
303 }
304
305 msgp = g_malloc0(size);
306
307 vfio_user_request_msg(&msgp->hdr, VFIO_USER_DEVICE_SET_IRQS, size, 0);
308 msgp->argsz = irq->argsz;
309 msgp->flags = irq->flags;
310 msgp->index = irq->index;
311 msgp->start = irq->start;
312 msgp->count = irq->count;
313 trace_vfio_user_set_irqs(msgp->index, msgp->start, msgp->count,
314 msgp->flags);
315
316 if (!vfio_user_send_wait(proxy, &msgp->hdr, NULL, 0, &local_err)) {
317 error_prepend(&local_err, "%s: ", __func__);
318 error_report_err(local_err);
319 return -EFAULT;
320 }
321
322 if (msgp->hdr.flags & VFIO_USER_ERROR) {
323 return -msgp->hdr.error_reply;
324 }
325
326 return 0;
327 }
328
329 /*
330 * Calculate the number of FDs to send
331 * and adjust argsz
332 */
333 nfds = (irq->argsz - sizeof(*irq)) / sizeof(int);
334 irq->argsz = sizeof(*irq);
335 msgp = g_malloc0(sizeof(*msgp));
336 /*
337 * Send in chunks if over max_send_fds
338 */
339 for (sent_fds = 0; nfds > sent_fds; sent_fds += send_fds) {
340 VFIOUserFDs *arg_fds, loop_fds;
341
342 /* must send all valid FDs or all invalid FDs in single msg */
343 max = nfds - sent_fds;
344 if (max > proxy->max_send_fds) {
345 max = proxy->max_send_fds;
346 }
347 send_fds = irq_howmany((int *)irq->data, sent_fds, max);
348
349 vfio_user_request_msg(&msgp->hdr, VFIO_USER_DEVICE_SET_IRQS,
350 sizeof(*msgp), 0);
351 msgp->argsz = irq->argsz;
352 msgp->flags = irq->flags;
353 msgp->index = irq->index;
354 msgp->start = irq->start + sent_fds;
355 msgp->count = send_fds;
356 trace_vfio_user_set_irqs(msgp->index, msgp->start, msgp->count,
357 msgp->flags);
358
359 loop_fds.send_fds = send_fds;
360 loop_fds.recv_fds = 0;
361 loop_fds.fds = (int *)irq->data + sent_fds;
362 arg_fds = loop_fds.fds[0] != -1 ? &loop_fds : NULL;
363
364 if (!vfio_user_send_wait(proxy, &msgp->hdr, arg_fds, 0, &local_err)) {
365 error_prepend(&local_err, "%s: ", __func__);
366 error_report_err(local_err);
367 return -EFAULT;
368 }
369
370 if (msgp->hdr.flags & VFIO_USER_ERROR) {
371 return -msgp->hdr.error_reply;
372 }
373 }
374
375 return 0;
376 }
377
378 static int vfio_user_device_io_region_read(VFIODevice *vbasedev, uint8_t index,
379 off_t off, uint32_t count,
380 void *data)
381 {
382 g_autofree VFIOUserRegionRW *msgp = NULL;
383 VFIOUserProxy *proxy = vbasedev->proxy;
384 int size = sizeof(*msgp) + count;
385 Error *local_err = NULL;
386
387 if (count > proxy->max_xfer_size) {
388 return -EINVAL;
389 }
390
391 msgp = g_malloc0(size);
392 vfio_user_request_msg(&msgp->hdr, VFIO_USER_REGION_READ, sizeof(*msgp), 0);
393 msgp->offset = off;
394 msgp->region = index;
395 msgp->count = count;
396 trace_vfio_user_region_rw(msgp->region, msgp->offset, msgp->count);
397
398 if (!vfio_user_send_wait(proxy, &msgp->hdr, NULL, size, &local_err)) {
399 error_prepend(&local_err, "%s: ", __func__);
400 error_report_err(local_err);
401 return -EFAULT;
402 }
403
404 if (msgp->hdr.flags & VFIO_USER_ERROR) {
405 return -msgp->hdr.error_reply;
406 } else if (msgp->count > count) {
407 return -E2BIG;
408 } else {
409 memcpy(data, &msgp->data, msgp->count);
410 }
411
412 return msgp->count;
413 }
414
415 /*
416 * If this is a posted write, and VFIO_PROXY_NO_POST is not set, then we are OK
417 * to send the write to the socket without waiting for the server's reply:
418 * a subsequent read (of any region) will not pass the posted write, as all
419 * messages are handled sequentially.
420 */
421 static int vfio_user_device_io_region_write(VFIODevice *vbasedev, uint8_t index,
422 off_t off, unsigned count,
423 void *data, bool post)
424 {
425 VFIOUserRegionRW *msgp = NULL;
426 VFIOUserProxy *proxy = vbasedev->proxy;
427 int size = sizeof(*msgp) + count;
428 Error *local_err = NULL;
429 bool can_multi;
430 int flags = 0;
431 int ret;
432
433 if (count > proxy->max_xfer_size) {
434 return -EINVAL;
435 }
436
437 if (proxy->flags & VFIO_PROXY_NO_POST) {
438 post = false;
439 }
440
441 if (post) {
442 flags |= VFIO_USER_NO_REPLY;
443 }
444
445 /* write eligible to be in a WRITE_MULTI msg ? */
446 can_multi = (proxy->flags & VFIO_PROXY_USE_MULTI) && post &&
447 count <= VFIO_USER_MULTI_DATA;
448
449 /*
450 * This should be a rare case, so first check without the lock,
451 * if we're wrong, vfio_send_queued() will flush any posted writes
452 * we missed here
453 */
454 if (proxy->wr_multi != NULL ||
455 (proxy->num_outgoing > VFIO_USER_OUT_HIGH && can_multi)) {
456
457 /*
458 * re-check with lock
459 *
460 * if already building a WRITE_MULTI msg,
461 * add this one if possible else flush pending before
462 * sending the current one
463 *
464 * else if outgoing queue is over the highwater,
465 * start a new WRITE_MULTI message
466 */
467 WITH_QEMU_LOCK_GUARD(&proxy->lock) {
468 if (proxy->wr_multi != NULL) {
469 if (can_multi) {
470 vfio_user_add_multi(proxy, index, off, count, data);
471 return count;
472 }
473 vfio_user_flush_multi(proxy);
474 } else if (proxy->num_outgoing > VFIO_USER_OUT_HIGH && can_multi) {
475 vfio_user_create_multi(proxy);
476 vfio_user_add_multi(proxy, index, off, count, data);
477 return count;
478 }
479 }
480 }
481
482 msgp = g_malloc0(size);
483 vfio_user_request_msg(&msgp->hdr, VFIO_USER_REGION_WRITE, size, flags);
484 msgp->offset = off;
485 msgp->region = index;
486 msgp->count = count;
487 memcpy(&msgp->data, data, count);
488 trace_vfio_user_region_rw(msgp->region, msgp->offset, msgp->count);
489
490 /* async send will free msg after it's sent */
491 if (post) {
492 if (!vfio_user_send_async(proxy, &msgp->hdr, NULL, &local_err)) {
493 error_prepend(&local_err, "%s: ", __func__);
494 error_report_err(local_err);
495 return -EFAULT;
496 }
497
498 return count;
499 }
500
501 if (!vfio_user_send_wait(proxy, &msgp->hdr, NULL, 0, &local_err)) {
502 error_prepend(&local_err, "%s: ", __func__);
503 error_report_err(local_err);
504 g_free(msgp);
505 return -EFAULT;
506 }
507
508 if (msgp->hdr.flags & VFIO_USER_ERROR) {
509 ret = -msgp->hdr.error_reply;
510 } else {
511 ret = count;
512 }
513
514 g_free(msgp);
515 return ret;
516 }
517
518 /*
519 * Socket-based io_ops
520 */
521 VFIODeviceIOOps vfio_user_device_io_ops_sock = {
522 .device_feature = vfio_user_device_io_device_feature,
523 .get_region_info = vfio_user_device_io_get_region_info,
524 .get_irq_info = vfio_user_device_io_get_irq_info,
525 .set_irqs = vfio_user_device_io_set_irqs,
526 .region_read = vfio_user_device_io_region_read,
527 .region_write = vfio_user_device_io_region_write,
528
529 };