mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-03 18:20:25 +02:00 
			
		
		
		
	KVM: fix spectrev1 gadgets
These were found with smatch, and then generalized when applicable. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									be43c440eb
								
							
						
					
					
						commit
						1d487e9bf8
					
				
					 4 changed files with 16 additions and 9 deletions
				
			
		| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue