|
|
@@ -0,0 +1,60 @@
|
|
|
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
+From: Jann Horn <[email protected]>
|
|
|
+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: [email protected]
|
|
|
+Signed-off-by: Jann Horn <[email protected]>
|
|
|
+Signed-off-by: Paolo Bonzini <[email protected]>
|
|
|
+
|
|
|
+CVE-2019-6974
|
|
|
+
|
|
|
+(cherry picked from commit cfa39381173d5f969daf43582c95ad679189cbc9)
|
|
|
+Signed-off-by: Tyler Hicks <[email protected]>
|
|
|
+Signed-off-by: Thomas Lamprecht <[email protected]>
|
|
|
+---
|
|
|
+ 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;
|
|
|
+ }
|