aboutsummaryrefslogtreecommitdiff
path: root/hw/9pfs/virtio-9p-device.c
diff options
context:
space:
mode:
authorGreg Kurz <groug@kaod.org>2017-06-29 15:11:51 +0200
committerGreg Kurz <groug@kaod.org>2017-06-29 15:11:51 +0200
commit8d37de41cab145cbba250a8f1f1372b0a5cdf26f (patch)
tree2206cde2c48908eeffd1263b30def0eac85306cf /hw/9pfs/virtio-9p-device.c
parenta4d99854505ed63f5ea67fbfefb90316472cf158 (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.c40
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;