From 2c6105acde389717317e725854d7dd3b3d6ece5c Mon Sep 17 00:00:00 2001 From: Juho Snellman Date: Wed, 31 Aug 2005 13:12:17 +0000 Subject: [PATCH] 0.9.4.16: "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 | 4 ++++ src/runtime/bsd-os.c | 3 ++- src/runtime/linux-os.c | 37 ++++++++++++++++++++++++++++++++++++- src/runtime/os.h | 2 +- src/runtime/osf1-os.c | 3 ++- src/runtime/runtime.c | 2 +- src/runtime/sunos-os.c | 3 ++- version.lisp-expr | 2 +- 8 files changed, 49 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 44e11b1..c6a1956 100644 --- 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 diff --git a/src/runtime/bsd-os.c b/src/runtime/bsd-os.c index 3199a86..f41911d 100644 --- a/src/runtime/bsd-os.c +++ b/src/runtime/bsd-os.c @@ -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(); diff --git a/src/runtime/linux-os.c b/src/runtime/linux-os.c index 222f0af..a283abb 100644 --- a/src/runtime/linux-os.c +++ b/src/runtime/linux-os.c @@ -52,6 +52,10 @@ #include "gencgc-internal.h" #endif +#ifdef LISP_FEATURE_LINUX +#include +#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 } diff --git a/src/runtime/os.h b/src/runtime/os.h index 7d24639..3cf3f2d 100644 --- a/src/runtime/os.h +++ b/src/runtime/os.h @@ -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 diff --git a/src/runtime/osf1-os.c b/src/runtime/osf1-os.c index e6f704c..5e22940 100644 --- a/src/runtime/osf1-os.c +++ b/src/runtime/osf1-os.c @@ -51,7 +51,8 @@ size_t os_vm_page_size; -void os_init(void) +void +os_init(char *argv[], char *envp[]) { os_vm_page_size = getpagesize(); } diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 8dbc76c..cb6fcb0 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -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(); diff --git a/src/runtime/sunos-os.c b/src/runtime/sunos-os.c index 0a47dd3..3bd9f45 100644 --- a/src/runtime/sunos-os.c +++ b/src/runtime/sunos-os.c @@ -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; diff --git a/version.lisp-expr b/version.lisp-expr index b44c564..130b2e6 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -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" -- 1.7.10.4