Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 277017
b: refs/heads/master
c: 3d27e23
h: refs/heads/master
i:
  277015: 7b92c51
v: v3
  • Loading branch information
Alex Williamson authored and Avi Kivity committed Dec 25, 2011
1 parent 4890274 commit 25dfc98
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 423873736b78f549fbfa2f715f2e4de7e6c5e1e9
refs/heads/master: 3d27e23b17010c668db311140b17bbbb70c78fb9
4 changes: 4 additions & 0 deletions trunk/Documentation/virtual/kvm/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,10 @@ following flags are specified:
The KVM_DEV_ASSIGN_ENABLE_IOMMU flag is a mandatory option to ensure
isolation of the device. Usages not specifying this flag are deprecated.

Only PCI header type 0 devices with PCI BAR resources are supported by
device assignment. The user requesting this ioctl must have read/write
access to the PCI sysfs resource files associated with the device.

4.49 KVM_DEASSIGN_PCI_DEVICE

Capability: KVM_CAP_DEVICE_DEASSIGNMENT
Expand Down
75 changes: 75 additions & 0 deletions trunk/virt/kvm/assigned-dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -480,12 +482,73 @@ static int kvm_vm_ioctl_deassign_dev_irq(struct kvm *kvm,
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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 25dfc98

Please sign in to comment.