summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kvm/lapic.c4
-rw-r--r--include/linux/kvm_host.h10
-rw-r--r--virt/kvm/irqchip.c5
-rw-r--r--virt/kvm/kvm_main.c6
4 files changed, 16 insertions, 9 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 991fdf7fc17f..9bf70cf84564 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -138,6 +138,7 @@ static inline bool kvm_apic_map_get_logical_dest(struct kvm_apic_map *map,
138 if (offset <= max_apic_id) { 138 if (offset <= max_apic_id) {
139 u8 cluster_size = min(max_apic_id - offset + 1, 16U); 139 u8 cluster_size = min(max_apic_id - offset + 1, 16U);
140 140
141 offset = array_index_nospec(offset, map->max_apic_id + 1);
141 *cluster = &map->phys_map[offset]; 142 *cluster = &map->phys_map[offset];
142 *mask = dest_id & (0xffff >> (16 - cluster_size)); 143 *mask = dest_id & (0xffff >> (16 - cluster_size));
143 } else { 144 } else {
@@ -901,7 +902,8 @@ static inline bool kvm_apic_map_get_dest_lapic(struct kvm *kvm,
901 if (irq->dest_id > map->max_apic_id) { 902 if (irq->dest_id > map->max_apic_id) {
902 *bitmap = 0; 903 *bitmap = 0;
903 } else { 904 } else {
904 *dst = &map->phys_map[irq->dest_id]; 905 u32 dest_id = array_index_nospec(irq->dest_id, map->max_apic_id + 1);
906 *dst = &map->phys_map[dest_id];
905 *bitmap = 1; 907 *bitmap = 1;
906 } 908 }
907 return true; 909 return true;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 9d55c63db09b..640a03642766 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -28,6 +28,7 @@
28#include <linux/irqbypass.h> 28#include <linux/irqbypass.h>
29#include <linux/swait.h> 29#include <linux/swait.h>
30#include <linux/refcount.h> 30#include <linux/refcount.h>
31#include <linux/nospec.h>
31#include <asm/signal.h> 32#include <asm/signal.h>
32 33
33#include <linux/kvm.h> 34#include <linux/kvm.h>
@@ -513,10 +514,10 @@ static inline struct kvm_io_bus *kvm_get_bus(struct kvm *kvm, enum kvm_bus idx)
513 514
514static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i) 515static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
515{ 516{
516 /* Pairs with smp_wmb() in kvm_vm_ioctl_create_vcpu, in case 517 int num_vcpus = atomic_read(&kvm->online_vcpus);
517 * the caller has read kvm->online_vcpus before (as is the case 518 i = array_index_nospec(i, num_vcpus);
518 * for kvm_for_each_vcpu, for example). 519
519 */ 520 /* Pairs with smp_wmb() in kvm_vm_ioctl_create_vcpu. */
520 smp_rmb(); 521 smp_rmb();
521 return kvm->vcpus[i]; 522 return kvm->vcpus[i];
522} 523}
@@ -600,6 +601,7 @@ void kvm_put_kvm(struct kvm *kvm);
600 601
601static inline struct kvm_memslots *__kvm_memslots(struct kvm *kvm, int as_id) 602static inline struct kvm_memslots *__kvm_memslots(struct kvm *kvm, int as_id)
602{ 603{
604 as_id = array_index_nospec(as_id, KVM_ADDRESS_SPACE_NUM);
603 return srcu_dereference_check(kvm->memslots[as_id], &kvm->srcu, 605 return srcu_dereference_check(kvm->memslots[as_id], &kvm->srcu,
604 lockdep_is_held(&kvm->slots_lock) || 606 lockdep_is_held(&kvm->slots_lock) ||
605 !refcount_read(&kvm->users_count)); 607 !refcount_read(&kvm->users_count));
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
index 3547b0d8c91e..79e59e4fa3dc 100644
--- a/virt/kvm/irqchip.c
+++ b/virt/kvm/irqchip.c
@@ -144,18 +144,19 @@ static int setup_routing_entry(struct kvm *kvm,
144{ 144{
145 struct kvm_kernel_irq_routing_entry *ei; 145 struct kvm_kernel_irq_routing_entry *ei;
146 int r; 146 int r;
147 u32 gsi = array_index_nospec(ue->gsi, KVM_MAX_IRQ_ROUTES);
147 148
148 /* 149 /*
149 * Do not allow GSI to be mapped to the same irqchip more than once. 150 * Do not allow GSI to be mapped to the same irqchip more than once.
150 * Allow only one to one mapping between GSI and non-irqchip routing. 151 * Allow only one to one mapping between GSI and non-irqchip routing.
151 */ 152 */
152 hlist_for_each_entry(ei, &rt->map[ue->gsi], link) 153 hlist_for_each_entry(ei, &rt->map[gsi], link)
153 if (ei->type != KVM_IRQ_ROUTING_IRQCHIP || 154 if (ei->type != KVM_IRQ_ROUTING_IRQCHIP ||
154 ue->type != KVM_IRQ_ROUTING_IRQCHIP || 155 ue->type != KVM_IRQ_ROUTING_IRQCHIP ||
155 ue->u.irqchip.irqchip == ei->irqchip.irqchip) 156 ue->u.irqchip.irqchip == ei->irqchip.irqchip)
156 return -EINVAL; 157 return -EINVAL;
157 158
158 e->gsi = ue->gsi; 159 e->gsi = gsi;
159 e->type = ue->type; 160 e->type = ue->type;
160 r = kvm_set_routing_entry(kvm, e, ue); 161 r = kvm_set_routing_entry(kvm, e, ue);
161 if (r) 162 if (r)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 55fe8e20d8fd..dc8edc97ba85 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2977,12 +2977,14 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
2977 struct kvm_device_ops *ops = NULL; 2977 struct kvm_device_ops *ops = NULL;
2978 struct kvm_device *dev; 2978 struct kvm_device *dev;
2979 bool test = cd->flags & KVM_CREATE_DEVICE_TEST; 2979 bool test = cd->flags & KVM_CREATE_DEVICE_TEST;
2980 int type;
2980 int ret; 2981 int ret;
2981 2982
2982 if (cd->type >= ARRAY_SIZE(kvm_device_ops_table)) 2983 if (cd->type >= ARRAY_SIZE(kvm_device_ops_table))
2983 return -ENODEV; 2984 return -ENODEV;
2984 2985
2985 ops = kvm_device_ops_table[cd->type]; 2986 type = array_index_nospec(cd->type, ARRAY_SIZE(kvm_device_ops_table));
2987 ops = kvm_device_ops_table[type];
2986 if (ops == NULL) 2988 if (ops == NULL)
2987 return -ENODEV; 2989 return -ENODEV;
2988 2990
@@ -2997,7 +2999,7 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
2997 dev->kvm = kvm; 2999 dev->kvm = kvm;
2998 3000
2999 mutex_lock(&kvm->lock); 3001 mutex_lock(&kvm->lock);
3000 ret = ops->create(dev, cd->type); 3002 ret = ops->create(dev, type);
3001 if (ret < 0) { 3003 if (ret < 0) {
3002 mutex_unlock(&kvm->lock); 3004 mutex_unlock(&kvm->lock);
3003 kfree(dev); 3005 kfree(dev);