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