Skip to content

Commit

Permalink
Merge tag 'vfio-v4.4-rc5' of git://github.com/awilliam/linux-vfio
Browse files Browse the repository at this point in the history
Pull VFIO fixes from Alex Williamson:

 - Various fixes for removing redundancy, const'ifying structs, avoiding
   stack usage, fixing WARN usage (Krzysztof Kozlowski, Julia Lawall,
   Kees Cook, Dan Carpenter)

 - Revert No-IOMMU mode as the intended user has not emerged (Alex
   Williamson)

* tag 'vfio-v4.4-rc5' of git://github.com/awilliam/linux-vfio:
  Revert: "vfio: Include No-IOMMU mode"
  vfio: fix a warning message
  vfio: platform: remove needless stack usage
  vfio-pci: constify pci_error_handlers structures
  vfio: Drop owner assignment from platform_driver
  • Loading branch information
Linus Torvalds committed Dec 10, 2015
2 parents eef121f + ae5515d commit 6764e5e
Show file tree
Hide file tree
Showing 7 changed files with 13 additions and 216 deletions.
15 changes: 0 additions & 15 deletions drivers/vfio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,6 @@ menuconfig VFIO

If you don't know what to do here, say N.

menuconfig VFIO_NOIOMMU
bool "VFIO No-IOMMU support"
depends on VFIO
help
VFIO is built on the ability to isolate devices using the IOMMU.
Only with an IOMMU can userspace access to DMA capable devices be
considered secure. VFIO No-IOMMU mode enables IOMMU groups for
devices without IOMMU backing for the purpose of re-using the VFIO
infrastructure in a non-secure mode. Use of this mode will result
in an unsupportable kernel and will therefore taint the kernel.
Device assignment to virtual machines is also not possible with
this mode since there is no IOMMU to provide DMA translation.

If you don't know what to do here, say N.

source "drivers/vfio/pci/Kconfig"
source "drivers/vfio/platform/Kconfig"
source "virt/lib/Kconfig"
10 changes: 5 additions & 5 deletions drivers/vfio/pci/vfio_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -940,13 +940,13 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
return -EINVAL;

group = vfio_iommu_group_get(&pdev->dev);
group = iommu_group_get(&pdev->dev);
if (!group)
return -EINVAL;

vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
if (!vdev) {
vfio_iommu_group_put(group, &pdev->dev);
iommu_group_put(group);
return -ENOMEM;
}

Expand All @@ -957,7 +957,7 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)

ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev);
if (ret) {
vfio_iommu_group_put(group, &pdev->dev);
iommu_group_put(group);
kfree(vdev);
return ret;
}
Expand Down Expand Up @@ -993,7 +993,7 @@ static void vfio_pci_remove(struct pci_dev *pdev)
if (!vdev)
return;

vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev);
iommu_group_put(pdev->dev.iommu_group);
kfree(vdev);

if (vfio_pci_is_vga(pdev)) {
Expand Down Expand Up @@ -1035,7 +1035,7 @@ static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev,
return PCI_ERS_RESULT_CAN_RECOVER;
}

static struct pci_error_handlers vfio_err_handlers = {
static const struct pci_error_handlers vfio_err_handlers = {
.error_detected = vfio_pci_aer_err_detected,
};

Expand Down
1 change: 0 additions & 1 deletion drivers/vfio/platform/vfio_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ static struct platform_driver vfio_platform_driver = {
.remove = vfio_platform_remove,
.driver = {
.name = "vfio-platform",
.owner = THIS_MODULE,
},
};

Expand Down
5 changes: 1 addition & 4 deletions drivers/vfio/platform/vfio_platform_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,10 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,

static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
{
char modname[256];

vdev->reset = vfio_platform_lookup_reset(vdev->compat,
&vdev->reset_module);
if (!vdev->reset) {
snprintf(modname, 256, "vfio-reset:%s", vdev->compat);
request_module(modname);
request_module("vfio-reset:%s", vdev->compat);
vdev->reset = vfio_platform_lookup_reset(vdev->compat,
&vdev->reset_module);
}
Expand Down
188 changes: 7 additions & 181 deletions drivers/vfio/vfio.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ struct vfio_container {
struct rw_semaphore group_lock;
struct vfio_iommu_driver *iommu_driver;
void *iommu_data;
bool noiommu;
};

struct vfio_unbound_dev {
Expand All @@ -85,7 +84,6 @@ struct vfio_group {
struct list_head unbound_list;
struct mutex unbound_lock;
atomic_t opened;
bool noiommu;
};

struct vfio_device {
Expand All @@ -97,147 +95,6 @@ struct vfio_device {
void *device_data;
};

#ifdef CONFIG_VFIO_NOIOMMU
static bool noiommu __read_mostly;
module_param_named(enable_unsafe_noiommu_support,
noiommu, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(enable_unsafe_noiommu_mode, "Enable UNSAFE, no-IOMMU mode. This mode provides no device isolation, no DMA translation, no host kernel protection, cannot be used for device assignment to virtual machines, requires RAWIO permissions, and will taint the kernel. If you do not know what this is for, step away. (default: false)");
#endif

/*
* vfio_iommu_group_{get,put} are only intended for VFIO bus driver probe
* and remove functions, any use cases other than acquiring the first
* reference for the purpose of calling vfio_add_group_dev() or removing
* that symmetric reference after vfio_del_group_dev() should use the raw
* iommu_group_{get,put} functions. In particular, vfio_iommu_group_put()
* removes the device from the dummy group and cannot be nested.
*/
struct iommu_group *vfio_iommu_group_get(struct device *dev)
{
struct iommu_group *group;
int __maybe_unused ret;

group = iommu_group_get(dev);

#ifdef CONFIG_VFIO_NOIOMMU
/*
* With noiommu enabled, an IOMMU group will be created for a device
* that doesn't already have one and doesn't have an iommu_ops on their
* bus. We use iommu_present() again in the main code to detect these
* fake groups.
*/
if (group || !noiommu || iommu_present(dev->bus))
return group;

group = iommu_group_alloc();
if (IS_ERR(group))
return NULL;

iommu_group_set_name(group, "vfio-noiommu");
ret = iommu_group_add_device(group, dev);
iommu_group_put(group);
if (ret)
return NULL;

/*
* Where to taint? At this point we've added an IOMMU group for a
* device that is not backed by iommu_ops, therefore any iommu_
* callback using iommu_ops can legitimately Oops. So, while we may
* be about to give a DMA capable device to a user without IOMMU
* protection, which is clearly taint-worthy, let's go ahead and do
* it here.
*/
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
dev_warn(dev, "Adding kernel taint for vfio-noiommu group on device\n");
#endif

return group;
}
EXPORT_SYMBOL_GPL(vfio_iommu_group_get);

void vfio_iommu_group_put(struct iommu_group *group, struct device *dev)
{
#ifdef CONFIG_VFIO_NOIOMMU
if (!iommu_present(dev->bus))
iommu_group_remove_device(dev);
#endif

iommu_group_put(group);
}
EXPORT_SYMBOL_GPL(vfio_iommu_group_put);

#ifdef CONFIG_VFIO_NOIOMMU
static void *vfio_noiommu_open(unsigned long arg)
{
if (arg != VFIO_NOIOMMU_IOMMU)
return ERR_PTR(-EINVAL);
if (!capable(CAP_SYS_RAWIO))
return ERR_PTR(-EPERM);

return NULL;
}

static void vfio_noiommu_release(void *iommu_data)
{
}

static long vfio_noiommu_ioctl(void *iommu_data,
unsigned int cmd, unsigned long arg)
{
if (cmd == VFIO_CHECK_EXTENSION)
return arg == VFIO_NOIOMMU_IOMMU ? 1 : 0;

return -ENOTTY;
}

static int vfio_iommu_present(struct device *dev, void *unused)
{
return iommu_present(dev->bus) ? 1 : 0;
}

static int vfio_noiommu_attach_group(void *iommu_data,
struct iommu_group *iommu_group)
{
return iommu_group_for_each_dev(iommu_group, NULL,
vfio_iommu_present) ? -EINVAL : 0;
}

static void vfio_noiommu_detach_group(void *iommu_data,
struct iommu_group *iommu_group)
{
}

static struct vfio_iommu_driver_ops vfio_noiommu_ops = {
.name = "vfio-noiommu",
.owner = THIS_MODULE,
.open = vfio_noiommu_open,
.release = vfio_noiommu_release,
.ioctl = vfio_noiommu_ioctl,
.attach_group = vfio_noiommu_attach_group,
.detach_group = vfio_noiommu_detach_group,
};

static struct vfio_iommu_driver vfio_noiommu_driver = {
.ops = &vfio_noiommu_ops,
};

/*
* Wrap IOMMU drivers, the noiommu driver is the one and only driver for
* noiommu groups (and thus containers) and not available for normal groups.
*/
#define vfio_for_each_iommu_driver(con, pos) \
for (pos = con->noiommu ? &vfio_noiommu_driver : \
list_first_entry(&vfio.iommu_drivers_list, \
struct vfio_iommu_driver, vfio_next); \
(con->noiommu ? pos != NULL : \
&pos->vfio_next != &vfio.iommu_drivers_list); \
pos = con->noiommu ? NULL : list_next_entry(pos, vfio_next))
#else
#define vfio_for_each_iommu_driver(con, pos) \
list_for_each_entry(pos, &vfio.iommu_drivers_list, vfio_next)
#endif


/**
* IOMMU driver registration
*/
Expand Down Expand Up @@ -342,8 +199,7 @@ static void vfio_group_unlock_and_free(struct vfio_group *group)
/**
* Group objects - create, release, get, put, search
*/
static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,
bool noiommu)
static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
{
struct vfio_group *group, *tmp;
struct device *dev;
Expand All @@ -361,7 +217,6 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,
atomic_set(&group->container_users, 0);
atomic_set(&group->opened, 0);
group->iommu_group = iommu_group;
group->noiommu = noiommu;

group->nb.notifier_call = vfio_iommu_group_notifier;

Expand Down Expand Up @@ -397,8 +252,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,

dev = device_create(vfio.class, NULL,
MKDEV(MAJOR(vfio.group_devt), minor),
group, "%s%d", noiommu ? "noiommu-" : "",
iommu_group_id(iommu_group));
group, "%d", iommu_group_id(iommu_group));
if (IS_ERR(dev)) {
vfio_free_group_minor(minor);
vfio_group_unlock_and_free(group);
Expand Down Expand Up @@ -682,7 +536,7 @@ static int vfio_group_nb_add_dev(struct vfio_group *group, struct device *dev)
return 0;

/* TODO Prevent device auto probing */
WARN("Device %s added to live group %d!\n", dev_name(dev),
WARN(1, "Device %s added to live group %d!\n", dev_name(dev),
iommu_group_id(group->iommu_group));

return 0;
Expand Down Expand Up @@ -786,8 +640,7 @@ int vfio_add_group_dev(struct device *dev,

group = vfio_group_get_from_iommu(iommu_group);
if (!group) {
group = vfio_create_group(iommu_group,
!iommu_present(dev->bus));
group = vfio_create_group(iommu_group);
if (IS_ERR(group)) {
iommu_group_put(iommu_group);
return PTR_ERR(group);
Expand Down Expand Up @@ -999,7 +852,8 @@ static long vfio_ioctl_check_extension(struct vfio_container *container,
*/
if (!driver) {
mutex_lock(&vfio.iommu_drivers_lock);
vfio_for_each_iommu_driver(container, driver) {
list_for_each_entry(driver, &vfio.iommu_drivers_list,
vfio_next) {
if (!try_module_get(driver->ops->owner))
continue;

Expand Down Expand Up @@ -1068,7 +922,7 @@ static long vfio_ioctl_set_iommu(struct vfio_container *container,
}

mutex_lock(&vfio.iommu_drivers_lock);
vfio_for_each_iommu_driver(container, driver) {
list_for_each_entry(driver, &vfio.iommu_drivers_list, vfio_next) {
void *data;

if (!try_module_get(driver->ops->owner))
Expand Down Expand Up @@ -1333,9 +1187,6 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
if (atomic_read(&group->container_users))
return -EINVAL;

if (group->noiommu && !capable(CAP_SYS_RAWIO))
return -EPERM;

f = fdget(container_fd);
if (!f.file)
return -EBADF;
Expand All @@ -1351,13 +1202,6 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)

down_write(&container->group_lock);

/* Real groups and fake groups cannot mix */
if (!list_empty(&container->group_list) &&
container->noiommu != group->noiommu) {
ret = -EPERM;
goto unlock_out;
}

driver = container->iommu_driver;
if (driver) {
ret = driver->ops->attach_group(container->iommu_data,
Expand All @@ -1367,7 +1211,6 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
}

group->container = container;
container->noiommu = group->noiommu;
list_add(&group->container_next, &container->group_list);

/* Get a reference on the container and mark a user within the group */
Expand Down Expand Up @@ -1398,9 +1241,6 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
!group->container->iommu_driver || !vfio_group_viable(group))
return -EINVAL;

if (group->noiommu && !capable(CAP_SYS_RAWIO))
return -EPERM;

device = vfio_device_get_from_name(group, buf);
if (!device)
return -ENODEV;
Expand Down Expand Up @@ -1443,10 +1283,6 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)

fd_install(ret, filep);

if (group->noiommu)
dev_warn(device->dev, "vfio-noiommu device opened by user "
"(%s:%d)\n", current->comm, task_pid_nr(current));

return ret;
}

Expand Down Expand Up @@ -1535,11 +1371,6 @@ static int vfio_group_fops_open(struct inode *inode, struct file *filep)
if (!group)
return -ENODEV;

if (group->noiommu && !capable(CAP_SYS_RAWIO)) {
vfio_group_put(group);
return -EPERM;
}

/* Do we need multiple instances of the group open? Seems not. */
opened = atomic_cmpxchg(&group->opened, 0, 1);
if (opened) {
Expand Down Expand Up @@ -1702,11 +1533,6 @@ struct vfio_group *vfio_group_get_external_user(struct file *filep)
if (!atomic_inc_not_zero(&group->container_users))
return ERR_PTR(-EINVAL);

if (group->noiommu) {
atomic_dec(&group->container_users);
return ERR_PTR(-EPERM);
}

if (!group->container->iommu_driver ||
!vfio_group_viable(group)) {
atomic_dec(&group->container_users);
Expand Down
Loading

0 comments on commit 6764e5e

Please sign in to comment.