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 +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 +Signed-off-by: Marcelo Tosatti +--- + 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 +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 +Signed-off-by: Yang Bai +Signed-off-by: Marcelo Tosatti +--- + 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 + #include + #include ++#include ++#include + #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 b22d4d5..a4db929 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -730,6 +730,9 @@ Patch21050: thp-reduce-khugepaged-freezing-latency.patch #rhbz 770102 Patch21055: KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch +#rhbz 770096 +Patch21056: KVM-fix-device-assignment-permissions.patch + #rhbz 770233 Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch @@ -1365,6 +1368,9 @@ ApplyPatch KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch #rhbz 770233 ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch +#rhbz 770096 +ApplyPatch KVM-fix-device-assignment-permissions.patch + # END OF PATCH APPLICATIONS %endif @@ -2012,6 +2018,9 @@ fi # and build. %changelog +* Wed Jan 04 2012 Josh Boyer +- CVE-2011-4347 kvm: device assignment DoS (rhbz 770096) + * Tue Jan 03 2012 Josh Boyer 2.6.41.7-1 - Linux 3.1.7