Skip to contentSkip to conversation

FAILED: patch "[PATCH] kvm: fix kvm_ioctl_create_device() reference counting" failed to apply to 4.4-stable tree

PATCH [email protected] 1 participant 1 message Feb 11, 2019

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 4.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From cfa39381173d5f969daf43582c95ad679189cbc9 Mon Sep 17 00:00:00 2001
From: Jann Horn <[email protected]>
Date: Sat, 26 Jan 2019 01:54:33 +0100
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")
virt/kvm/kvm_main.c +2 -1
index 5ecea812cb6a..585845203db8 100644
@@ -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;
 }