mirror of
https://github.com/xemu-project/xemu.git
synced 2025-02-19 11:41:32 +00:00
virtio-9p: handle handle_9p_output() error
A broken guest may send a request without providing buffers for the reply or for the request itself, and virtqueue_pop() will return an element with either in_num == 0 or out_num == 0. All 9P requests are expected to start with the following 7-byte header: uint32_t size_le; uint8_t id; uint16_t tag_le; If iov_to_buf() fails to return these 7 bytes, then something is wrong in the guest. In both cases, it is wrong to crash QEMU, since the root cause lies in the guest. This patch hence does the following: - keep the check of in_num since pdu_complete() assumes it has enough space to store the reply and we will send something broken to the guest - let iov_to_buf() handle out_num == 0, since it will return 0 just like if the guest had provided an zero-sized buffer. - call virtio_error() to inform the guest that the device is now broken, instead of aborting - detach the request from the virtqueue and free it Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
d14dde5ec7
commit
d3d74d6fe0
@ -41,6 +41,7 @@ static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
V9fsState *s = &v->state;
|
||||
V9fsPDU *pdu;
|
||||
ssize_t len;
|
||||
VirtQueueElement *elem;
|
||||
|
||||
while ((pdu = pdu_alloc(s))) {
|
||||
struct {
|
||||
@ -48,21 +49,28 @@ static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
uint8_t id;
|
||||
uint16_t tag_le;
|
||||
} QEMU_PACKED out;
|
||||
VirtQueueElement *elem;
|
||||
|
||||
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
||||
if (!elem) {
|
||||
pdu_free(pdu);
|
||||
break;
|
||||
goto out_free_pdu;
|
||||
}
|
||||
|
||||
BUG_ON(elem->out_num == 0 || elem->in_num == 0);
|
||||
if (elem->in_num == 0) {
|
||||
virtio_error(vdev,
|
||||
"The guest sent a VirtFS request without space for "
|
||||
"the reply");
|
||||
goto out_free_req;
|
||||
}
|
||||
QEMU_BUILD_BUG_ON(sizeof(out) != 7);
|
||||
|
||||
v->elems[pdu->idx] = elem;
|
||||
len = iov_to_buf(elem->out_sg, elem->out_num, 0,
|
||||
&out, sizeof(out));
|
||||
BUG_ON(len != sizeof(out));
|
||||
if (len != sizeof(out)) {
|
||||
virtio_error(vdev, "The guest sent a malformed VirtFS request: "
|
||||
"header size is %zd, should be 7", len);
|
||||
goto out_free_req;
|
||||
}
|
||||
|
||||
pdu->size = le32_to_cpu(out.size_le);
|
||||
|
||||
@ -72,6 +80,14 @@ static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
qemu_co_queue_init(&pdu->complete);
|
||||
pdu_submit(pdu);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
out_free_req:
|
||||
virtqueue_detach_element(vq, elem, 0);
|
||||
g_free(elem);
|
||||
out_free_pdu:
|
||||
pdu_free(pdu);
|
||||
}
|
||||
|
||||
static uint64_t virtio_9p_get_features(VirtIODevice *vdev, uint64_t features,
|
||||
|
Loading…
x
Reference in New Issue
Block a user