Subject: ELF loader doesn't mprotect(PROT_EXEC).
To: None <tech-x11@netbsd.org>
From: Aymeric Vincent <Aymeric.Vincent@labri.fr>
List: port-macppc
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;