0.9.4.16:
authorJuho Snellman <jsnell@iki.fi>
Wed, 31 Aug 2005 13:12:17 +0000 (13:12 +0000)
committerJuho Snellman <jsnell@iki.fi>
Wed, 31 Aug 2005 13:12:17 +0000 (13:12 +0000)
"I feel safer already".

Add a horrible kludge to work around the new Linux kernel
security features for randomizing memory maps.
* Before setting up the memory maps, check whether we're running
  on 2.6 or newer. If so, check where the ADDR_NO_RANDOMIZE
  personality flag is set. If not, set the flag and re-execute
  the program.
* Follow the /proc/self/exe symlink to find out what binary
  we should be executing. (Can't execute /proc/self/exe
  directly, since some proc-groveling tools will then show
  the name of the process as "exe").
* For more details, see the sbcl-devel threads "Memory randomization
  problems coming" and "memory randomization patch" in 2005-08.

NEWS
src/runtime/bsd-os.c
src/runtime/linux-os.c
src/runtime/os.h
src/runtime/osf1-os.c
src/runtime/runtime.c
src/runtime/sunos-os.c
version.lisp-expr

diff --git a/NEWS b/NEWS
index 44e11b1..c6a1956 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,10 @@ changes in sbcl-0.9.5 relative to sbcl-0.9.4:
     more sigsegvs when receiving a signal to soon
   * optimization: Faster 32-bit SB-ROTATE-BYTE:ROTATE-BYTE on non-x86/ppc
     platforms
+  * bug fix: add a workaround for the memory randomization features in
+    Linux kernels >= 2.6.12 that interfere with SBCL's memory maps. This
+    workaround will only be in effect on systems with the proc filesystem
+    mounted.
   * threads
     ** bug fix: parent thread now can be gc'ed even with a live
        child thread
index 3199a86..f41911d 100644 (file)
@@ -51,7 +51,8 @@ os_vm_size_t os_vm_page_size;
 static void netbsd_init();
 #endif /* __NetBSD__ */
 
-void os_init(void)
+void
+os_init(char *argv[], char *envp[])
 {
     os_vm_page_size = getpagesize();
 
index 222f0af..a283abb 100644 (file)
 #include "gencgc-internal.h"
 #endif
 
+#ifdef LISP_FEATURE_LINUX
+#include <sys/personality.h>
+#endif
+
 size_t os_vm_page_size;
 
 #ifdef LISP_FEATURE_SB_THREAD
@@ -92,7 +96,7 @@ int linux_sparc_siginfo_bug = 0;
 int linux_no_threads_p = 0;
 
 void
-os_init(void)
+os_init(char *argv[], char *envp[])
 {
     /* Conduct various version checks: do we have enough mmap(), is
      * this a sparc running 2.2, can we do threads? */
@@ -125,6 +129,37 @@ os_init(void)
         fprintf(stderr,"Linux with NPTL support (e.g. kernel 2.6 or newer) required for \nthread-enabled SBCL.  Disabling thread support.\n\n");
 #endif
     os_vm_page_size = getpagesize();
+
+    /* KLUDGE: Disable memory randomization on new Linux kernels
+     * by setting a personality flag and re-executing. (We need
+     * to re-execute, since the memory maps that can conflict with
+     * the SBCL spaces have already been done at this point).
+     */
+#if defined(LISP_FEATURE_X86)
+    if ((major_version == 2 && minor_version >= 6)
+        || major_version >= 3)
+     {
+       long pers = personality(-1);
+       /* 0x40000 aka. ADDR_NO_RANDOMIZE */
+       if (!(pers & 0x40000)) {
+          if (personality(pers | 0x40000) != -1) {
+             char runtime[PATH_MAX+1];
+             /* Use /proc/self/exe instead of trying to figure out the
+              * executable path from PATH and argv[0], since that's
+              * unreliable.
+              */
+             if (readlink("/proc/self/exe", runtime, PATH_MAX) != -1) {
+                execve(runtime, argv, envp);
+             }
+          }
+          /* Either changing the personality or execve() failed. Either
+           * way we might as well continue, and hope that the random
+           * memory maps are ok this time around.
+           */
+          fprintf(stderr, "WARNING: Couldn't re-execute SBCL with the proper personality flags (maybe /proc isn't mounted?). Trying to continue anyway.\n");
+       }
+    }
+#endif
 }
 
 
index 7d24639..3cf3f2d 100644 (file)
@@ -50,7 +50,7 @@ extern os_vm_size_t os_vm_page_size;
 
 /* Do anything we need to do when starting up the runtime environment
  * in this OS. */
-extern void os_init(void);
+extern void os_init(char *argv[], char *envp[]);
 
 /* Install any OS-dependent low-level signal handlers which are needed
  * by the runtime environment. E.g. the signals raised by a violation
index e6f704c..5e22940 100644 (file)
@@ -51,7 +51,8 @@ size_t os_vm_page_size;
 
 \f
 
-void os_init(void)
+void
+os_init(char *argv[], char *envp[])
 {
     os_vm_page_size = getpagesize();
 }
index 8dbc76c..cb6fcb0 100644 (file)
@@ -199,7 +199,7 @@ main(int argc, char *argv[], char *envp[])
     /* KLUDGE: os_vm_page_size is set by os_init(), and on some
      * systems (e.g. Alpha) arch_init() needs need os_vm_page_size, so
      * it must follow os_init(). -- WHN 2000-01-26 */
-    os_init();
+    os_init(argv, envp);
     arch_init();
     gc_init();
     validate();
index 0a47dd3..3bd9f45 100644 (file)
@@ -53,7 +53,8 @@ static os_vm_size_t real_page_size_difference=0;
 int KLUDGE_MAYBE_MAP_ANON = 0x0;
 int kludge_mmap_fd = -1; /* default for MAP_ANON */
 
-void os_init(void)
+void
+os_init(char *argv[], char *envp[])
 {
     struct utsname name;
     int major_version;
index b44c564..130b2e6 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.9.4.15"
+"0.9.4.16"