1
0
Fork 0

KVM: fix spectrev1 gadgets

These were found with smatch, and then generalized when applicable.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
hifive-unleashed-5.1
Paolo Bonzini 2019-04-11 11:16:47 +02:00
parent be43c440eb
commit 1d487e9bf8
4 changed files with 16 additions and 9 deletions

View File

@ -138,6 +138,7 @@ static inline bool kvm_apic_map_get_logical_dest(struct kvm_apic_map *map,
if (offset <= max_apic_id) { if (offset <= max_apic_id) {
u8 cluster_size = min(max_apic_id - offset + 1, 16U); u8 cluster_size = min(max_apic_id - offset + 1, 16U);
offset = array_index_nospec(offset, map->max_apic_id + 1);
*cluster = &map->phys_map[offset]; *cluster = &map->phys_map[offset];
*mask = dest_id & (0xffff >> (16 - cluster_size)); *mask = dest_id & (0xffff >> (16 - cluster_size));
} else { } else {
@ -901,7 +902,8 @@ static inline bool kvm_apic_map_get_dest_lapic(struct kvm *kvm,
if (irq->dest_id > map->max_apic_id) { if (irq->dest_id > map->max_apic_id) {
*bitmap = 0; *bitmap = 0;
} else { } else {
*dst = &map->phys_map[irq->dest_id]; u32 dest_id = array_index_nospec(irq->dest_id, map->max_apic_id + 1);
*dst = &map->phys_map[dest_id];
*bitmap = 1; *bitmap = 1;
} }
return true; return true;

View File

@ -28,6 +28,7 @@
#include <linux/irqbypass.h> #include <linux/irqbypass.h>
#include <linux/swait.h> #include <linux/swait.h>
#include <linux/refcount.h> #include <linux/refcount.h>
#include <linux/nospec.h>
#include <asm/signal.h> #include <asm/signal.h>
#include <linux/kvm.h> #include <linux/kvm.h>
@ -513,10 +514,10 @@ static inline struct kvm_io_bus *kvm_get_bus(struct kvm *kvm, enum kvm_bus idx)
static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i) static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
{ {
/* Pairs with smp_wmb() in kvm_vm_ioctl_create_vcpu, in case int num_vcpus = atomic_read(&kvm->online_vcpus);
* the caller has read kvm->online_vcpus before (as is the case i = array_index_nospec(i, num_vcpus);
* for kvm_for_each_vcpu, for example).
*/ /* Pairs with smp_wmb() in kvm_vm_ioctl_create_vcpu. */
smp_rmb(); smp_rmb();
return kvm->vcpus[i]; return kvm->vcpus[i];
} }
@ -600,6 +601,7 @@ void kvm_put_kvm(struct kvm *kvm);
static inline struct kvm_memslots *__kvm_memslots(struct kvm *kvm, int as_id) static inline struct kvm_memslots *__kvm_memslots(struct kvm *kvm, int as_id)
{ {
as_id = array_index_nospec(as_id, KVM_ADDRESS_SPACE_NUM);
return srcu_dereference_check(kvm->memslots[as_id], &kvm->srcu, return srcu_dereference_check(kvm->memslots[as_id], &kvm->srcu,
lockdep_is_held(&kvm->slots_lock) || lockdep_is_held(&kvm->slots_lock) ||
!refcount_read(&kvm->users_count)); !refcount_read(&kvm->users_count));

View File

@ -144,18 +144,19 @@ static int setup_routing_entry(struct kvm *kvm,
{ {
struct kvm_kernel_irq_routing_entry *ei; struct kvm_kernel_irq_routing_entry *ei;
int r; int r;
u32 gsi = array_index_nospec(ue->gsi, KVM_MAX_IRQ_ROUTES);
/* /*
* Do not allow GSI to be mapped to the same irqchip more than once. * Do not allow GSI to be mapped to the same irqchip more than once.
* Allow only one to one mapping between GSI and non-irqchip routing. * Allow only one to one mapping between GSI and non-irqchip routing.
*/ */
hlist_for_each_entry(ei, &rt->map[ue->gsi], link) hlist_for_each_entry(ei, &rt->map[gsi], link)
if (ei->type != KVM_IRQ_ROUTING_IRQCHIP || if (ei->type != KVM_IRQ_ROUTING_IRQCHIP ||
ue->type != KVM_IRQ_ROUTING_IRQCHIP || ue->type != KVM_IRQ_ROUTING_IRQCHIP ||
ue->u.irqchip.irqchip == ei->irqchip.irqchip) ue->u.irqchip.irqchip == ei->irqchip.irqchip)
return -EINVAL; return -EINVAL;
e->gsi = ue->gsi; e->gsi = gsi;
e->type = ue->type; e->type = ue->type;
r = kvm_set_routing_entry(kvm, e, ue); r = kvm_set_routing_entry(kvm, e, ue);
if (r) if (r)

View File

@ -2977,12 +2977,14 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
struct kvm_device_ops *ops = NULL; struct kvm_device_ops *ops = NULL;
struct kvm_device *dev; struct kvm_device *dev;
bool test = cd->flags & KVM_CREATE_DEVICE_TEST; bool test = cd->flags & KVM_CREATE_DEVICE_TEST;
int type;
int ret; int ret;
if (cd->type >= ARRAY_SIZE(kvm_device_ops_table)) if (cd->type >= ARRAY_SIZE(kvm_device_ops_table))
return -ENODEV; return -ENODEV;
ops = kvm_device_ops_table[cd->type]; type = array_index_nospec(cd->type, ARRAY_SIZE(kvm_device_ops_table));
ops = kvm_device_ops_table[type];
if (ops == NULL) if (ops == NULL)
return -ENODEV; return -ENODEV;
@ -2997,7 +2999,7 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
dev->kvm = kvm; dev->kvm = kvm;
mutex_lock(&kvm->lock); mutex_lock(&kvm->lock);
ret = ops->create(dev, cd->type); ret = ops->create(dev, type);
if (ret < 0) { if (ret < 0) {
mutex_unlock(&kvm->lock); mutex_unlock(&kvm->lock);
kfree(dev); kfree(dev);