]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools: Prevent PFN wraparound
authorSasha Levin <levinsasha928@gmail.com>
Wed, 11 May 2011 15:17:24 +0000 (18:17 +0300)
committerPekka Enberg <penberg@kernel.org>
Wed, 11 May 2011 15:51:15 +0000 (18:51 +0300)
queue->pfn may be used to point at addresses larger
than 32 bit.
Prevent a wraparound when shifting it left.

Acked-and-tested-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/include/kvm/virtio.h
tools/kvm/virtio/blk.c
tools/kvm/virtio/console.c
tools/kvm/virtio/net.c
tools/kvm/virtio/rng.c

index 7f92dead43b46d002a9ab70a687b45867860b058..bea63df9035376a08254fc4357b42e8acc46f291 100644 (file)
@@ -36,6 +36,16 @@ static inline bool virt_queue__available(struct virt_queue *vq)
        return vq->vring.avail->idx !=  vq->last_avail_idx;
 }
 
+/*
+ * Warning: on 32-bit hosts, shifting pfn left may cause a truncation of pfn values
+ * higher than 4GB - thus, pointing to the wrong area in guest virtual memory space
+ * and breaking the virt queue which owns this pfn.
+ */
+static inline void *guest_pfn_to_host(struct kvm *kvm, u32 pfn)
+{
+       return guest_flat_to_host(kvm, (unsigned long)pfn << 12);
+}
+
 struct vring_used_elem *virt_queue__set_used_elem(struct virt_queue *queue, u32 head, u32 len);
 
 u16 virt_queue__get_iov(struct virt_queue *queue, struct iovec iov[], u16 *out, u16 *in, struct kvm *kvm);
index 12c70291673dc346df16e96570f02180ef7cd706..9f1aa1dfce22a3dd4ffee620c5b6f109064311c6 100644 (file)
@@ -197,7 +197,7 @@ static bool virtio_blk_pci_io_out(struct kvm *self, u16 port, void *data, int si
 
                queue                   = &bdev->vqs[bdev->queue_selector];
                queue->pfn              = ioport__read32(data);
-               p                       = guest_flat_to_host(self, queue->pfn << 12);
+               p                       = guest_pfn_to_host(self, queue->pfn);
 
                vring_init(&queue->vring, VIRTIO_BLK_QUEUE_SIZE, p, 4096);
 
index f9031cbd88a38cba0db0b454820f8d73092adcec..87b816af0960c66f75b842dca5c67590bf8e732f 100644 (file)
@@ -199,7 +199,7 @@ static bool virtio_console_pci_io_out(struct kvm *self, u16 port, void *data, in
 
                queue                   = &cdev.vqs[cdev.queue_selector];
                queue->pfn              = ioport__read32(data);
-               p                       = guest_flat_to_host(self, queue->pfn << 12);
+               p                       = guest_pfn_to_host(self, queue->pfn);
 
                vring_init(&queue->vring, VIRTIO_CONSOLE_QUEUE_SIZE, p, 4096);
 
index 8d430e388c3fc56e59a0d0cf18f162f812d23db2..3f3ee22734f88b0644203febb4abe1b95003580d 100644 (file)
@@ -245,7 +245,7 @@ static bool virtio_net_pci_io_out(struct kvm *self, u16 port, void *data, int si
 
                queue                           = &net_device.vqs[net_device.queue_selector];
                queue->pfn                      = ioport__read32(data);
-               p                               = guest_flat_to_host(self, queue->pfn << 12);
+               p                               = guest_pfn_to_host(self, queue->pfn);
 
                vring_init(&queue->vring, VIRTIO_NET_QUEUE_SIZE, p, 4096);
 
index f692dfd692ece255687f1343b73c58b3e0714543..1951d0d1c3702bb0532a626e6699744a7f92b75e 100644 (file)
@@ -129,7 +129,7 @@ static bool virtio_rng_pci_io_out(struct kvm *kvm, u16 port, void *data, int siz
 
                queue                   = &rdev.vqs[rdev.queue_selector];
                queue->pfn              = ioport__read32(data);
-               p                       = guest_flat_to_host(kvm, queue->pfn << 12);
+               p                       = guest_pfn_to_host(kvm, queue->pfn);
 
                vring_init(&queue->vring, VIRTIO_RNG_QUEUE_SIZE, p, 4096);