diff options
| -rw-r--r-- | arch/x86/kvm/lapic.c | 4 | ||||
| -rw-r--r-- | include/linux/kvm_host.h | 10 | ||||
| -rw-r--r-- | virt/kvm/irqchip.c | 5 | ||||
| -rw-r--r-- | virt/kvm/kvm_main.c | 6 |
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 | ||
| 514 | static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i) | 515 | static 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 | ||
| 601 | static inline struct kvm_memslots *__kvm_memslots(struct kvm *kvm, int as_id) | 602 | static 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); |
