kvm: NULL deref in vcpu_enter_guest

From: Dmitry Vyukov
Date: Thu Dec 29 2016 - 12:50:24 EST


Hello,

The following program triggers NULL deref in vcpu_enter_guest:

BUG: unable to handle kernel NULL pointer dereference at 00000000000001b0
IP: atomic_cmpxchg arch/x86/include/asm/atomic.h:186 [inline]
IP: queued_spin_lock include/asm-generic/qspinlock.h:100 [inline]
IP: do_raw_spin_lock include/linux/spinlock.h:148 [inline]
IP: __raw_spin_lock include/linux/spinlock_api_smp.h:145 [inline]
IP: _raw_spin_lock+0x7/0x20 kernel/locking/spinlock.c:151
PGD 7db45067
PUD 7db44067
PMD 0
Oops: 0002 [#1] SMP
Modules linked in:
CPU: 3 PID: 2747 Comm: a.out Not tainted 4.10.0-rc1+ #55
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
task: ffff88003df0b640 task.stack: ffffc900024e0000
RIP: 0010:atomic_cmpxchg arch/x86/include/asm/atomic.h:186 [inline]
RIP: 0010:queued_spin_lock include/asm-generic/qspinlock.h:100 [inline]
RIP: 0010:do_raw_spin_lock include/linux/spinlock.h:148 [inline]
RIP: 0010:__raw_spin_lock include/linux/spinlock_api_smp.h:145 [inline]
RIP: 0010:_raw_spin_lock+0x7/0x20 kernel/locking/spinlock.c:151
RSP: 0018:ffffc900024e3d18 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffff88007cc88040 RCX: 0000000000000000
RDX: 0000000000000001 RSI: ffff88007cc88370 RDI: 00000000000001b0
RBP: ffffc900024e3d48 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
R13: ffff88007cc88040 R14: ffff88007cc88370 R15: 0000000000000000
FS: 00000000014a4880(0000) GS:ffff88007fd00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000000001b0 CR3: 000000007ccca000 CR4: 00000000000026e0
Call Trace:
vcpu_scan_ioapic arch/x86/kvm/x86.c:6559 [inline]
vcpu_enter_guest arch/x86/kvm/x86.c:6680 [inline]
vcpu_run arch/x86/kvm/x86.c:6933 [inline]
kvm_arch_vcpu_ioctl_run+0x10be/0x14d0 arch/x86/kvm/x86.c:7091
kvm_vcpu_ioctl+0x30a/0x5c0 arch/x86/kvm/../../../virt/kvm/kvm_main.c:2567
vfs_ioctl fs/ioctl.c:43 [inline]
do_vfs_ioctl+0x8f/0x5a0 fs/ioctl.c:683
SYSC_ioctl fs/ioctl.c:698 [inline]
SyS_ioctl+0x74/0x80 fs/ioctl.c:689
entry_SYSCALL_64_fastpath+0x1a/0xa9
RIP: 0033:0x43f437
RSP: 002b:00007ffcb80085f8 EFLAGS: 00000202 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00000000004002c8 RCX: 000000000043f437
RDX: 0000000000000000 RSI: 000000000000ae80 RDI: 0000000000000005
RBP: 00007ffcb8008810 R08: 00000000006d0c68 R09: 00000000006d0ce0
R10: 00007f4830dc39d0 R11: 0000000000000202 R12: 0000000000000000
R13: 000000000040bfe0 R14: 000000000040c070 R15: 0000000000000000
Code: 00 00 00 00 55 48 89 e5 8b 07 85 c0 74 04 31 c0 5d c3 ba 01 00
00 00 f0 0f b1 17 85 c0 75 ef b0 01 5d c3 90 31 c0 ba 01 00 00 00 <f0>
0f b1 17 85 c0 75 01 c3 55 89 c6 48 89 e5 e8 75 20 76 ff 5d
RIP: atomic_cmpxchg arch/x86/include/asm/atomic.h:186 [inline] RSP:
ffffc900024e3d18
RIP: queued_spin_lock include/asm-generic/qspinlock.h:100 [inline]
RSP: ffffc900024e3d18
RIP: do_raw_spin_lock include/linux/spinlock.h:148 [inline] RSP:
ffffc900024e3d18
RIP: __raw_spin_lock include/linux/spinlock_api_smp.h:145 [inline]
RSP: ffffc900024e3d18
RIP: _raw_spin_lock+0x7/0x20 kernel/locking/spinlock.c:151 RSP: ffffc900024e3d18
CR2: 00000000000001b0
---[ end trace 820952a240d809e9 ]---


// autogenerated by syzkaller (http://github.com/google/syzkaller)
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <linux/kvm.h>
#include <pthread.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#ifndef KVM_CAP_HYPERV_SYNIC
#define KVM_CAP_HYPERV_SYNIC 123
#endif

void* thr(void* arg)
{
struct kvm_enable_cap cap;
cap.flags = 0;
cap.cap = KVM_CAP_HYPERV_SYNIC;
ioctl((long)arg, KVM_ENABLE_CAP, &cap);
return 0;
}

int main()
{
void *host_mem = mmap(0, 0x1000, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
int kvmfd = open("/dev/kvm", 0);
int vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
struct kvm_userspace_memory_region memreg;
memreg.slot = 0;
memreg.flags = 0;
memreg.guest_phys_addr = 0;
memreg.memory_size = 0x1000;
memreg.userspace_addr = (unsigned long)host_mem;
memcpy(host_mem,
"\x1a\xb5\x00\x04\x65\x26\x64\x26\xf0\x82\xaa\x00"
"\x02\x00\x3e\x75\x64\xf3\xf3\xf0\x18\x35\x66\xb9"
"\x99\x00\x00\x40\x46\xb8\xc0\x40\x00\x00\x66\xba"
"\x00\x00\x00\x00\x0f\x30\x0f\xfc\xda\xdb\xca\x36"
"\x26\x3e\x67\x3e\x67\xcf\x66\xb9\x4a\x0a\x00\x00"
"\x0f\x32\x2e\x26\x65\x0f\x0f\x01\xa0",
69);
ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg);
int cpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0);
struct kvm_sregs sregs;
ioctl(cpufd, KVM_GET_SREGS, &sregs);
sregs.cr0 = 0;
sregs.cr4 = 0;
sregs.efer = 0;
sregs.cs.selector = 0;
sregs.cs.base = 0;
ioctl(cpufd, KVM_SET_SREGS, &sregs);
struct kvm_regs regs;
memset(&regs, 0, sizeof(regs));
regs.rflags = 2;
ioctl(cpufd, KVM_SET_REGS, &regs);
ioctl(vmfd, KVM_CREATE_IRQCHIP, 0);
pthread_t th;
pthread_create(&th, 0, thr, (void*)(long)cpufd);
usleep(rand() % 10000);
ioctl(cpufd, KVM_RUN, 0);
pthread_join(th, 0);
return 0;
}


On commit 0dad3a3014a0b9e72521ff44f17e0054f43dcdea (Dec 26)