Juergen Gross b8ac5b
Patch-mainline: v5.1-rc6
Juergen Gross b8ac5b
Git-commit: 1d487e9bf8ba66a7174c56a0029c54b1eca8f99c
Juergen Gross b8ac5b
From: Paolo Bonzini <pbonzini@redhat.com>
Juergen Gross b8ac5b
Date: Thu, 11 Apr 2019 11:16:47 +0200
Juergen Gross b8ac5b
Subject: [PATCH] KVM: fix spectrev1 gadgets
Juergen Gross b8ac5b
References: bsc#1164705
Juergen Gross b8ac5b
Juergen Gross b8ac5b
These were found with smatch, and then generalized when applicable.
Juergen Gross b8ac5b
Juergen Gross b8ac5b
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Juergen Gross b8ac5b
Signed-off-by: Juergen Gross <jgross@suse.com>
Juergen Gross b8ac5b
---
Juergen Gross b8ac5b
 arch/x86/kvm/lapic.c     |  4 +++-
Juergen Gross b8ac5b
 include/linux/kvm_host.h | 10 ++++++----
Juergen Gross b8ac5b
 virt/kvm/irqchip.c       |  5 +++--
Juergen Gross b8ac5b
 virt/kvm/kvm_main.c      |  6 ++++--
Juergen Gross b8ac5b
 4 files changed, 16 insertions(+), 9 deletions(-)
Juergen Gross b8ac5b
Juergen Gross b8ac5b
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
Juergen Gross b8ac5b
index 991fdf7fc17f..9bf70cf84564 100644
Juergen Gross b8ac5b
--- a/arch/x86/kvm/lapic.c
Juergen Gross b8ac5b
+++ b/arch/x86/kvm/lapic.c
Juergen Gross b8ac5b
@@ -133,6 +133,7 @@ static inline bool kvm_apic_map_get_logical_dest(struct kvm_apic_map *map,
Juergen Gross b8ac5b
 		if (offset <= max_apic_id) {
Juergen Gross b8ac5b
 			u8 cluster_size = min(max_apic_id - offset + 1, 16U);
Juergen Gross b8ac5b
 
Juergen Gross b8ac5b
+			offset = array_index_nospec(offset, map->max_apic_id + 1);
Juergen Gross b8ac5b
 			*cluster = &map->phys_map[offset];
Juergen Gross b8ac5b
 			*mask = dest_id & (0xffff >> (16 - cluster_size));
Juergen Gross b8ac5b
 		} else {
Juergen Gross b8ac5b
@@ -838,7 +839,8 @@ static inline bool kvm_apic_map_get_dest_lapic(struct kvm *kvm,
Juergen Gross b8ac5b
 		if (irq->dest_id > map->max_apic_id) {
Juergen Gross b8ac5b
 			*bitmap = 0;
Juergen Gross b8ac5b
 		} else {
Juergen Gross b8ac5b
-			*dst = &map->phys_map[irq->dest_id];
Juergen Gross b8ac5b
+			u32 dest_id = array_index_nospec(irq->dest_id, map->max_apic_id + 1);
Juergen Gross b8ac5b
+			*dst = &map->phys_map[dest_id];
Juergen Gross b8ac5b
 			*bitmap = 1;
Juergen Gross b8ac5b
 		}
Juergen Gross b8ac5b
 		return true;
Juergen Gross b8ac5b
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
Juergen Gross b8ac5b
index 9d55c63db09b..640a03642766 100644
Juergen Gross b8ac5b
--- a/include/linux/kvm_host.h
Juergen Gross b8ac5b
+++ b/include/linux/kvm_host.h
Juergen Gross b8ac5b
@@ -28,6 +28,7 @@
Juergen Gross b8ac5b
 #include <linux/irqbypass.h>
Juergen Gross b8ac5b
 #include <linux/swait.h>
Juergen Gross b8ac5b
 #include <linux/refcount.h>
Juergen Gross b8ac5b
+#include <linux/nospec.h>
Juergen Gross b8ac5b
 #include <asm/signal.h>
Juergen Gross b8ac5b
 
Juergen Gross b8ac5b
 #include <linux/kvm.h>
Juergen Gross b8ac5b
@@ -484,10 +485,10 @@ static inline struct kvm_io_bus *kvm_get_bus(struct kvm *kvm, enum kvm_bus idx)
Juergen Gross b8ac5b
 
Juergen Gross b8ac5b
 static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
Juergen Gross b8ac5b
 {
Juergen Gross b8ac5b
-	/* Pairs with smp_wmb() in kvm_vm_ioctl_create_vcpu, in case
Juergen Gross b8ac5b
-	 * the caller has read kvm->online_vcpus before (as is the case
Juergen Gross b8ac5b
-	 * for kvm_for_each_vcpu, for example).
Juergen Gross b8ac5b
-	 */
Juergen Gross b8ac5b
+	int num_vcpus = atomic_read(&kvm->online_vcpus);
Juergen Gross b8ac5b
+	i = array_index_nospec(i, num_vcpus);
Juergen Gross b8ac5b
+
Juergen Gross b8ac5b
+	/* Pairs with smp_wmb() in kvm_vm_ioctl_create_vcpu.  */
Juergen Gross b8ac5b
 	smp_rmb();
Juergen Gross b8ac5b
 	return kvm->vcpus[i];
Juergen Gross b8ac5b
 }
Juergen Gross b8ac5b
@@ -571,6 +572,7 @@ void kvm_put_kvm(struct kvm *kvm);
Juergen Gross b8ac5b
 
Juergen Gross b8ac5b
 static inline struct kvm_memslots *__kvm_memslots(struct kvm *kvm, int as_id)
Juergen Gross b8ac5b
 {
Juergen Gross b8ac5b
+	as_id = array_index_nospec(as_id, KVM_ADDRESS_SPACE_NUM);
Juergen Gross b8ac5b
 	return srcu_dereference_check(kvm->memslots[as_id], &kvm->srcu,
Juergen Gross b8ac5b
 			lockdep_is_held(&kvm->slots_lock) ||
Juergen Gross b8ac5b
 			!refcount_read(&kvm->users_count));
Juergen Gross b8ac5b
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
Juergen Gross b8ac5b
index 3547b0d8c91e..79e59e4fa3dc 100644
Juergen Gross b8ac5b
--- a/virt/kvm/irqchip.c
Juergen Gross b8ac5b
+++ b/virt/kvm/irqchip.c
Juergen Gross b8ac5b
@@ -144,18 +144,19 @@ static int setup_routing_entry(struct kvm *kvm,
Juergen Gross b8ac5b
 {
Juergen Gross b8ac5b
 	struct kvm_kernel_irq_routing_entry *ei;
Juergen Gross b8ac5b
 	int r;
Juergen Gross b8ac5b
+	u32 gsi = array_index_nospec(ue->gsi, KVM_MAX_IRQ_ROUTES);
Juergen Gross b8ac5b
 
Juergen Gross b8ac5b
 	/*
Juergen Gross b8ac5b
 	 * Do not allow GSI to be mapped to the same irqchip more than once.
Juergen Gross b8ac5b
 	 * Allow only one to one mapping between GSI and non-irqchip routing.
Juergen Gross b8ac5b
 	 */
Juergen Gross b8ac5b
-	hlist_for_each_entry(ei, &rt->map[ue->gsi], link)
Juergen Gross b8ac5b
+	hlist_for_each_entry(ei, &rt->map[gsi], link)
Juergen Gross b8ac5b
 		if (ei->type != KVM_IRQ_ROUTING_IRQCHIP ||
Juergen Gross b8ac5b
 		    ue->type != KVM_IRQ_ROUTING_IRQCHIP ||
Juergen Gross b8ac5b
 		    ue->u.irqchip.irqchip == ei->irqchip.irqchip)
Juergen Gross b8ac5b
 			return -EINVAL;
Juergen Gross b8ac5b
 
Juergen Gross b8ac5b
-	e->gsi = ue->gsi;
Juergen Gross b8ac5b
+	e->gsi = gsi;
Juergen Gross b8ac5b
 	e->type = ue->type;
Juergen Gross b8ac5b
 	r = kvm_set_routing_entry(kvm, e, ue);
Juergen Gross b8ac5b
 	if (r)
Juergen Gross b8ac5b
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
Juergen Gross b8ac5b
index 55fe8e20d8fd..dc8edc97ba85 100644
Juergen Gross b8ac5b
--- a/virt/kvm/kvm_main.c
Juergen Gross b8ac5b
+++ b/virt/kvm/kvm_main.c
Juergen Gross b8ac5b
@@ -2982,12 +2982,14 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
Juergen Gross b8ac5b
 	struct kvm_device_ops *ops = NULL;
Juergen Gross b8ac5b
 	struct kvm_device *dev;
Juergen Gross b8ac5b
 	bool test = cd->flags & KVM_CREATE_DEVICE_TEST;
Juergen Gross b8ac5b
+	int type;
Juergen Gross b8ac5b
 	int ret;
Juergen Gross b8ac5b
 
Juergen Gross b8ac5b
 	if (cd->type >= ARRAY_SIZE(kvm_device_ops_table))
Juergen Gross b8ac5b
 		return -ENODEV;
Juergen Gross b8ac5b
 
Juergen Gross b8ac5b
-	ops = kvm_device_ops_table[cd->type];
Juergen Gross b8ac5b
+	type = array_index_nospec(cd->type, ARRAY_SIZE(kvm_device_ops_table));
Juergen Gross b8ac5b
+	ops = kvm_device_ops_table[type];
Juergen Gross b8ac5b
 	if (ops == NULL)
Juergen Gross b8ac5b
 		return -ENODEV;
Juergen Gross b8ac5b
 
Juergen Gross b8ac5b
@@ -3002,7 +3004,7 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
Juergen Gross b8ac5b
 	dev->kvm = kvm;
Juergen Gross b8ac5b
 
Juergen Gross b8ac5b
 	mutex_lock(&kvm->lock);
Juergen Gross b8ac5b
-	ret = ops->create(dev, cd->type);
Juergen Gross b8ac5b
+	ret = ops->create(dev, type);
Juergen Gross b8ac5b
 	if (ret < 0) {
Juergen Gross b8ac5b
 		mutex_unlock(&kvm->lock);
Juergen Gross b8ac5b
 		kfree(dev);
Juergen Gross b8ac5b
-- 
Juergen Gross b8ac5b
2.16.4
Juergen Gross b8ac5b