[RHEL7,COMMIT] ms/kvm: fix kvm_ioctl_create_device() reference counting (CVE-2019-6974)

Submitted by Konstantin Khorenko on April 3, 2019, 11:25 a.m.

Details

Message ID 201904031125.x33BPQvc007482@finist-ce7.sw.ru
State New
Series "ms/kvm: fix kvm_ioctl_create_device() reference counting (CVE-2019-6974)"
Headers show

Commit Message

Konstantin Khorenko April 3, 2019, 11:25 a.m.
The commit is pushed to "branch-rh7-3.10.0-957.10.1.vz7.85.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-957.10.1.vz7.85.11
------>
commit 21ba0e5f37414590a0090fac3b250034547cb987
Author: Jann Horn <jannh@google.com>
Date:   Wed Apr 3 14:25:26 2019 +0300

    ms/kvm: fix kvm_ioctl_create_device() reference counting (CVE-2019-6974)
    
    kvm_ioctl_create_device() does the following:
    
    1. creates a device that holds a reference to the VM object (with a borrowed
       reference, the VM's refcount has not been bumped yet)
    2. initializes the device
    3. transfers the reference to the device to the caller's file descriptor table
    4. calls kvm_get_kvm() to turn the borrowed reference to the VM into a real
       reference
    
    The ownership transfer in step 3 must not happen before the reference to the VM
    becomes a proper, non-borrowed reference, which only happens in step 4.
    After step 3, an attacker can close the file descriptor and drop the borrowed
    reference, which can cause the refcount of the kvm object to drop to zero.
    
    This means that we need to grab a reference for the device before
    anon_inode_getfd(), otherwise the VM can disappear from under us.
    
    Fixes: 852b6d57dc7f ("kvm: add device control API")
    Cc: stable@kernel.org
    Signed-off-by: Jann Horn <jannh@google.com>
    Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
    
    This is a backport of commit cfa39381173d5f969daf43582c95ad679189cbc9
    in the mainline kernel.
    
    https://jira.sw.ru/browse/PSBM-93360
    
    Signed-off-by: Evgenii Shatokhin <eshatokhin@virtuozzo.com>
---
 virt/kvm/kvm_main.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 84e3064052dd..ccab89847623 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2858,14 +2858,15 @@  static int kvm_ioctl_create_device(struct kvm *kvm,
 		return ret;
 	}
 
+	kvm_get_kvm(kvm);
 	ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC);
 	if (ret < 0) {
+		kvm_put_kvm(kvm);
 		ops->destroy(dev);
 		return ret;
 	}
 
 	list_add(&dev->vm_node, &kvm->devices);
-	kvm_get_kvm(kvm);
 	cd->fd = ret;
 	return 0;
 }