4e6465dfa5
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
61 lines
2.1 KiB
Diff
61 lines
2.1 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Jann Horn <jannh@google.com>
|
|
Date: Mon, 25 Feb 2019 11:48:05 +0000
|
|
Subject: [PATCH] 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>
|
|
|
|
CVE-2019-6974
|
|
|
|
(cherry picked from commit cfa39381173d5f969daf43582c95ad679189cbc9)
|
|
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
|
|
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.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 234d03abcb75..238ddbc127e1 100644
|
|
--- a/virt/kvm/kvm_main.c
|
|
+++ b/virt/kvm/kvm_main.c
|
|
@@ -2908,8 +2908,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);
|
|
@@ -2917,7 +2919,6 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
|
|
return ret;
|
|
}
|
|
|
|
- kvm_get_kvm(kvm);
|
|
cd->fd = ret;
|
|
return 0;
|
|
}
|