[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#900: temacs segmentation fault in unexec under Linux 2.6.26
From: |
Ulrich Mueller |
Subject: |
bug#900: temacs segmentation fault in unexec under Linux 2.6.26 |
Date: |
Tue, 9 Sep 2008 17:02:04 +0200 |
Tags: patch
I guess the issue boils down to the fact that testing for
(heap_bss_diff > MAX_HEAP_BSS_DIFF) is not a reliable method to
determine if heap randomisation is switched on. "heap_bss_diff" is
random in nature, and will therefore be smaller than MAX_HEAP_BSS_DIFF
in some cases. These lead to the observed segmentation faults.
Here is an attempt of a patch, asking the kernel (via /proc fs) for
the presence of the feature. I've also made the definition of
ADDR_NO_RANDOMIZE conditional, since it is already defined in newer
versions of personality.h.
Patch was tested with 22.3, but also applies cleanly to the CVS trunk
of today.
*** emacs-orig/src/emacs.c 2008-05-12 21:55:52.000000000 +0200
--- emacs/src/emacs.c 2008-09-09 16:26:52.000000000 +0200
***************
*** 73,78 ****
--- 73,81 ----
#ifdef HAVE_PERSONALITY_LINUX32
#include <sys/personality.h>
+ #ifndef ADDR_NO_RANDOMIZE
+ #define ADDR_NO_RANDOMIZE 0x0040000
+ #endif
#endif
#ifndef O_RDWR
***************
*** 789,794 ****
--- 792,817 ----
return count >= 3 ? REPORT_EMACS_BUG_PRETEST_ADDRESS :
REPORT_EMACS_BUG_ADDRESS;
}
+ #ifdef HAVE_PERSONALITY_LINUX32
+ /* Get the `randomize_va_space' parameter. A value of 2 (introduced
+ in Linux 2.6.25) indicates that brk() randomization is switched on,
+ which will break unexec. See <http://lkml.org/lkml/2007/10/23/435>. */
+ static int
+ linux_randomize_va_space ()
+ {
+ FILE *fp;
+ int rand, count;
+
+ fp = fopen ("/proc/sys/kernel/randomize_va_space", "r");
+ if (!fp)
+ return -1;
+ count = fscanf (fp, "%d", &rand);
+ (void) fclose (fp);
+ if (count != 1)
+ return -1;
+ return rand;
+ }
+ #endif /* HAVE_PERSONALITY_LINUX32 */
/* ARGSUSED */
int
***************
*** 883,906 ****
if (!initialized
&& (strcmp (argv[argc-1], "dump") == 0
|| strcmp (argv[argc-1], "bootstrap") == 0)
! && heap_bss_diff > MAX_HEAP_BSS_DIFF)
{
! if (! getenv ("EMACS_HEAP_EXEC"))
! {
! /* Set this so we only do this once. */
! putenv("EMACS_HEAP_EXEC=true");
!
! /* A flag to turn off address randomization which is introduced
! in linux kernel shipped with fedora core 4 */
! #define ADD_NO_RANDOMIZE 0x0040000
! personality (PER_LINUX32 | ADD_NO_RANDOMIZE);
! #undef ADD_NO_RANDOMIZE
!
! execvp (argv[0], argv);
!
! /* If the exec fails, try to dump anyway. */
! perror ("execvp");
! }
}
#endif /* HAVE_PERSONALITY_LINUX32 */
--- 906,925 ----
if (!initialized
&& (strcmp (argv[argc-1], "dump") == 0
|| strcmp (argv[argc-1], "bootstrap") == 0)
! && !getenv ("EMACS_HEAP_EXEC")
! && (heap_bss_diff > MAX_HEAP_BSS_DIFF
! || linux_randomize_va_space() >= 2))
{
! /* Set this so we only do this once. */
! putenv("EMACS_HEAP_EXEC=true");
!
! /* Set personality and disable randomization of VA space. */
! personality (PER_LINUX32 | ADDR_NO_RANDOMIZE);
!
! execvp (argv[0], argv);
!
! /* If the exec fails, try to dump anyway. */
! perror ("execvp");
}
#endif /* HAVE_PERSONALITY_LINUX32 */