Message ID | 20090416113044.GA11200@amt.cnet (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Marcelo Tosatti wrote: > Matt T. Yourst notes that kvm_arch_vcpu_ioctl_set_sregs lacks validity > checking for the new cr3 value: > > "Userspace callers of KVM_SET_SREGS can pass a bogus value of cr3 to > the kernel. This will trigger a NULL pointer access in gfn_to_rmap() > when userspace next tries to call KVM_RUN on the affected VCPU and kvm > attempts to activate the new non-existent page table root. > > This happens since kvm only validates that cr3 points to a valid guest > physical memory page when code *inside* the guest sets cr3. However, kvm > currently trusts the userspace caller (e.g. QEMU) on the host machine to > always supply a valid page table root, rather than properly validating > it along with the rest of the reloaded guest state." > > http://sourceforge.net/tracker/?func=detail&atid=893831&aid=2687641&group_id=180599 > > Check for a valid cr3 address in kvm_arch_vcpu_ioctl_set_sregs, triple > fault in case of failure. > > Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> > > Index: kvm/arch/x86/kvm/x86.c > =================================================================== > --- kvm.orig/arch/x86/kvm/x86.c > +++ kvm/arch/x86/kvm/x86.c > @@ -3986,7 +3986,13 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct > > vcpu->arch.cr2 = sregs->cr2; > mmu_reset_needed |= vcpu->arch.cr3 != sregs->cr3; > - vcpu->arch.cr3 = sregs->cr3; > + > + down_read(&vcpu->kvm->slots_lock); > + if (gfn_to_memslot(vcpu->kvm, sregs->cr3 >> PAGE_SHIFT)) > + vcpu->arch.cr3 = sregs->cr3; > + else > + set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests); > + up_read(&vcpu->kvm->slots_lock); > > kvm_set_cr8(vcpu, sregs->cr8); > > Isn't this self-defeating? If you drop slots_lock, cr3 may be invalid again by the time you set cvpu->arch.cr3?
Avi Kivity wrote: > Marcelo Tosatti wrote: >> Matt T. Yourst notes that kvm_arch_vcpu_ioctl_set_sregs lacks validity >> checking for the new cr3 value: >> "Userspace callers of KVM_SET_SREGS can pass a bogus value of >> cr3 to >> the kernel. This will trigger a NULL pointer access in gfn_to_rmap() >> when userspace next tries to call KVM_RUN on the affected VCPU and kvm >> attempts to activate the new non-existent page table root. >> >> This happens since kvm only validates that cr3 points to a valid guest >> physical memory page when code *inside* the guest sets cr3. However, kvm >> currently trusts the userspace caller (e.g. QEMU) on the host machine to >> always supply a valid page table root, rather than properly validating >> it along with the rest of the reloaded guest state." >> >> http://sourceforge.net/tracker/?func=detail&atid=893831&aid=2687641&group_id=180599 >> >> >> Check for a valid cr3 address in kvm_arch_vcpu_ioctl_set_sregs, triple >> fault in case of failure. >> >> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> >> >> Index: kvm/arch/x86/kvm/x86.c >> =================================================================== >> --- kvm.orig/arch/x86/kvm/x86.c >> +++ kvm/arch/x86/kvm/x86.c >> @@ -3986,7 +3986,13 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct >> >> vcpu->arch.cr2 = sregs->cr2; >> mmu_reset_needed |= vcpu->arch.cr3 != sregs->cr3; >> - vcpu->arch.cr3 = sregs->cr3; >> + >> + down_read(&vcpu->kvm->slots_lock); >> + if (gfn_to_memslot(vcpu->kvm, sregs->cr3 >> PAGE_SHIFT)) >> + vcpu->arch.cr3 = sregs->cr3; >> + else >> + set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests); >> + up_read(&vcpu->kvm->slots_lock); >> >> kvm_set_cr8(vcpu, sregs->cr8); >> >> > > Isn't this self-defeating? If you drop slots_lock, cr3 may be invalid > again by the time you set cvpu->arch.cr3? > Uh, sorry, of course not. I misread down as up. Bad day for me. Will apply the patch. Still, don't we have a problem if userspace drops the memory slot where cr3 points to?
Index: kvm/arch/x86/kvm/x86.c =================================================================== --- kvm.orig/arch/x86/kvm/x86.c +++ kvm/arch/x86/kvm/x86.c @@ -3986,7 +3986,13 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct vcpu->arch.cr2 = sregs->cr2; mmu_reset_needed |= vcpu->arch.cr3 != sregs->cr3; - vcpu->arch.cr3 = sregs->cr3; + + down_read(&vcpu->kvm->slots_lock); + if (gfn_to_memslot(vcpu->kvm, sregs->cr3 >> PAGE_SHIFT)) + vcpu->arch.cr3 = sregs->cr3; + else + set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests); + up_read(&vcpu->kvm->slots_lock); kvm_set_cr8(vcpu, sregs->cr8);
Matt T. Yourst notes that kvm_arch_vcpu_ioctl_set_sregs lacks validity checking for the new cr3 value: "Userspace callers of KVM_SET_SREGS can pass a bogus value of cr3 to the kernel. This will trigger a NULL pointer access in gfn_to_rmap() when userspace next tries to call KVM_RUN on the affected VCPU and kvm attempts to activate the new non-existent page table root. This happens since kvm only validates that cr3 points to a valid guest physical memory page when code *inside* the guest sets cr3. However, kvm currently trusts the userspace caller (e.g. QEMU) on the host machine to always supply a valid page table root, rather than properly validating it along with the rest of the reloaded guest state." http://sourceforge.net/tracker/?func=detail&atid=893831&aid=2687641&group_id=180599 Check for a valid cr3 address in kvm_arch_vcpu_ioctl_set_sregs, triple fault in case of failure. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html