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