From 2e85ea08a32706d7787fa7ec0e9873a49b1e52b8 Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Fri, 9 Nov 2018 22:17:46 -0500 Subject: 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. --- 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(-) 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 */ ; -- cgit v1.2.3