[PATCH] 1.3.0.0 X86EMU: added blacklist for I/O port in 0-0xFF range

Bart Trojanowski bart at jukie.net
Fri Jan 11 12:49:35 PST 2008


This patch adds a test just before x86emu accesses real I/O ports.  The
intent is to prevent access to ports that are know to be under the
kernel's control.  Accessing these from the X process could cause
catastrophic failure of the system.

If such an access is detected, we terminate X "gracefully" by sending a
SIGSEGV signal which is picked up by xf86SigHandler() which dumps the
backtrace and exits gracefully.

Signed-off-by: Bart Trojanowski <bart at jukie.net>
---
 hw/xfree86/int10/helper_exec.c |   80 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 80 insertions(+), 0 deletions(-)

diff --git a/hw/xfree86/int10/helper_exec.c b/hw/xfree86/int10/helper_exec.c
index befc18e..99d5937 100644
--- a/hw/xfree86/int10/helper_exec.c
+++ b/hw/xfree86/int10/helper_exec.c
@@ -19,6 +19,8 @@
 #endif
 
 #include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
 
 #include <X11/Xos.h>
 #include "xf86.h"
@@ -203,6 +205,72 @@ stack_trace(xf86Int10InfoPtr pInt)
 	xf86ErrorFVerb(3, "\n");
 }
 
+enum port_action_e {
+	PORT_ACTION_PERMIT,
+	PORT_ACTION_WARN,
+	PORT_ACTION_BAIL,
+	PORT_ACTION_MAX
+};
+
+static const struct port_range {
+	CARD16 start, end;
+	enum port_action_e access;
+} port_range_table[] = {
+	// NOTE: port ranges are non overlapping and sorted
+	{ 0x00, 0x1f, PORT_ACTION_BAIL },	// DMA
+	{ 0x20, 0x21, PORT_ACTION_BAIL },	// PIC
+	{ 0x40, 0x47, PORT_ACTION_BAIL },	// PIT 1&2
+	{ 0x50, 0x53, PORT_ACTION_BAIL },
+	{ 0x70, 0x77, PORT_ACTION_BAIL },	// CMOS/RTC
+	{ 0x81, 0x8f, PORT_ACTION_BAIL },	// DIAG REGS
+	{ 0xa0, 0xa1, PORT_ACTION_BAIL },	// PIC2
+	{ 0xc0, 0xdf, PORT_ACTION_BAIL },	// DMA
+};
+#define ARRAY_SIZE(X) (sizeof((X)) / (sizeof(*(X))))
+#define ARRAY_END(X)  (&((X)[ARRAY_SIZE(X)]))
+
+static void assert_port_access_allowed (CARD16 port, CARD16 width)
+{
+	CARD16 access_start, access_end;
+	const struct port_range *pr, *pr_start, *pr_end;
+
+	access_start = port;
+	access_end = port + width - 1;
+
+	// TODO: if the list gets too long we should do a binary search
+	//        or convert the port list to a bitmap representation
+	pr_start = port_range_table;
+	pr_end   = ARRAY_END(port_range_table);
+
+	for (pr = pr_start; pr < pr_end; pr++) {
+		if (access_end < pr->start)
+			continue;
+		if (access_start > pr->end)
+			break;
+
+		// we are in the pr range now
+		switch (pr->access) {
+		default:
+			continue;
+		case PORT_ACTION_BAIL:
+		case PORT_ACTION_WARN:
+			break;
+		}
+
+		ErrorF("Emulator asked to make a suspect %saccess to "
+				"port %u (0x%04x)%s\n",
+				(width == 1) ? "byte " :
+				(width == 2) ? "word " :
+				(width == 4) ? "long " : "",
+				port, port,
+				(pr->access == PORT_ACTION_BAIL)
+				? "; terminating." : "ignoring.");
+
+		if (pr->access == PORT_ACTION_BAIL)
+			kill(getpid(), SIGSEGV);
+	}
+}
+
 int
 port_rep_inb(xf86Int10InfoPtr pInt,
 	     CARD16 port, CARD32 base, int d_f, CARD32 count)
@@ -328,6 +396,8 @@ x_inb(CARD16 port)
 	}
 #endif /* __NOT_YET__ */
     } else {
+	assert_port_access_allowed (port, sizeof(val));
+
 	if (!pciCfg1inb(port, &val))
 	    val = inb(Int10Current->ioBase + port);
 #ifdef PRINT_PORT
@@ -352,6 +422,8 @@ x_inw(CARD16 port)
 	X_GETTIMEOFDAY(&tv);
 	val = (CARD16)(tv.tv_usec / 3);
     } else {
+	assert_port_access_allowed (port, sizeof(val));
+
 	if (!pciCfg1inw(port, &val))
 	    val = inw(Int10Current->ioBase + port);
     }
@@ -390,6 +462,8 @@ x_outb(CARD16 port, CARD8 val)
 #ifdef PRINT_PORT
 	ErrorF(" outb(%#x, %2.2x)\n", port, val);
 #endif
+	assert_port_access_allowed (port, sizeof(val));
+
 	if (!pciCfg1outb(port, val))
 	    outb(Int10Current->ioBase + port, val);
     }
@@ -402,6 +476,8 @@ x_outw(CARD16 port, CARD16 val)
     ErrorF(" outw(%#x, %4.4x)\n", port, val);
 #endif
 
+    assert_port_access_allowed (port, sizeof(val));
+
     if (!pciCfg1outw(port, val))
 	outw(Int10Current->ioBase + port, val);
 }
@@ -411,6 +487,8 @@ x_inl(CARD16 port)
 {
     CARD32 val;
 
+    assert_port_access_allowed (port, sizeof(val));
+
     if (!pciCfg1in(port, &val))
 	val = inl(Int10Current->ioBase + port);
 
@@ -427,6 +505,8 @@ x_outl(CARD16 port, CARD32 val)
     ErrorF(" outl(%#x, %8.8x)\n", port, val);
 #endif
 
+    assert_port_access_allowed (port, sizeof(val));
+
     if (!pciCfg1out(port, val))
 	outl(Int10Current->ioBase + port, val);
 }
-- 
1.5.3.7.1150.g149d432



More information about the xorg mailing list