[Xorg-driver-geode] [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-driver-geode
mailing list