| From: Matthew Garrett <matthew.garrett@nebula.com> |
| Date: Thu, 8 Mar 2012 10:10:38 -0500 |
| Subject: [PATCH] PCI: Lock down BAR access when module security is enabled |
| |
| Any hardware that can potentially generate DMA has to be locked down from |
| userspace in order to avoid it being possible for an attacker to modify |
| kernel code, allowing them to circumvent disabled module loading or module |
| signing. Default to paranoid - in future we can potentially relax this for |
| sufficiently IOMMU-isolated devices. |
| |
| Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com> |
| |
| drivers/pci/pci-sysfs.c | 10 ++++++++++ |
| drivers/pci/proc.c | 8 +++++++- |
| drivers/pci/syscall.c | 3 ++- |
| 3 files changed, 19 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c |
| index 6d04771e4903..f8886fe74b9d 100644 |
| |
| |
| @@ -30,6 +30,7 @@ |
| #include <linux/vgaarb.h> |
| #include <linux/pm_runtime.h> |
| #include <linux/of.h> |
| +#include <linux/module.h> |
| #include "pci.h" |
| |
| static int sysfs_initialized; /* = 0 */ |
| @@ -704,6 +705,9 @@ static ssize_t pci_write_config(struct file *filp, struct kobject *kobj, |
| loff_t init_off = off; |
| u8 *data = (u8 *) buf; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| if (off > dev->cfg_size) |
| return 0; |
| if (off + count > dev->cfg_size) { |
| @@ -998,6 +1002,9 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, |
| resource_size_t start, end; |
| int i; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| for (i = 0; i < PCI_ROM_RESOURCE; i++) |
| if (res == &pdev->resource[i]) |
| break; |
| @@ -1099,6 +1106,9 @@ static ssize_t pci_write_resource_io(struct file *filp, struct kobject *kobj, |
| struct bin_attribute *attr, char *buf, |
| loff_t off, size_t count) |
| { |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| return pci_resource_io(filp, kobj, attr, buf, off, count, true); |
| } |
| |
| diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c |
| index 3f155e78513f..4265ea07e3b0 100644 |
| |
| |
| @@ -116,6 +116,9 @@ static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf, |
| int size = dev->cfg_size; |
| int cnt; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| if (pos >= size) |
| return 0; |
| if (nbytes >= size) |
| @@ -195,6 +198,9 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd, |
| #endif /* HAVE_PCI_MMAP */ |
| int ret = 0; |
| |
| + if (secure_modules()) |
| + return -EPERM; |
| + |
| switch (cmd) { |
| case PCIIOC_CONTROLLER: |
| ret = pci_domain_nr(dev->bus); |
| @@ -233,7 +239,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) |
| struct pci_filp_private *fpriv = file->private_data; |
| int i, ret; |
| |
| - if (!capable(CAP_SYS_RAWIO)) |
| + if (!capable(CAP_SYS_RAWIO) || secure_modules()) |
| return -EPERM; |
| |
| /* Make sure the caller is mapping a real resource for this device */ |
| diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c |
| index b91c4da68365..98f5637304d1 100644 |
| |
| |
| @@ -10,6 +10,7 @@ |
| #include <linux/errno.h> |
| #include <linux/pci.h> |
| #include <linux/syscalls.h> |
| +#include <linux/module.h> |
| #include <asm/uaccess.h> |
| #include "pci.h" |
| |
| @@ -92,7 +93,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn, |
| u32 dword; |
| int err = 0; |
| |
| - if (!capable(CAP_SYS_ADMIN)) |
| + if (!capable(CAP_SYS_ADMIN) || secure_modules()) |
| return -EPERM; |
| |
| dev = pci_get_bus_and_slot(bus, dfn); |
| -- |
| 1.9.3 |
| |