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