diff options
author | Greg Kurz <groug@kaod.org> | 2017-06-29 15:11:51 +0200 |
---|---|---|
committer | Greg Kurz <groug@kaod.org> | 2017-06-29 15:11:51 +0200 |
commit | 8d37de41cab145cbba250a8f1f1372b0a5cdf26f (patch) | |
tree | 2206cde2c48908eeffd1263b30def0eac85306cf /hw/9pfs/virtio-9p-device.c | |
parent | a4d99854505ed63f5ea67fbfefb90316472cf158 (diff) |
virtio-9p: break device if buffers are misconfigured
The 9P protocol is transport agnostic: if the guest misconfigured the
buffers, the best we can do is to set the broken flag on the device.
Signed-off-by: Greg Kurz <groug@kaod.org>
Diffstat (limited to 'hw/9pfs/virtio-9p-device.c')
-rw-r--r-- | hw/9pfs/virtio-9p-device.c | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index 1a68c1622d..62650b0a6b 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -146,8 +146,16 @@ static ssize_t virtio_pdu_vmarshal(V9fsPDU *pdu, size_t offset, V9fsState *s = pdu->s; V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); VirtQueueElement *elem = v->elems[pdu->idx]; + ssize_t ret; - return v9fs_iov_vmarshal(elem->in_sg, elem->in_num, offset, 1, fmt, ap); + ret = v9fs_iov_vmarshal(elem->in_sg, elem->in_num, offset, 1, fmt, ap); + if (ret < 0) { + VirtIODevice *vdev = VIRTIO_DEVICE(v); + + virtio_error(vdev, "Failed to encode VirtFS reply type %d", + pdu->id + 1); + } + return ret; } static ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset, @@ -156,28 +164,52 @@ static ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset, V9fsState *s = pdu->s; V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); VirtQueueElement *elem = v->elems[pdu->idx]; + ssize_t ret; + + ret = v9fs_iov_vunmarshal(elem->out_sg, elem->out_num, offset, 1, fmt, ap); + if (ret < 0) { + VirtIODevice *vdev = VIRTIO_DEVICE(v); - return v9fs_iov_vunmarshal(elem->out_sg, elem->out_num, offset, 1, fmt, ap); + virtio_error(vdev, "Failed to decode VirtFS request type %d", pdu->id); + } + return ret; } -/* The size parameter is used by other transports. Do not drop it. */ static void virtio_init_in_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov, unsigned int *pniov, size_t size) { V9fsState *s = pdu->s; V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); VirtQueueElement *elem = v->elems[pdu->idx]; + size_t buf_size = iov_size(elem->in_sg, elem->in_num); + + if (buf_size < size) { + VirtIODevice *vdev = VIRTIO_DEVICE(v); + + virtio_error(vdev, + "VirtFS reply type %d needs %zu bytes, buffer has %zu", + pdu->id + 1, size, buf_size); + } *piov = elem->in_sg; *pniov = elem->in_num; } static void virtio_init_out_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov, - unsigned int *pniov) + unsigned int *pniov, size_t size) { V9fsState *s = pdu->s; V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); VirtQueueElement *elem = v->elems[pdu->idx]; + size_t buf_size = iov_size(elem->out_sg, elem->out_num); + + if (buf_size < size) { + VirtIODevice *vdev = VIRTIO_DEVICE(v); + + virtio_error(vdev, + "VirtFS request type %d needs %zu bytes, buffer has %zu", + pdu->id, size, buf_size); + } *piov = elem->out_sg; *pniov = elem->out_num; |