58 lines
2.0 KiB
Diff
58 lines
2.0 KiB
Diff
From: Jann Horn <jannh@google.com>
|
|
Date: Sat, 26 Jan 2019 01:54:33 +0100
|
|
Subject: kvm: fix kvm_ioctl_create_device() reference counting (CVE-2019-6974)
|
|
Origin: https://git.kernel.org/linus/cfa39381173d5f969daf43582c95ad679189cbc9
|
|
Bug-Debian-Security: https://security-tracker.debian.org/tracker/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>
|
|
---
|
|
virt/kvm/kvm_main.c | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
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,
|
|
if (ops->init)
|
|
ops->init(dev);
|
|
|
|
+ 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);
|
|
mutex_lock(&kvm->lock);
|
|
list_del(&dev->vm_node);
|
|
mutex_unlock(&kvm->lock);
|
|
@@ -3009,7 +3011,6 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
|
|
return ret;
|
|
}
|
|
|
|
- kvm_get_kvm(kvm);
|
|
cd->fd = ret;
|
|
return 0;
|
|
}
|
|
--
|
|
2.11.0
|
|
|