Re: [bug report] KVM: X86: Implement "send IPI" hypercall

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




> On 28 Aug 2018, at 16:28, Dan Carpenter <dan.carpenter@xxxxxxxxxx> wrote:
> 
> Hello Wanpeng Li,
> 
> The patch 4180bf1b655a: "KVM: X86: Implement "send IPI" hypercall"
> from Jul 23, 2018, leads to the following static checker warning:
> 
> 	arch/x86/kvm/lapic.c:576 kvm_pv_send_ipi()
> 	error: buffer underflow 'map->phys_map' 's32min-s32max'
> 
> arch/x86/kvm/lapic.c
>   550  int kvm_pv_send_ipi(struct kvm *kvm, unsigned long ipi_bitmap_low,
>   551                      unsigned long ipi_bitmap_high, int min,
>   552                      unsigned long icr, int op_64_bit)
>   553  {
>   554          int i;
>   555          struct kvm_apic_map *map;
>   556          struct kvm_vcpu *vcpu;
>   557          struct kvm_lapic_irq irq = {0};
>   558          int cluster_size = op_64_bit ? 64 : 32;
>   559          int count = 0;
>   560  
>   561          irq.vector = icr & APIC_VECTOR_MASK;
>   562          irq.delivery_mode = icr & APIC_MODE_MASK;
>   563          irq.level = (icr & APIC_INT_ASSERT) != 0;
>   564          irq.trig_mode = icr & APIC_INT_LEVELTRIG;
>   565  
>   566          if (icr & APIC_DEST_MASK)
>   567                  return -KVM_EINVAL;
>   568          if (icr & APIC_SHORT_MASK)
>   569                  return -KVM_EINVAL;
>   570  
>   571          rcu_read_lock();
>   572          map = rcu_dereference(kvm->arch.apic_map);
>   573  
>   574          /* Bits above cluster_size are masked in the caller.  */
>   575          for_each_set_bit(i, &ipi_bitmap_low, BITS_PER_LONG) {
>   576                  vcpu = map->phys_map[min + i]->vcpu;
>                                             ^^^^^^^
>   577                  count += kvm_apic_set_irq(vcpu, &irq, NULL);
>   578          }
>   579  
>   580          min += cluster_size;
>   581          for_each_set_bit(i, &ipi_bitmap_high, BITS_PER_LONG) {
>   582                  vcpu = map->phys_map[min + i]->vcpu;
>                                             ^^^^^^^
> The truth is that I don't understand KVM very well so I'm just reporting
> these warning in the hope that someone will explain things to me.  This
> is called from kvm_emulate_hypercall().  Recently we marked the return
> from kvm_register_read() as untrusted data.  Now Smatch thinks that
> "min" is totally untrusted and there are no boundary checks.
> 
> Btw the reason Smatch only warns about a buffer underflow instead of a
> buffer overflow is because it doesn't know the size of map->phys_map[].
> 
> When can kvm_register_read() be trusted?
> 
>   583                  count += kvm_apic_set_irq(vcpu, &irq, NULL);
>   584          }
>   585  
>   586          rcu_read_unlock();
>   587          return count;
>   588  }
> 
> regards,
> dan carpenter

Thanks Dan.
It seems to be a real issue.

KVM guest can easily trigger this by executing the following assembly sequence in Ring0:
mov $10, %rax
mov $0xFFFFFFFF, %rbx
mov $0xFFFFFFFF, %rdx
mov $0, %rsi
vmcall

As this will cause KVM to execute the following code-path:
vmx_handle_exit() -> handle_vmcall() -> kvm_emulate_hypercall() -> kvm_pv_send_ipi()
which will reach out-of-bounds access.

We should add a check to kvm_pv_send_ipi() against map->max_apic_id.

-Liran






[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux