From 593fe05864a8e9e03a158c2785c663f1a096d25a Mon Sep 17 00:00:00 2001 From: Xiao Wang Date: Tue, 7 Jul 2015 09:18:30 +0200 Subject: [PATCH 056/100] virtio: disallow late feature changes for virtio-1 Message-id: <1436260751-25015-28-git-send-email-jasowang@redhat.com> Patchwork-id: 66802 O-Subject: [RHEL7.2 qemu-kvm-rhev PATCH V2 27/68] virtio: disallow late feature changes for virtio-1 Bugzilla: 1227343 RH-Acked-by: Michael S. Tsirkin RH-Acked-by: David Gibson RH-Acked-by: Laurent Vivier RH-Acked-by: Thomas Huth From: Cornelia Huck For virtio-1 devices, the driver must not attempt to set feature bits after it set FEATURES_OK in the device status. Simply reject it in that case. Signed-off-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin (cherry picked from commit 6c0196d702e8482a17638ee79f45ce27cdd1ef5d) Signed-off-by: Miroslav Rezanina --- hw/virtio/virtio.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index c27e975..3367100 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -1021,7 +1021,7 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) vmstate_save_state(f, &vmstate_virtio, vdev, NULL); } -int virtio_set_features(VirtIODevice *vdev, uint64_t val) +static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val) { VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); bool bad = (val & ~(vdev->host_features)) != 0; @@ -1034,6 +1034,18 @@ int virtio_set_features(VirtIODevice *vdev, uint64_t val) return bad ? -1 : 0; } +int virtio_set_features(VirtIODevice *vdev, uint64_t val) +{ + /* + * The driver must not attempt to set features after feature negotiation + * has finished. + */ + if (vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) { + return -EINVAL; + } + return virtio_set_features_nocheck(vdev, val); +} + int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) { int i, ret; @@ -1137,14 +1149,14 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) * host_features. */ uint64_t features64 = vdev->guest_features; - if (virtio_set_features(vdev, features64) < 0) { + if (virtio_set_features_nocheck(vdev, features64) < 0) { error_report("Features 0x%" PRIx64 " unsupported. " "Allowed features: 0x%" PRIx64, features64, vdev->host_features); return -1; } } else { - if (virtio_set_features(vdev, features) < 0) { + if (virtio_set_features_nocheck(vdev, features) < 0) { error_report("Features 0x%x unsupported. " "Allowed features: 0x%" PRIx64, features, vdev->host_features); -- 1.8.3.1