| From c622a3c21ede892e370b56e1ceb9eb28f8bbda6b Mon Sep 17 00:00:00 2001 |
| From: Paolo Bonzini <pbonzini@redhat.com> |
| Date: Wed, 1 Jun 2016 14:09:21 +0200 |
| Subject: KVM: irqfd: fix NULL pointer dereference in kvm_irq_map_gsi |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Paolo Bonzini <pbonzini@redhat.com> |
| |
| commit c622a3c21ede892e370b56e1ceb9eb28f8bbda6b upstream. |
| |
| Found by syzkaller: |
| |
| BUG: unable to handle kernel NULL pointer dereference at 0000000000000120 |
| IP: [<ffffffffa0797202>] kvm_irq_map_gsi+0x12/0x90 [kvm] |
| PGD 6f80b067 PUD b6535067 PMD 0 |
| Oops: 0000 [#1] SMP |
| CPU: 3 PID: 4988 Comm: a.out Not tainted 4.4.9-300.fc23.x86_64 #1 |
| [...] |
| Call Trace: |
| [<ffffffffa0795f62>] irqfd_update+0x32/0xc0 [kvm] |
| [<ffffffffa0796c7c>] kvm_irqfd+0x3dc/0x5b0 [kvm] |
| [<ffffffffa07943f4>] kvm_vm_ioctl+0x164/0x6f0 [kvm] |
| [<ffffffff81241648>] do_vfs_ioctl+0x298/0x480 |
| [<ffffffff812418a9>] SyS_ioctl+0x79/0x90 |
| [<ffffffff817a1062>] tracesys_phase2+0x84/0x89 |
| Code: b5 71 a7 e0 5b 41 5c 41 5d 5d f3 c3 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 55 48 8b 8f 10 2e 00 00 31 c0 48 89 e5 <39> 91 20 01 00 00 76 6a 48 63 d2 48 8b 94 d1 28 01 00 00 48 85 |
| RIP [<ffffffffa0797202>] kvm_irq_map_gsi+0x12/0x90 [kvm] |
| RSP <ffff8800926cbca8> |
| CR2: 0000000000000120 |
| |
| Testcase: |
| |
| #include <unistd.h> |
| #include <sys/syscall.h> |
| #include <string.h> |
| #include <stdint.h> |
| #include <linux/kvm.h> |
| #include <fcntl.h> |
| #include <sys/ioctl.h> |
| |
| long r[26]; |
| |
| int main() |
| { |
| memset(r, -1, sizeof(r)); |
| r[2] = open("/dev/kvm", 0); |
| r[3] = ioctl(r[2], KVM_CREATE_VM, 0); |
| |
| struct kvm_irqfd ifd; |
| ifd.fd = syscall(SYS_eventfd2, 5, 0); |
| ifd.gsi = 3; |
| ifd.flags = 2; |
| ifd.resamplefd = ifd.fd; |
| r[25] = ioctl(r[3], KVM_IRQFD, &ifd); |
| return 0; |
| } |
| |
| Reported-by: Dmitry Vyukov <dvyukov@google.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Radim Krčmář <rkrcmar@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| virt/kvm/irqchip.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/virt/kvm/irqchip.c |
| +++ b/virt/kvm/irqchip.c |
| @@ -40,7 +40,7 @@ int kvm_irq_map_gsi(struct kvm *kvm, |
| |
| irq_rt = srcu_dereference_check(kvm->irq_routing, &kvm->irq_srcu, |
| lockdep_is_held(&kvm->irq_lock)); |
| - if (gsi < irq_rt->nr_rt_entries) { |
| + if (irq_rt && gsi < irq_rt->nr_rt_entries) { |
| hlist_for_each_entry(e, &irq_rt->map[gsi], link) { |
| entries[n] = *e; |
| ++n; |