From 911be03206685adfca9eddfeaa7feb8e9080e835 Mon Sep 17 00:00:00 2001
From: rtoy <rtoy>
Date: Mon, 1 Feb 2010 15:16:09 +0000
Subject: [PATCH] Patch from Stelian Ionescu on cmucl-imp, 2010/02/01:

    When run on a kernel compiled without COMPAT_BRK CMUCL segfaults,
    so I copied the kludge used by SBCL - check the current
    personality, and if necessary, enable ADDR_NO_RANDOMIZE and
    re-exec itself.

Linux-os.c:
o Check for personality and rexec if necessary.

os.h:
o New prototype for os_init needed because it needs argv and envp.

lisp.c:
Darwin-os.c:
FreeBSD-os.c:
NetBSD-os.c:
OpenBSD-os.c:
hpux-os.c:
irix-os.c:
mach-os.c:
osf1-os.c:
solaris-os.c:
sunos-os.c:
o Update call to os_init, which needs argv and envp now.
---
 lisp/Darwin-os.c  |  4 +--
 lisp/FreeBSD-os.c |  4 +--
 lisp/Linux-os.c   | 86 +++++++++++++++++++++++++++++++++++++++++++++--
 lisp/NetBSD-os.c  |  4 +--
 lisp/OpenBSD-os.c |  4 +--
 lisp/hpux-os.c    |  4 +--
 lisp/irix-os.c    |  4 +--
 lisp/lisp.c       |  4 +--
 lisp/mach-os.c    |  4 +--
 lisp/os.h         |  4 +--
 lisp/osf1-os.c    |  4 +--
 lisp/solaris-os.c |  4 +--
 lisp/sunos-os.c   |  4 +--
 13 files changed, 108 insertions(+), 26 deletions(-)

diff --git a/lisp/Darwin-os.c b/lisp/Darwin-os.c
index c124ed60e..cd4bf2c2d 100644
--- a/lisp/Darwin-os.c
+++ b/lisp/Darwin-os.c
@@ -14,7 +14,7 @@
  * Frobbed for OpenBSD by Pierre R. Mai, 2001.
  * Frobbed for Darwin by Pierre R. Mai, 2003.
  *
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/Darwin-os.c,v 1.25 2009/01/06 00:06:46 rtoy Rel $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/Darwin-os.c,v 1.26 2010/02/01 15:16:08 rtoy Exp $
  *
  */
 
@@ -101,7 +101,7 @@ timebase_init(void)
 
 
 void
-os_init(void)
+os_init(char *argv[], char *envp[])
 {
     os_vm_page_size = OS_VM_DEFAULT_PAGESIZE;
 #ifdef __ppc__
diff --git a/lisp/FreeBSD-os.c b/lisp/FreeBSD-os.c
index 4f5e9a019..cd1cc2d4c 100644
--- a/lisp/FreeBSD-os.c
+++ b/lisp/FreeBSD-os.c
@@ -12,7 +12,7 @@
  * Much hacked by Paul Werkowski
  * GENCGC support by Douglas Crosher, 1996, 1997.
  *
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/FreeBSD-os.c,v 1.31 2009/10/15 15:05:51 rtoy Exp $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/FreeBSD-os.c,v 1.32 2010/02/01 15:16:08 rtoy Exp $
  *
  */
 
@@ -39,7 +39,7 @@
 vm_size_t os_vm_page_size;
 
 void
-os_init(void)
+os_init(char *argv[], char *envp[])
 {
     os_vm_page_size = getpagesize();
 }
diff --git a/lisp/Linux-os.c b/lisp/Linux-os.c
index 2679bd26a..26dc4037a 100644
--- a/lisp/Linux-os.c
+++ b/lisp/Linux-os.c
@@ -15,7 +15,7 @@
  * GENCGC support by Douglas Crosher, 1996, 1997.
  * Alpha support by Julian Dolby, 1999.
  *
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/Linux-os.c,v 1.46 2009/11/02 15:05:07 rtoy Exp $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/Linux-os.c,v 1.47 2010/02/01 15:16:09 rtoy Exp $
  *
  */
 
@@ -51,8 +51,88 @@ size_t os_vm_page_size;
 #include "gencgc.h"
 #endif
 
+
+#if defined(__i386) || defined(__x86_64)
+/* Prototype for personality(2). Done inline here since the header file
+ * for this isn't available on old versions of glibc. */
+int personality (unsigned long);
+
+#if !defined(ADDR_NO_RANDOMIZE)
+#define ADDR_NO_RANDOMIZE 0x40000
+#endif
+/* From personality(2) */
+#define CURRENT_PERSONALITY 0xffffffffUL
+#endif
+
+void
+check_personality(struct utsname *name, char *argv[], char *envp[])
+{
+    /* 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 CMUCL spaces have already been done at this point).
+     *
+     * Since randomization is currently implemented only on x86 kernels,
+     * don't do this trick on other platforms.
+     */
+#if defined(__i386) || defined(__x86_64)
+    int major_version, minor_version, patch_version;
+    char *p;
+    p=name->release;
+    major_version=atoi(p);
+    p=strchr(p,'.')+1;
+    minor_version=atoi(p);
+    p=strchr(p,'.')+1;
+    patch_version=atoi(p);
+
+    if ((major_version == 2
+         /* Some old kernels will apparently lose unsupported personality flags
+          * on exec() */
+         && ((minor_version == 6 && patch_version >= 11)
+             || (minor_version > 6)
+             /* This is what RHEL 3 reports */
+             || (minor_version == 4 && patch_version > 20)))
+        || major_version >= 3)
+    {
+        int pers = personality(CURRENT_PERSONALITY);
+        if (!(pers & ADDR_NO_RANDOMIZE)) {
+            int retval = personality(pers | ADDR_NO_RANDOMIZE);
+            /* Allegedly some Linux kernels (the reported case was
+             * "hardened Linux 2.6.7") won't set the new personality,
+             * but nor will they return -1 for an error. So as a
+             * workaround query the new personality...
+             */
+            int newpers = personality(CURRENT_PERSONALITY);
+            /* ... and don't re-execute if either the setting resulted
+             * in an error or if the value didn't change. Otherwise
+             * this might result in an infinite loop.
+             */
+            if (retval != -1 && newpers != pers) {
+                /* Use /proc/self/exe instead of trying to figure out
+                 * the executable path from PATH and argv[0], since
+                 * that's unreliable. We follow the symlink instead of
+                 * executing the file directly in order to prevent top
+                 * from displaying the name of the process as "exe". */
+                char runtime[PATH_MAX+1];
+                int i = readlink("/proc/self/exe", runtime, PATH_MAX);
+                if (i != -1) {
+                    runtime[i] = '\0';
+                    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 CMUCL with the proper personality flags"
+                            "(maybe /proc isn't mounted?). Trying to continue anyway.\n");
+        }
+    }
+#endif
+}
+
 void
-os_init(void)
+os_init(char *argv[], char *envp[])
 {
     struct utsname name;
 
@@ -66,6 +146,8 @@ os_init(void)
     }
 
     os_vm_page_size = getpagesize();
+
+    check_personality(&name, argv, envp);
 }
 
 #ifdef __i386
diff --git a/lisp/NetBSD-os.c b/lisp/NetBSD-os.c
index 903f80a89..a2726332b 100644
--- a/lisp/NetBSD-os.c
+++ b/lisp/NetBSD-os.c
@@ -15,7 +15,7 @@
  * Frobbed for OpenBSD by Pierre R. Mai, 2001.
  * Frobbed for NetBSD by Pierre R. Mai, 2002.
  *
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/NetBSD-os.c,v 1.13 2009/10/16 13:38:02 rswindells Exp $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/NetBSD-os.c,v 1.14 2010/02/01 15:16:09 rtoy Exp $
  *
  */
 
@@ -45,7 +45,7 @@ size_t os_vm_page_size;
 
 
 void
-os_init(void)
+os_init(char *argv[], char *envp[])
 {
     os_vm_page_size = OS_VM_DEFAULT_PAGESIZE;
 }
diff --git a/lisp/OpenBSD-os.c b/lisp/OpenBSD-os.c
index 4e62ad3b0..fd784bdb1 100644
--- a/lisp/OpenBSD-os.c
+++ b/lisp/OpenBSD-os.c
@@ -13,7 +13,7 @@
  * GENCGC support by Douglas Crosher, 1996, 1997.
  * Frobbed for OpenBSD by Pierre R. Mai, 2001.
  *
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/OpenBSD-os.c,v 1.8 2008/12/07 02:33:55 agoncharov Rel $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/OpenBSD-os.c,v 1.9 2010/02/01 15:16:09 rtoy Exp $
  *
  */
 
@@ -41,7 +41,7 @@ vm_size_t os_vm_page_size;
 
 
 void
-os_init(void)
+os_init(char *argv[], char *envp[])
 {
     os_vm_page_size = OS_VM_DEFAULT_PAGESIZE;
 }
diff --git a/lisp/hpux-os.c b/lisp/hpux-os.c
index 3039e3772..17501ae06 100644
--- a/lisp/hpux-os.c
+++ b/lisp/hpux-os.c
@@ -1,5 +1,5 @@
 /*
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/hpux-os.c,v 1.8 2008/03/19 09:17:10 cshapiro Rel $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/hpux-os.c,v 1.9 2010/02/01 15:16:09 rtoy Exp $
  *
  * OS-dependent routines.  This file (along with os.h) exports an
  * OS-independent interface to the operating system VM facilities.
@@ -53,7 +53,7 @@ static struct segment {
 } segments[MAX_SEGMENTS];
 
 void
-os_init(void)
+os_init(char *argv[], char *envp[])
 {
     int i;
 
diff --git a/lisp/irix-os.c b/lisp/irix-os.c
index 072a8a53a..1e39defd1 100644
--- a/lisp/irix-os.c
+++ b/lisp/irix-os.c
@@ -1,5 +1,5 @@
 /*
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/irix-os.c,v 1.4 2008/03/19 09:17:10 cshapiro Rel $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/irix-os.c,v 1.5 2010/02/01 15:16:09 rtoy Exp $
  *
  * OS-dependent routines.  This file (along with os.h) exports an
  * OS-independent interface to the operating system VM facilities.
@@ -30,7 +30,7 @@ os_vm_size_t os_vm_page_size = (-1);
 int zero_fd;
 
 void
-os_init(void)
+os_init(char *argv[], char *envp[])
 {
     zero_fd = open("/dev/zero", O_RDONLY);
     os_vm_page_size = getpagesize();
diff --git a/lisp/lisp.c b/lisp/lisp.c
index 4c568fbeb..f22ac7320 100644
--- a/lisp/lisp.c
+++ b/lisp/lisp.c
@@ -1,7 +1,7 @@
 /*
  * main() entry point for a stand alone lisp image.
  *
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/lisp.c,v 1.69 2009/12/18 04:03:24 agoncharov Exp $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/lisp.c,v 1.70 2010/02/01 15:16:09 rtoy Exp $
  *
  */
 
@@ -556,7 +556,7 @@ main(int argc, const char *argv[], const char *envp[])
     if (default_core == NULL)
 	default_core = "lisp.core";
 
-    os_init();
+    os_init(argv, envp);
 #if defined FEATURE_EXECUTABLE
     if (builtin_image_flag != 0)
 	map_core_sections(argv[0]);
diff --git a/lisp/mach-os.c b/lisp/mach-os.c
index d76be8eee..471085e7f 100644
--- a/lisp/mach-os.c
+++ b/lisp/mach-os.c
@@ -1,5 +1,5 @@
 /*
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/mach-os.c,v 1.6 2008/03/19 09:17:13 cshapiro Rel $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/mach-os.c,v 1.7 2010/02/01 15:16:09 rtoy Exp $
  *
  * OS-dependent routines.  This file (along with os.h) exports an
  * OS-independent interface to the operating system VM facilities.
@@ -38,7 +38,7 @@ task_self(void)
 #endif
 
 void
-os_init(void)
+os_init(char *argv[], char *envp[])
 {
     os_vm_page_size = vm_page_size;
 }
diff --git a/lisp/os.h b/lisp/os.h
index a3d5ed1a3..b9853435d 100644
--- a/lisp/os.h
+++ b/lisp/os.h
@@ -1,5 +1,5 @@
 /*
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/os.h,v 1.23 2008/12/10 02:39:13 rtoy Rel $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/os.h,v 1.24 2010/02/01 15:16:09 rtoy Exp $
  *
  * Common interface for os-dependent functions.
  *
@@ -72,7 +72,7 @@
 
 extern os_vm_size_t os_vm_page_size;
 
-extern void os_init(void);
+extern void os_init(char *argv[], char *envp[]);
 extern void os_install_interrupt_handlers(void);
 
 extern os_vm_address_t os_allocate(os_vm_size_t len);
diff --git a/lisp/osf1-os.c b/lisp/osf1-os.c
index c9071178a..aaad7546b 100644
--- a/lisp/osf1-os.c
+++ b/lisp/osf1-os.c
@@ -1,5 +1,5 @@
 /*
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/osf1-os.c,v 1.4 2008/03/19 09:17:13 cshapiro Rel $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/osf1-os.c,v 1.5 2010/02/01 15:16:09 rtoy Exp $
  *
  * OS-dependent routines.  This file (along with os.h) exports an
  * OS-independent interface to the operating system VM facilities.
@@ -26,7 +26,7 @@
 vm_size_t os_vm_page_size;
 
 void
-os_init(void)
+os_init(char *argv[], char *envp[])
 {
     int buf[2] = { SSIN_UACPROC, UAC_SIGBUS | UAC_NOPRINT };
     int error;
diff --git a/lisp/solaris-os.c b/lisp/solaris-os.c
index 97301d181..1bbd6e731 100644
--- a/lisp/solaris-os.c
+++ b/lisp/solaris-os.c
@@ -1,5 +1,5 @@
 /*
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/solaris-os.c,v 1.23 2008/09/24 09:42:33 cshapiro Rel $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/solaris-os.c,v 1.24 2010/02/01 15:16:09 rtoy Exp $
  *
  * OS-dependent routines.  This file (along with os.h) exports an
  * OS-independent interface to the operating system VM facilities.
@@ -71,7 +71,7 @@ os_init_bailout(char *arg)
 }
 
 void
-os_init(void)
+os_init(char *argv[], char *envp[])
 {
     zero_fd = open(ZEROFILE, O_RDONLY);
     if (zero_fd < 0)
diff --git a/lisp/sunos-os.c b/lisp/sunos-os.c
index 7412f9488..4c2171ff9 100644
--- a/lisp/sunos-os.c
+++ b/lisp/sunos-os.c
@@ -1,5 +1,5 @@
 /*
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/sunos-os.c,v 1.10 2008/09/07 07:07:49 cshapiro Rel $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/sunos-os.c,v 1.11 2010/02/01 15:16:09 rtoy Exp $
  *
  * OS-dependent routines.  This file (along with os.h) exports an
  * OS-independent interface to the operating system VM facilities.
@@ -81,7 +81,7 @@ os_init_bailout(arg)
 }
 
 void
-os_init(void)
+os_init(char *argv[], char *envp[])
 {
     char *empty_file = getenv("CMUCL_EMPTYFILE");
 
-- 
GitLab