[flashrom] [PATCH] Acquire I/O privileges only if needed for mmap access to PCI resources

Ed Swierk eswierk at skyportsystems.com
Mon Mar 2 18:50:08 CET 2015


On Linux, /dev/mem can be used to access PCI device resources without
first calling iopl() to obtain I/O privileges.  Skipping the iopl()
call allows several flashrom programmers to work on a grsecurity kernel
with GRKERNSEC_IO=y, which blocks calls to iopl() while permitting
selective /dev/mem access.

With this patch, pcidev_init() calls rget_io_perms() automatically
on non-Linux systems.  rget_io_perms() is no longer called explicitly
by programmers that use only mmapped access to PCI resources.

I have tested this patch on a Debian sid system, Linux 3.14.30 kernel
with grsecurity (GRKERNSEC_KMEM=y, GRKERNSEC_IO=y, STRICT_DEVMEM=y),
successfully programming the SPI flash on an Intel 10G NIC using the
nicintel_spi programmer.  I have not tested any other programmers or
system configurations.

Signed-off-by: Ed Swierk <eswierk at skyportsystems.com>
---
 atavia.c          | 3 ---
 drkaiser.c        | 3 ---
 gfxnvidia.c       | 3 ---
 it8212.c          | 3 ---
 nicintel.c        | 6 ------
 nicintel_eeprom.c | 3 ---
 nicintel_spi.c    | 3 ---
 ogp_spi.c         | 3 ---
 pcidev.c          | 6 ++++++
 satasii.c         | 3 ---
 10 files changed, 6 insertions(+), 30 deletions(-)

diff --git a/atavia.c b/atavia.c
index db29eea..1bcdda5 100644
--- a/atavia.c
+++ b/atavia.c
@@ -143,9 +143,6 @@ int atavia_init(void)
 	}
 	free(arg);
 
-	if (rget_io_perms())
-		return 1;
-
 	dev = pcidev_init(ata_via, PCI_ROM_ADDRESS); /* Acutally no BAR setup needed at all. */
 	if (!dev)
 		return 1;
diff --git a/drkaiser.c b/drkaiser.c
index 75cc085..7ccdd07 100644
--- a/drkaiser.c
+++ b/drkaiser.c
@@ -61,9 +61,6 @@ int drkaiser_init(void)
 	struct pci_dev *dev = NULL;
 	uint32_t addr;
 
-	if (rget_io_perms())
-		return 1;
-
 	dev = pcidev_init(drkaiser_pcidev, PCI_BASE_ADDRESS_2);
 	if (!dev)
 		return 1;
diff --git a/gfxnvidia.c b/gfxnvidia.c
index 1e5a23a..d1635b0 100644
--- a/gfxnvidia.c
+++ b/gfxnvidia.c
@@ -82,9 +82,6 @@ int gfxnvidia_init(void)
 	struct pci_dev *dev = NULL;
 	uint32_t reg32;
 
-	if (rget_io_perms())
-		return 1;
-
 	dev = pcidev_init(gfx_nvidia, PCI_BASE_ADDRESS_0);
 	if (!dev)
 		return 1;
diff --git a/it8212.c b/it8212.c
index 460e820..417ffc7 100644
--- a/it8212.c
+++ b/it8212.c
@@ -51,9 +51,6 @@ static const struct par_master par_master_it8212 = {
 
 int it8212_init(void)
 {
-	if (rget_io_perms())
-		return 1;
-
 	struct pci_dev *dev = pcidev_init(devs_it8212, PCI_ROM_ADDRESS);
 	if (!dev)
 		return 1;
diff --git a/nicintel.c b/nicintel.c
index 69b40d3..ad8a0b2 100644
--- a/nicintel.c
+++ b/nicintel.c
@@ -64,12 +64,6 @@ int nicintel_init(void)
 	struct pci_dev *dev = NULL;
 	uintptr_t addr;
 
-	/* Needed only for PCI accesses on some platforms.
-	 * FIXME: Refactor that into get_mem_perms/rget_io_perms/get_pci_perms?
-	 */
-	if (rget_io_perms())
-		return 1;
-
 	/* FIXME: BAR2 is not available if the device uses the CardBus function. */
 	dev = pcidev_init(nics_intel, PCI_BASE_ADDRESS_2);
 	if (!dev)
diff --git a/nicintel_eeprom.c b/nicintel_eeprom.c
index b5d4202..3aba21d 100644
--- a/nicintel_eeprom.c
+++ b/nicintel_eeprom.c
@@ -295,9 +295,6 @@ static int nicintel_ee_shutdown(void *eecp)
 
 int nicintel_ee_init(void)
 {
-	if (rget_io_perms())
-		return 1;
-
 	struct pci_dev *dev = pcidev_init(nics_intel_ee, PCI_BASE_ADDRESS_0);
 	if (!dev)
 		return 1;
diff --git a/nicintel_spi.c b/nicintel_spi.c
index 9195c79..fa93d08 100644
--- a/nicintel_spi.c
+++ b/nicintel_spi.c
@@ -187,9 +187,6 @@ int nicintel_spi_init(void)
 	struct pci_dev *dev = NULL;
 	uint32_t tmp;
 
-	if (rget_io_perms())
-		return 1;
-
 	dev = pcidev_init(nics_intel_spi, PCI_BASE_ADDRESS_0);
 	if (!dev)
 		return 1;
diff --git a/ogp_spi.c b/ogp_spi.c
index 929ecd9..73993c1 100644
--- a/ogp_spi.c
+++ b/ogp_spi.c
@@ -125,9 +125,6 @@ int ogp_spi_init(void)
 	}
 	free(type);
 
-	if (rget_io_perms())
-		return 1;
-
 	dev = pcidev_init(ogp_spi, PCI_BASE_ADDRESS_0);
 	if (!dev)
 		return 1;
diff --git a/pcidev.c b/pcidev.c
index 2c78063..6655987 100644
--- a/pcidev.c
+++ b/pcidev.c
@@ -165,6 +165,12 @@ static int pcidev_shutdown(void *data)
 
 int pci_init_common(void)
 {
+#if IS_LINUX
+	/* On Linux, I/O privileges are not needed for mmap access to PCI resources in /dev/mem. */
+#else
+	if (rget_io_perms())
+		return 1;
+#endif
 	if (pacc != NULL) {
 		msg_perr("%s: Tried to allocate a new PCI context, but there is still an old one!\n"
 			 "Please report a bug at flashrom at flashrom.org\n", __func__);
diff --git a/satasii.c b/satasii.c
index 368d7d4..63eb788 100644
--- a/satasii.c
+++ b/satasii.c
@@ -74,9 +74,6 @@ int satasii_init(void)
 	uint32_t addr;
 	uint16_t reg_offset;
 
-	if (rget_io_perms())
-		return 1;
-
 	dev = pcidev_init(satas_sii, PCI_BASE_ADDRESS_0);
 	if (!dev)
 		return 1;
-- 
1.9.1





More information about the flashrom mailing list