ASA-2019-00086 – Linux kernel: Potential use-after-free via kvm_ioctl_create_device()


Allele Security Alert

ASA-2019-00086

Identifier(s)

ASA-2019-00086, CVE-2019-6974

Title

Potential use-after-free via kvm_ioctl_create_device()

Vendor(s)

Linux foundation

Product(s)

Linux kernel

Affected version(s)

Linux kernel versions before 5.0

Linux kernel versions 4.20.x before 4.20.8
Linux kernel versions 4.19.x before 4.19.21
Linux kernel versions 4.14.x before 4.14.99
Linux kernel versions 4.9.x before 4.9.156
Linux kernel versions 4.4.x before 4.4.176
Linux kernel versions 3.18.x before 3.18.136

Linux kernel versions since the following commit:

kvm: add device control API
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=852b6d57dc7fa378019786fa84727036e56839ea

Fixed version(s)

Linux kernel version 5.0

Linux kernel version 4.20.8
Linux kernel version 4.19.21
Linux kernel version 4.14.99
Linux kernel version 4.9.156
Linux kernel version 4.4.176
Linux kernel version 3.18.136

Linux kernel with the following commit:

kvm: fix kvm_ioctl_create_device() reference counting (CVE-2019-6974)
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cfa39381173d5f969daf43582c95ad679189cbc9

Proof of concept

Yes

Description

A use-after-free vulnerability was found in the way the Linux kernel’s KVM hypervisor implements its device control API. While creating a device via kvm_ioctl_create_device(), the device holds a reference to a VM object, later this reference is transferred to the caller’s file descriptor table. If such file descriptor was to be closed, reference count to the VM object could become zero, potentially leading to a use-after-free issue. A user/process could use this flaw to crash the guest VM resulting in a denial of service issue or, potentially, gain privileged access to a system.

Technical details

 kvm_ioctl_create_device() contains the following code:

dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;

dev->ops = ops;
dev->kvm = kvm;

mutex_lock(&kvm->lock);
ret = ops->create(dev, cd->type);
if (ret < 0) { mutex_unlock(&kvm->lock);
kfree(dev);
return ret;
}
list_add(&dev->vm_node, &kvm->devices);
mutex_unlock(&kvm->lock);

if (ops->init)
ops->init(dev);

ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC);
if (ret < 0) { mutex_lock(&kvm->lock);
list_del(&dev->vm_node);
mutex_unlock(&kvm->lock);
ops->destroy(dev);
return ret;
}

kvm_get_kvm(kvm);
cd->fd = ret;

This code:

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.

Credits

Jann Horn (Google Project Zero)

Reference(s)

kvm: fix kvm_ioctl_create_device() reference counting (CVE-2019-6974)
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cfa39381173d5f969daf43582c95ad679189cbc9

kvm: add device control API
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=852b6d57dc7fa378019786fa84727036e56839ea

kvm: fix kvm_ioctl_create_device() reference counting (CVE-2019-6974)
https://github.com/torvalds/linux/commit/cfa39381173d5f969daf43582c95ad679189cbc9

kvm: add device control API
https://github.com/torvalds/linux/commit/852b6d57dc7fa378019786fa84727036e56839ea

Linux 5.0
https://cdn.kernel.org/pub/linux/kernel/v5.x/ChangeLog-5.0

Linux 4.20.8
https://cdn.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.20.8

Linux 4.19.21
https://cdn.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.19.21

Linux 4.14.99
https://cdn.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.14.99

Linux 4.9.156
https://cdn.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.9.156

Linux 4.4.176
https://cdn.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.4.176

Linux 3.18.136
https://cdn.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.18.136

CVE-2019-6974 - Red Hat Customer Portal
https://access.redhat.com/security/cve/CVE-2019-6974

CVE-2019-6974 in Ubuntu
https://people.canonical.com/~ubuntu-security/cve/CVE-2019-6974.html

CVE-2019-6974
https://security-tracker.debian.org/tracker/CVE-2019-6974

CVE-2019-6974 | SUSE
https://www.suse.com/security/cve/CVE-2019-6974

CVE-2019-6974
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6974

CVE-2019-6974
https://nvd.nist.gov/vuln/detail/CVE-2019-6974

If there is any error in this alert or you wish a comprehensive analysis, let us know.

Last modified: November 29, 2019

We are not responsible for any data loss, device corruption or any other type of issue due to the use of any information mentioned in our security alerts.