Message ID | 1495187216-9294-1-git-send-email-wanpeng.li@hotmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 19/05/2017 11:46, Wanpeng Li wrote: > From: Wanpeng Li <wanpeng.li@hotmail.com> > > Huawei folks reported a read out-of-bounds vulnerability in kvm pio emulation. > > - "inb" instruction to access PIT Mod/Command register (ioport 0x43, write only, > a read should be ignored) in guest can get a random number. > - "rep insb" instruction to access PIT register port 0x43 can control memcpy() > in emulator_pio_in_emulated() to copy max 0x400 bytes but only read 1 bytes, > which will disclose the unimportant kernel memory in host but no crash. The data comes simply from the last PIO read, right? The vcpu struct is zero-initialized, so there is no kernel memory leak---the byte was already previously known to the guest. Good catch though, and the patch looks good. Thanks, Paolo > The similar test program below can reproduce the read out-of-bounds vulnerability:
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index b54125b..8440fc6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4823,16 +4823,20 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt, static int kernel_pio(struct kvm_vcpu *vcpu, void *pd) { - /* TODO: String I/O for in kernel device */ - int r; + int r = 0, i; - if (vcpu->arch.pio.in) - r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port, - vcpu->arch.pio.size, pd); - else - r = kvm_io_bus_write(vcpu, KVM_PIO_BUS, - vcpu->arch.pio.port, vcpu->arch.pio.size, - pd); + for (i = 0; i < vcpu->arch.pio.count; i++) { + if (vcpu->arch.pio.in) + r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port, + vcpu->arch.pio.size, pd); + else + r = kvm_io_bus_write(vcpu, KVM_PIO_BUS, + vcpu->arch.pio.port, vcpu->arch.pio.size, + pd); + if (r) + break; + pd += vcpu->arch.pio.size; + } return r; } @@ -4870,6 +4874,8 @@ static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt, if (vcpu->arch.pio.count) goto data_avail; + memset(vcpu->arch.pio_data, 0, size * count); + ret = emulator_pio_in_out(vcpu, size, port, val, count, true); if (ret) { data_avail: