]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
[BZ #227]
authorRoland McGrath <roland@gnu.org>
Sun, 15 Aug 2004 23:33:02 +0000 (23:33 +0000)
committerRoland McGrath <roland@gnu.org>
Sun, 15 Aug 2004 23:33:02 +0000 (23:33 +0000)
2004-08-15  Roland McGrath  <roland@redhat.com>
[BZ #227]
* sysdeps/unix/sysv/linux/kernel-features.h
(__ASSUME_BRK_PAGE_ROUNDED): New macro.
* sysdeps/unix/sysv/linux/dl-sysdep.c (frob_brk)
[! __ASSUME_BRK_PAGE_ROUNDED]: Adjust the break up if it falls within
the partial page after the dynamic linker's own data segment.

sysdeps/unix/sysv/linux/dl-sysdep.c
sysdeps/unix/sysv/linux/kernel-features.h

index b58f4c13e241165f4b36a92ff40af56c08294342..79f95df0a22a345459c324fb93b8af8307dfe52d 100644 (file)
@@ -1,5 +1,5 @@
 /* Dynamic linker system dependencies for Linux.
-   Copyright (C) 1995, 1997, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1997, 2001, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -21,6 +21,8 @@
    the generic dynamic linker system interface code.  */
 
 #include <unistd.h>
+#include <ldsodefs.h>
+#include "kernel-features.h"
 
 #define DL_SYSDEP_INIT frob_brk ()
 
@@ -28,6 +30,27 @@ static inline void
 frob_brk (void)
 {
   __brk (0);                   /* Initialize the break.  */
+
+#if ! __ASSUME_BRK_PAGE_ROUNDED
+  /* If the dynamic linker was executed as a program, then the break may
+     start immediately after our data segment.  However, dl-minimal.c has
+     already stolen the remainder of the page for internal allocations.
+     If we don't adjust the break location recorded by the kernel, the
+     normal program startup will inquire, find the value at our &_end,
+     and start allocating its own data there, clobbering dynamic linker
+     data structures allocated there during startup.
+
+     Later Linux kernels have changed this behavior so that the initial
+     break value is rounded up to the page boundary before we start.  */
+
+  extern void *__curbrk attribute_hidden;
+  extern void _end attribute_hidden;
+  void *const endpage = (void *) 0 + (((__curbrk - (void *) 0)
+                                      + GLRO(dl_pagesize) - 1)
+                                     & -GLRO(dl_pagesize));
+  if (__builtin_expect (__curbrk >= &_end && __curbrk < endpage, 0))
+    __brk (endpage);
+#endif
 }
 
 #include <sysdeps/generic/dl-sysdep.c>
index ee089d550be50b7ae1327dcec91c9b782a1f5c8f..6f19fc6360088b14bc25b09d70b0bdce31fc2fc5 100644 (file)
 #if __LINUX_KERNEL_VERSION >= 132612
 # define __ASSUME_GETDENTS32_D_TYPE    1
 #endif
+
+/* Starting with version 2.5.3, the initial location returned by `brk'
+   after exec is always rounded up to the next page.  */
+#if __LINUX_KERNEL_VERSION >= 132355
+# define __ASSUME_BRK_PAGE_ROUNDED     1
+#endif