[kernel/f16] CVE-2011-4347 kvm: device assignment DoS (rhbz 771678)
Josh Boyer
jwboyer at fedoraproject.org
Wed Jan 4 15:39:04 UTC 2012
commit a8b9f7674811343fb92fbb8504ae988583477dde
Author: Josh Boyer <jwboyer at redhat.com>
Date: Wed Jan 4 10:36:23 2012 -0500
CVE-2011-4347 kvm: device assignment DoS (rhbz 771678)
KVM-fix-device-assignment-permissions.patch | 206 +++++++++++++++++++++++++++
kernel.spec | 11 ++-
2 files changed, 216 insertions(+), 1 deletions(-)
---
diff --git a/KVM-fix-device-assignment-permissions.patch b/KVM-fix-device-assignment-permissions.patch
new file mode 100644
index 0000000..2089482
--- /dev/null
+++ b/KVM-fix-device-assignment-permissions.patch
@@ -0,0 +1,206 @@
+From 423873736b78f549fbfa2f715f2e4de7e6c5e1e9 Mon Sep 17 00:00:00 2001
+From: Alex Williamson <alex.williamson at redhat.com>
+Date: Tue, 20 Dec 2011 21:59:03 -0700
+Subject: [PATCH 1/2] KVM: Remove ability to assign a device without iommu
+ support
+
+This option has no users and it exposes a security hole that we
+can allow devices to be assigned without iommu protection. Make
+KVM_DEV_ASSIGN_ENABLE_IOMMU a mandatory option.
+
+Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
+Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
+---
+ virt/kvm/assigned-dev.c | 18 +++++++++---------
+ 1 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c
+index 3ad0925..a251a28 100644
+--- a/virt/kvm/assigned-dev.c
++++ b/virt/kvm/assigned-dev.c
+@@ -487,6 +487,9 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *match;
+ struct pci_dev *dev;
+
++ if (!(assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU))
++ return -EINVAL;
++
+ mutex_lock(&kvm->lock);
+ idx = srcu_read_lock(&kvm->srcu);
+
+@@ -544,16 +547,14 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
+
+ list_add(&match->list, &kvm->arch.assigned_dev_head);
+
+- if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) {
+- if (!kvm->arch.iommu_domain) {
+- r = kvm_iommu_map_guest(kvm);
+- if (r)
+- goto out_list_del;
+- }
+- r = kvm_assign_device(kvm, match);
++ if (!kvm->arch.iommu_domain) {
++ r = kvm_iommu_map_guest(kvm);
+ if (r)
+ goto out_list_del;
+ }
++ r = kvm_assign_device(kvm, match);
++ if (r)
++ goto out_list_del;
+
+ out:
+ srcu_read_unlock(&kvm->srcu, idx);
+@@ -593,8 +594,7 @@ static int kvm_vm_ioctl_deassign_device(struct kvm *kvm,
+ goto out;
+ }
+
+- if (match->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU)
+- kvm_deassign_device(kvm, match);
++ kvm_deassign_device(kvm, match);
+
+ kvm_free_assigned_device(kvm, match);
+
+--
+1.7.7.5
+
+
+From 3d27e23b17010c668db311140b17bbbb70c78fb9 Mon Sep 17 00:00:00 2001
+From: Alex Williamson <alex.williamson at redhat.com>
+Date: Tue, 20 Dec 2011 21:59:09 -0700
+Subject: [PATCH 2/2] KVM: Device assignment permission checks
+
+Only allow KVM device assignment to attach to devices which:
+
+ - Are not bridges
+ - Have BAR resources (assume others are special devices)
+ - The user has permissions to use
+
+Assigning a bridge is a configuration error, it's not supported, and
+typically doesn't result in the behavior the user is expecting anyway.
+Devices without BAR resources are typically chipset components that
+also don't have host drivers. We don't want users to hold such devices
+captive or cause system problems by fencing them off into an iommu
+domain. We determine "permission to use" by testing whether the user
+has access to the PCI sysfs resource files. By default a normal user
+will not have access to these files, so it provides a good indication
+that an administration agent has granted the user access to the device.
+
+[Yang Bai: add missing #include]
+[avi: fix comment style]
+
+Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
+Signed-off-by: Yang Bai <hamo.by at gmail.com>
+Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
+---
+ virt/kvm/assigned-dev.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 75 insertions(+), 0 deletions(-)
+
+diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c
+index a251a28..758e3b3 100644
+--- a/virt/kvm/assigned-dev.c
++++ b/virt/kvm/assigned-dev.c
+@@ -17,6 +17,8 @@
+ #include <linux/pci.h>
+ #include <linux/interrupt.h>
+ #include <linux/slab.h>
++#include <linux/namei.h>
++#include <linux/fs.h>
+ #include "irq.h"
+
+ static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head,
+@@ -480,12 +482,73 @@ out:
+ return r;
+ }
+
++/*
++ * We want to test whether the caller has been granted permissions to
++ * use this device. To be able to configure and control the device,
++ * the user needs access to PCI configuration space and BAR resources.
++ * These are accessed through PCI sysfs. PCI config space is often
++ * passed to the process calling this ioctl via file descriptor, so we
++ * can't rely on access to that file. We can check for permissions
++ * on each of the BAR resource files, which is a pretty clear
++ * indicator that the user has been granted access to the device.
++ */
++static int probe_sysfs_permissions(struct pci_dev *dev)
++{
++#ifdef CONFIG_SYSFS
++ int i;
++ bool bar_found = false;
++
++ for (i = PCI_STD_RESOURCES; i <= PCI_STD_RESOURCE_END; i++) {
++ char *kpath, *syspath;
++ struct path path;
++ struct inode *inode;
++ int r;
++
++ if (!pci_resource_len(dev, i))
++ continue;
++
++ kpath = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
++ if (!kpath)
++ return -ENOMEM;
++
++ /* Per sysfs-rules, sysfs is always at /sys */
++ syspath = kasprintf(GFP_KERNEL, "/sys%s/resource%d", kpath, i);
++ kfree(kpath);
++ if (!syspath)
++ return -ENOMEM;
++
++ r = kern_path(syspath, LOOKUP_FOLLOW, &path);
++ kfree(syspath);
++ if (r)
++ return r;
++
++ inode = path.dentry->d_inode;
++
++ r = inode_permission(inode, MAY_READ | MAY_WRITE | MAY_ACCESS);
++ path_put(&path);
++ if (r)
++ return r;
++
++ bar_found = true;
++ }
++
++ /* If no resources, probably something special */
++ if (!bar_found)
++ return -EPERM;
++
++ return 0;
++#else
++ return -EINVAL; /* No way to control the device without sysfs */
++#endif
++}
++
+ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
+ struct kvm_assigned_pci_dev *assigned_dev)
+ {
+ int r = 0, idx;
+ struct kvm_assigned_dev_kernel *match;
+ struct pci_dev *dev;
++ u8 header_type;
+
+ if (!(assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU))
+ return -EINVAL;
+@@ -516,6 +579,18 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
+ r = -EINVAL;
+ goto out_free;
+ }
++
++ /* Don't allow bridges to be assigned */
++ pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
++ if ((header_type & PCI_HEADER_TYPE) != PCI_HEADER_TYPE_NORMAL) {
++ r = -EPERM;
++ goto out_put;
++ }
++
++ r = probe_sysfs_permissions(dev);
++ if (r)
++ goto out_put;
++
+ if (pci_enable_device(dev)) {
+ printk(KERN_INFO "%s: Could not enable PCI device\n", __func__);
+ r = -EBUSY;
+--
+1.7.7.5
+
diff --git a/kernel.spec b/kernel.spec
index 1ceb3fc..a932a29 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -54,7 +54,7 @@ Summary: The Linux kernel
# For non-released -rc kernels, this will be appended after the rcX and
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
#
-%global baserelease 1
+%global baserelease 2
%global fedora_build %{baserelease}
# base_sublevel is the kernel version we're starting with and patching
@@ -852,6 +852,9 @@ Patch21050: thp-reduce-khugepaged-freezing-latency.patch
#rhbz 771387
Patch21055: KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch
+#rhbz 771678
+Patch21056: KVM-fix-device-assignment-permissions.patch
+
#rhbz 770233
Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch
@@ -1595,6 +1598,9 @@ ApplyPatch KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch
#rhbz 770233
ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch
+#rhbz 771678
+ApplyPatch KVM-fix-device-assignment-permissions.patch
+
# END OF PATCH APPLICATIONS
%endif
@@ -2370,6 +2376,9 @@ fi
# and build.
%changelog
+* Wed Jan 04 2012 Josh Boyer <jwboyer at redhat.com>
+- CVE-2011-4347 kvm: device assignment DoS (rhbz 771678)
+
* Tue Jan 03 2012 Josh Boyer <jwboyer at redhat.com> 3.1.7-1
- Linux 3.1.7
More information about the scm-commits
mailing list