Wanpeng Li
2e112f3659
KVM: mmu: Fix overlap between public and private memslots
commit b28676bb8ae4569cced423dc2a88f7cb319d5379 upstream.
Reported by syzkaller:
pte_list_remove: ffff9714eb1f8078 0->BUG
------------[ cut here ]------------
kernel BUG at arch/x86/kvm/mmu.c:1157!
invalid opcode: 0000 [#1] SMP
RIP: 0010:pte_list_remove+0x11b/0x120 [kvm]
Call Trace:
drop_spte+0x83/0xb0 [kvm]
mmu_page_zap_pte+0xcc/0xe0 [kvm]
kvm_mmu_prepare_zap_page+0x81/0x4a0 [kvm]
kvm_mmu_invalidate_zap_all_pages+0x159/0x220 [kvm]
kvm_arch_flush_shadow_all+0xe/0x10 [kvm]
kvm_mmu_notifier_release+0x6c/0xa0 [kvm]
? kvm_mmu_notifier_release+0x5/0xa0 [kvm]
__mmu_notifier_release+0x79/0x110
? __mmu_notifier_release+0x5/0x110
exit_mmap+0x15a/0x170
? do_exit+0x281/0xcb0
mmput+0x66/0x160
do_exit+0x2c9/0xcb0
? __context_tracking_exit.part.5+0x4a/0x150
do_group_exit+0x50/0xd0
SyS_exit_group+0x14/0x20
do_syscall_64+0x73/0x1f0
entry_SYSCALL64_slow_path+0x25/0x25
The reason is that when creates new memslot, there is no guarantee for new
memslot not overlap with private memslots. This can be triggered by the
following program:
#include <fcntl.h>
#include <pthread.h>
#include <setjmp.h>
#include <signal.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/kvm.h>
long r[16];
int main()
{
void *p = valloc(0x4000);
r[2] = open("/dev/kvm", 0);
r[3] = ioctl(r[2], KVM_CREATE_VM, 0x0ul);
uint64_t addr = 0xf000;
ioctl(r[3], KVM_SET_IDENTITY_MAP_ADDR, &addr);
r[6] = ioctl(r[3], KVM_CREATE_VCPU, 0x0ul);
ioctl(r[3], KVM_SET_TSS_ADDR, 0x0ul);
ioctl(r[6], KVM_RUN, 0);
ioctl(r[6], KVM_RUN, 0);
struct kvm_userspace_memory_region mr = {
.slot = 0,
.flags = KVM_MEM_LOG_DIRTY_PAGES,
.guest_phys_addr = 0xf000,
.memory_size = 0x4000,
.userspace_addr = (uintptr_t) p
};
ioctl(r[3], KVM_SET_USER_MEMORY_REGION, &mr);
return 0;
}
This patch fixes the bug by not adding a new memslot even if it
overlaps with private memslots.
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Eric Biggers <ebiggers3@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
|
2018-03-11 16:21:29 +01:00 |
| .. |
|
arm
|
KVM: arm/arm64: vgic-its: Preserve the revious read from the pending table
|
2017-12-16 16:25:47 +01:00 |
|
async_pf.c
|
KVM: async_pf: avoid recursive flushing of work items
|
2016-11-19 19:04:17 +01:00 |
|
async_pf.h
|
KVM: fix checkpatch.pl errors in kvm/async_pf.h
|
2015-06-19 17:16:25 +02:00 |
|
coalesced_mmio.c
|
KVM: move iodev.h from virt/kvm/ to include/kvm
|
2015-03-26 21:43:12 +00:00 |
|
coalesced_mmio.h
|
KVM: make the declaration of functions within 80 characters
|
2015-09-14 18:43:19 +02:00 |
|
eventfd.c
|
KVM: kvm_io_bus_unregister_dev() should never fail
|
2017-04-08 09:30:34 +02:00 |
|
irqchip.c
|
KVM/ARM Changes for v4.8 - Take 2
|
2016-08-04 13:59:56 +02:00 |
|
Kconfig
|
KVM: remove kvm_vcpu_compatible
|
2016-06-16 00:05:00 +02:00 |
|
kvm_main.c
|
KVM: mmu: Fix overlap between public and private memslots
|
2018-03-11 16:21:29 +01:00 |
|
vfio.c
|
vfio: New external user group/file match
|
2017-07-27 15:08:03 -07:00 |
|
vfio.h
|
kvm: vfio: fix unregister kvm_device_ops of vfio
|
2014-10-24 13:30:47 +02:00 |