Subject: ELF loader doesn't mprotect(PROT_EXEC).
To: None <tech-x11@netbsd.org>
From: Aymeric Vincent <Aymeric.Vincent@labri.fr>
List: tech-x11
Date: 10/21/2004 17:51:03
Hi,
XFree86's elfloader.c doesn't set the execution bit on the memory
containing the modules it loads.
On my iBook, this results in the X server aborting as soon as I put
some stress on the machine. Currently, doing a make update on a package
would make the X server crash within seconds.
The following patch seems to DTRT for me, and is pretty
straightforward, since the code was there, but #ifdef __OpenBSD__.
Now, my real question is: how come no one stumbled on this much
earlier?? I can understand that on powerpc it requires a bit of bad
luck for these pages to fall into a ~EXEC segment, but the bug should
be triggered immediately on many other architectures...
Please enlighten me. :-)
Regards,
Aymeric
Index: elfloader.c
===================================================================
RCS file: /cvsroot/xsrc/xfree/xc/programs/Xserver/hw/xfree86/loader/elfloader.c,v
retrieving revision 1.2
diff -u -u -r1.2 elfloader.c
--- elfloader.c 28 Mar 2004 15:24:25 -0000 1.2
+++ elfloader.c 21 Oct 2004 15:43:16 -0000
@@ -758,7 +758,7 @@
symbol->address = (char *)&symbol->code.plt[0];
symval = (Elf_Addr) symbol->address;
ppc_flush_icache(&symbol->code.plt[0]);
- ppc_flush_icache(&symbol->code.plt[6]);
+ ppc_flush_icache(&symbol->code.plt[6]); /* XXX why 6? */
break;
default:
symval = 0;
@@ -921,7 +921,7 @@
ErrorF("ELFCreateGOT() Unable to reallocate memory!!!!\n");
return FALSE;
}
-# if defined(linux) && defined(__ia64__) || defined(__OpenBSD__)
+# if defined(linux) && defined(__ia64__) || defined(__OpenBSD__) || defined(__NetBSD__)
{
unsigned long page_size = getpagesize();
unsigned long round;
@@ -2772,7 +2772,7 @@
elffile->lsection[j].size = SecSize(i);
elffile->lsection[j].flags = flags;
switch (SecType(i)) {
-#ifdef __OpenBSD__
+#if defined(__OpenBSD__) || defined(__NetBSD__)
case SHT_PROGBITS:
mprotect(elffile->lsection[j].saddr, SecSize(i),
PROT_READ | PROT_WRITE | PROT_EXEC);
@@ -2970,7 +2970,7 @@
ErrorF("Unable to allocate ELF sections\n");
return NULL;
}
-# if defined(linux) && defined(__ia64__) || defined(__OpenBSD__)
+# if defined(linux) && defined(__ia64__) || defined(__OpenBSD__) || defined(__NetBSD__)
{
unsigned long page_size = getpagesize();
unsigned long round;