Restrict access to PCI cfg io ports to one process

Message ID 20181205222528.25579-1-samuel.thibault@ens-lyon.org
State Not applicable, archived
Headers

Commit Message

Samuel Thibault Dec. 5, 2018, 10:25 p.m. UTC
  From: Damien Zammit <damien@zamaudio.com>

---
 i386/i386/io_perm.c                   | 27 ++++++++++++++++++++++-----
 i386/i386/io_perm.h                   |  2 --
 i386/include/mach/i386/mach_i386.defs |  2 --
 3 files changed, 22 insertions(+), 9 deletions(-)
  

Comments

Samuel Thibault Dec. 5, 2018, 10:26 p.m. UTC | #1
Oops, sorry, that was a remnant in the same directory.

Samuel
  

Patch

diff --git a/i386/i386/io_perm.c b/i386/i386/io_perm.c
index 3224fdd3..086d1d8f 100644
--- a/i386/i386/io_perm.c
+++ b/i386/i386/io_perm.c
@@ -67,10 +67,22 @@ 
 #include "io_perm.h"
 #include "gdt.h"
 #include "pcb.h"
+
+#define PCI_CFG1_START	0xcf8
+#define PCI_CFG1_END	0xcff
+#define PCI_CFG2_START	0xc000
+#define PCI_CFG2_END	0xcfff
+
+#define IS_IN_PROTECTED_RANGE(from, to) \
+  ( ( ( from <= PCI_CFG1_END ) && ( to >= PCI_CFG1_START ) ) || \
+    ( ( from <= PCI_CFG2_END ) && ( to >= PCI_CFG2_START ) ) )
+
 
 /* Our device emulation ops.  See below, at the bottom of this file.  */
 static struct device_emulation_ops io_perm_device_emulation_ops;
 
+/* Flag to hold PCI io cfg access lock */
+static boolean_t taken_pci_cfg = FALSE;
 
 /* The outtran which allows MIG to convert an io_perm_t object to a port
    representing it.  */
@@ -107,17 +119,15 @@  convert_port_to_io_perm (ipc_port_t port)
   return io_perm;
 }
 
-#if TODO_REMOVE_ME
-/* TODO.  Fix this comment.  */
 /* The destructor which is called when the last send right to a port
    representing an io_perm_t object vanishes.  */
 void
 io_perm_deallocate (io_perm_t io_perm)
 {
-  /* TODO.  Is there anything to deallocate in here?  I don't think so, as we
-     don't allocate anything in `convert_port_to_io_perm'.  */
+  /* We need to check if the io_perm was a PCI cfg one and release it */
+  if (IS_IN_PROTECTED_RANGE(io_perm->from, io_perm->to))
+    taken_pci_cfg = FALSE;
 }
-#endif
 
 /* Our ``no senders'' handling routine.  Deallocate the object.  */
 static
@@ -185,6 +195,10 @@  i386_io_perm_create (const ipc_port_t master_port, io_port_t from, io_port_t to,
   if (from > to)
     return KERN_INVALID_ARGUMENT;
 
+  /* Only one process may take a range that includes PCI cfg registers */
+  if (taken_pci_cfg && IS_IN_PROTECTED_RANGE(from, to))
+    return KERN_PROTECTION_FAILURE;
+
   io_perm_t io_perm;
 
   io_perm = (io_perm_t) kalloc (sizeof *io_perm);
@@ -216,6 +230,9 @@  i386_io_perm_create (const ipc_port_t master_port, io_port_t from, io_port_t to,
 
   *new = io_perm;
 
+  if (IS_IN_PROTECTED_RANGE(from, to))
+    taken_pci_cfg = TRUE;
+
   return KERN_SUCCESS;
 }
 
diff --git a/i386/i386/io_perm.h b/i386/i386/io_perm.h
index a7f1f6fe..b97cf973 100644
--- a/i386/i386/io_perm.h
+++ b/i386/i386/io_perm.h
@@ -58,8 +58,6 @@  typedef struct io_perm *io_perm_t;
 
 extern io_perm_t convert_port_to_io_perm (ipc_port_t);
 extern ipc_port_t convert_io_perm_to_port (io_perm_t);
-#if TODO_REMOVE_ME
 extern void io_perm_deallocate (io_perm_t);
-#endif
 
 #endif /* _I386_IO_PERM_H_ */
diff --git a/i386/include/mach/i386/mach_i386.defs b/i386/include/mach/i386/mach_i386.defs
index 0703d59a..a8cb91ce 100644
--- a/i386/include/mach/i386/mach_i386.defs
+++ b/i386/include/mach/i386/mach_i386.defs
@@ -51,9 +51,7 @@  type	io_perm_t	=	mach_port_t
 #if	KERNEL_SERVER
 		intran: io_perm_t convert_port_to_io_perm(mach_port_t)
 		outtran: mach_port_t convert_io_perm_to_port(io_perm_t)
-#if TODO_REMOVE_ME
 		destructor: io_perm_deallocate(io_perm_t)
-#endif
 #endif	/* KERNEL_SERVER */
 		;