summaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorJann Horn <jannh@google.com>2019-01-25 19:54:33 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2019-02-07 13:02:38 -0500
commitcfa39381173d5f969daf43582c95ad679189cbc9 (patch)
treee2a5314d128b9daf9839b8fe5482ed445924353a /virt
parent8834f5600cf3c8db365e18a3d5cac2c2780c81e5 (diff)
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>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/kvm_main.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 5ecea812cb6a..585845203db8 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -3000,8 +3000,10 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
3000 if (ops->init) 3000 if (ops->init)
3001 ops->init(dev); 3001 ops->init(dev);
3002 3002
3003 kvm_get_kvm(kvm);
3003 ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC); 3004 ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC);
3004 if (ret < 0) { 3005 if (ret < 0) {
3006 kvm_put_kvm(kvm);
3005 mutex_lock(&kvm->lock); 3007 mutex_lock(&kvm->lock);
3006 list_del(&dev->vm_node); 3008 list_del(&dev->vm_node);
3007 mutex_unlock(&kvm->lock); 3009 mutex_unlock(&kvm->lock);
@@ -3009,7 +3011,6 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
3009 return ret; 3011 return ret;
3010 } 3012 }
3011 3013
3012 kvm_get_kvm(kvm);
3013 cd->fd = ret; 3014 cd->fd = ret;
3014 return 0; 3015 return 0;
3015} 3016}