summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2018-11-09 22:17:46 -0500
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2018-12-05 22:37:02 +0100
commit2e85ea08a32706d7787fa7ec0e9873a49b1e52b8 (patch)
tree54f1f75923b564413b566ca20dc6b0e71e85482d
parente952f70189bf34039453334b725a0da70086873e (diff)
Restrict access to PCI cfg io ports to one process
* i386/i386/io_perm.c (PCI_CFG1_START, PCI_CFG1_END, PCI_CFG2_START, PCI_CFG2_END, IS_IN_PROTECTED_RANGE): New macros. (taken_pci_cfg): New variable. (io_perm_deallocate): New function. (i386_io_perm_create): Return KERN_PROTECTION_FAILURE if requested port range contains PCI config registers and that is already taken. Set taken_pci_cfg to true when taking them. * i386/i386/io_perm.h (io_perm_deallocate): New declaration. * i386/include/mach/i386/mach_i386.defs (io_perm_t): Add io_perm_deallocate destructor.
-rw-r--r--i386/i386/io_perm.c27
-rw-r--r--i386/i386/io_perm.h2
-rw-r--r--i386/include/mach/i386/mach_i386.defs2
3 files changed, 22 insertions, 9 deletions
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 */
;