>From 8f5525e8d46b5cf47d7eaaeb92cdc247464cf1ac Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Fri, 9 Nov 2018 22:17:46 -0500 Subject: [PATCH] Restrict access to PCI cfg io ports to one process --- i386/i386/io_perm.c | 26 +++++++++++++++++++++----- i386/i386/io_perm.h | 2 -- i386/include/mach/i386/mach_i386.defs | 2 -- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/i386/i386/io_perm.c b/i386/i386/io_perm.c index 3224fdd3..381c9321 100644 --- a/i386/i386/io_perm.c +++ b/i386/i386/io_perm.c @@ -67,10 +67,16 @@ #include "io_perm.h" #include "gdt.h" #include "pcb.h" + +#define PCI_CFG1_ADDRESS_REG 0xcf8 +#define PCI_CFG1_DATA_REG 0xcfc + /* 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 +113,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 (io_perm->from <= PCI_CFG1_ADDRESS_REG && io_perm->to >= PCI_CFG1_DATA_REG) + taken_pci_cfg = FALSE; } -#endif /* Our ``no senders'' handling routine. Deallocate the object. */ static @@ -177,6 +181,8 @@ kern_return_t i386_io_perm_create (const ipc_port_t master_port, io_port_t from, io_port_t to, io_perm_t *new) { + boolean_t in_pcicfg_range = FALSE; + if (master_port != master_device_port) return KERN_INVALID_ARGUMENT; @@ -185,6 +191,13 @@ 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; + if (from <= PCI_CFG1_ADDRESS_REG && to >= PCI_CFG1_DATA_REG) + in_pcicfg_range = TRUE; + + /* Only one process may take a range that includes PCI cfg registers */ + if (taken_pci_cfg && in_pcicfg_range) + return KERN_PROTECTION_FAILURE; + io_perm_t io_perm; io_perm = (io_perm_t) kalloc (sizeof *io_perm); @@ -216,6 +229,9 @@ i386_io_perm_create (const ipc_port_t master_port, io_port_t from, io_port_t to, *new = io_perm; + if (in_pcicfg_range) + 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 */ ; -- 2.17.1