summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEgbert Eich <eich@ovid.suse.de>2008-11-21 18:50:01 +0100
committerEgbert Eich <eich@ovid.suse.de>2008-11-21 18:57:07 +0100
commita9e20306fbe3262602f21b876a52a1ef38cdf20a (patch)
treec68edbc03ea72d45c9ea0cb159b8e41b2729e42a
parenta54153e669fd293a47f0077bf25505dd545ddce2 (diff)
int10: Do an mprotect(..,PROT_EXEC) on shmat()ed memory ranges.
When the linux kernel sets the NX bit vm86 segfaults when it tries to execute code in memory that is not marked EXEC. Such code gets called whenever we return from a VBIOS call to signal the calling program that the call is actually finished and that we are not trapping for other reasons (like IO accesses). Use mprotect(2) to set these memory ranges PROT_EXEC.
-rw-r--r--hw/xfree86/os-support/linux/int10/linux.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/hw/xfree86/os-support/linux/int10/linux.c b/hw/xfree86/os-support/linux/int10/linux.c
index 67eb16107..b15f7fdc4 100644
--- a/hw/xfree86/os-support/linux/int10/linux.c
+++ b/hw/xfree86/os-support/linux/int10/linux.c
@@ -1,6 +1,6 @@
/*
* linux specific part of the int10 module
- * Copyright 1999, 2000, 2001, 2002, 2003, 2004 Egbert Eich
+ * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2008 Egbert Eich
*/
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
@@ -357,7 +357,10 @@ MapCurrentInt10(xf86Int10InfoPtr pInt)
"shmat(low_mem) error: %s\n",strerror(errno));
return FALSE;
}
-
+ if (mprotect((void*)0, V_RAM, PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
+ xf86DrvMsg(pInt->scrnIndex, X_ERROR,
+ "Cannot set EXEC bit on low memory: %s\n", strerror(errno));
+
if (((linuxInt10Priv*)pInt->private)->highMem >= 0) {
addr = shmat(((linuxInt10Priv*)pInt->private)->highMem,
(char*)HIGH_MEM, 0);
@@ -368,6 +371,11 @@ MapCurrentInt10(xf86Int10InfoPtr pInt)
"shmget error: %s\n",strerror(errno));
return FALSE;
}
+ if (mprotect((void*)HIGH_MEM, HIGH_MEM_SIZE,
+ PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
+ xf86DrvMsg(pInt->scrnIndex, X_ERROR,
+ "Cannot set EXEC bit on high memory: %s\n",
+ strerror(errno));
} else {
if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) {
if (mmap((void *)(V_BIOS), SYS_BIOS - V_BIOS,