This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Support LD_USE_LOAD_BIAS


Hi!

On a prelinked system PIEs aren't much useful, since although the PIE
itself can be randomized, the libraries PIE links against typically
aren't randomized.  PIEs cannot make use of the prelinking information
anyway, so it would be good to honor library load biases assigned by
prelink only in binaries and not in (non-prelinked) PIEs.
The following patch does this, plus adds an environment variable
LD_USE_LOAD_BIAS to override this.
Without LD_USE_LOAD_BIAS in environment, executables and prelinked
ET_DYN objects will honor base addresses of their dependent libraries
and (non-prelinked) PIEs and other ET_DYN objects will not honor it.
With LD_USE_LOAD_BIAS=1 in environment, both executables and PIEs
will honor the base addresses while with LD_USE_LOAD_BIAS=0
neither executables nor PIEs will honor it.

2003-11-22  Jakub Jelinek  <jakub@redhat.com>

	* sysdeps/generic/ldsodefs.h (_dl_use_load_bias): New _rtld_global
	field.
	* elf/rtld.c (_rtld_global): Initialize _dl_use_load_bias field.
	(dl_main): Set GL(dl_use_load_bias) default.
	(process_envvars): Set GL(dl_use_load_bias) from LD_USE_LOAD_BIAS.
	Add EXTRA_LD_ENVVARS_13.
	* elf/dl-support.c (_dl_use_load_bias): New variable.
	* elf/dl-load.c (_dl_map_object_from_fd): Mask c->mapstart
	with GL(dl_use_load_bias).
	* sysdeps/generic/unsecvars.h (UNSECURE_ENVVARS): Add
	LD_USE_LOAD_BIAS.
	* sysdeps/unix/sysv/linux/dl-librecon.h (EXTRA_LD_ENVVARS): Remove.
	(EXTRA_LD_ENVVARS_LINUX): Renamed to...
	(EXTRA_LD_ENVVARS_13): ... this.  Remove case at the beginning.
	* sysdeps/unix/sysv/linux/i386/dl-librecon.h (EXTRA_LD_ENVVARS):
	Don't undefine first.  Remove EXTRA_LD_ENVVARS_LINUX.

--- libc/elf/rtld.c.jj	2003-10-29 00:18:41.000000000 +0100
+++ libc/elf/rtld.c	2003-11-21 23:46:17.000000000 +0100
@@ -95,6 +95,7 @@ struct rtld_global _rtld_global =
     ._dl_sysinfo = DL_SYSINFO_DEFAULT,
 #endif
     ._dl_lazy = 1,
+    ._dl_use_load_bias = -2,
     ._dl_fpu_control = _FPU_DEFAULT,
     ._dl_correct_cache_id = _DL_CACHE_DEFAULT_ID,
     ._dl_hwcap_mask = HWCAP_IMPORTANT,
@@ -996,6 +997,12 @@ of this helper program; chances are you 
   GL(dl_rtld_map).l_prev = GL(dl_loaded);
   ++GL(dl_nloaded);
 
+  /* If LD_USE_LOAD_BIAS env variable has not been seen, default
+     to not using bias for non-prelinked PIEs and libraries
+     and using it for executables or prelinked PIEs or libraries.  */
+  if (GL(dl_use_load_bias) == (ElfW(Addr)) -2)
+    GL(dl_use_load_bias) = (GL(dl_loaded)->l_addr == 0) ? -1 : 0;
+
   /* Set up the program header information for the dynamic linker
      itself.  It is needed in the dl_iterate_phdr() callbacks.  */
   ElfW(Ehdr) *rtld_ehdr = (ElfW(Ehdr) *) GL(dl_rtld_map).l_map_start;
@@ -1992,6 +1999,16 @@ process_envvars (enum mode *modep)
 	    GL(dl_dynamic_weak) = 1;
 	  break;
 
+	case 13:
+	  /* We might have some extra environment variable with length 13
+	     to handle.  */
+#ifdef EXTRA_LD_ENVVARS_13
+	  EXTRA_LD_ENVVARS_13
+#endif
+	  if (memcmp (envline, "USE_LOAD_BIAS", 13) == 0)
+	    GL(dl_use_load_bias) = envline[14] == '1' ? -1 : 0;
+	  break;
+
 	case 14:
 	  /* Where to place the profiling data file.  */
 	  if (!INTUSE(__libc_enable_secure)
--- libc/elf/dl-support.c.jj	2003-09-23 16:14:05.000000000 +0200
+++ libc/elf/dl-support.c	2003-11-21 23:42:10.000000000 +0100
@@ -41,6 +41,7 @@ size_t _dl_platformlen;
 
 int _dl_debug_mask;
 int _dl_lazy;
+ElfW(Addr) _dl_use_load_bias = -2;
 int _dl_dynamic_weak;
 
 /* If nonzero print warnings about problematic situations.  */
--- libc/elf/dl-load.c.jj	2003-10-27 21:05:07.000000000 +0100
+++ libc/elf/dl-load.c	2003-11-21 23:43:52.000000000 +0100
@@ -1096,7 +1096,8 @@ cannot allocate TLS data structures for 
 	   prefer to map such objects at; but this is only a preference,
 	   the OS can do whatever it likes. */
 	ElfW(Addr) mappref;
-	mappref = (ELF_PREFERRED_ADDRESS (loader, maplength, c->mapstart)
+	mappref = (ELF_PREFERRED_ADDRESS (loader, maplength,
+					  c->mapstart & GL(dl_use_load_bias))
 		   - MAP_BASE_ADDR (l));
 
 	/* Remember which part of the address space this object uses.  */
--- libc/sysdeps/generic/unsecvars.h.jj	2001-11-06 01:13:43.000000000 +0100
+++ libc/sysdeps/generic/unsecvars.h	2003-11-21 23:48:34.000000000 +0100
@@ -7,6 +7,7 @@
   "LD_ORIGIN_PATH\0"							      \
   "LD_DEBUG_OUTPUT\0"							      \
   "LD_PROFILE\0"							      \
+  "LD_USE_LOAD_BIAS\0"							      \
   "GCONV_PATH\0"							      \
   "HOSTALIASES\0"							      \
   "LOCALDOMAIN\0"							      \
--- libc/sysdeps/generic/ldsodefs.h.jj	2003-09-23 17:03:02.000000000 +0200
+++ libc/sysdeps/generic/ldsodefs.h	2003-11-21 23:36:37.000000000 +0100
@@ -337,6 +337,11 @@ struct rtld_global
   /* File descriptor to write debug messages to.  */
   EXTERN int _dl_debug_fd;
 
+  /* -1 if the dynamic linker should honor library load bias,
+     0 if not, -2 use the default (honor biases for normal
+     binaries, don't honor for PIEs).  */
+  EXTERN ElfW(Addr) _dl_use_load_bias;
+
 #ifdef _LIBC_REENTRANT
   EXTERN void **(*_dl_error_catch_tsd) (void) __attribute__ ((const));
 #endif
--- libc/sysdeps/unix/sysv/linux/dl-librecon.h.jj	2003-02-26 01:01:15.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/dl-librecon.h	2003-11-21 18:00:29.000000000 +0100
@@ -1,5 +1,5 @@
 /* Optional code to distinguish library flavours.
-   Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
 
@@ -44,12 +44,12 @@ _dl_osversion_init (char *assume_kernel)
 }
 
 /* Recognizing extra environment variables.  */
-#define EXTRA_LD_ENVVARS EXTRA_LD_ENVVARS_LINUX
-#define EXTRA_LD_ENVVARS_LINUX \
-  case 13:								      \
+#define EXTRA_LD_ENVVARS_13 \
     if (memcmp (envline, "ASSUME_KERNEL", 13) == 0)			      \
-      _dl_osversion_init (&envline[14]);				      \
-    break;								      \
+      {									      \
+	_dl_osversion_init (&envline[14]);				      \
+	break;								      \
+      }
 
 #define DL_OSVERSION_INIT \
   do {									      \
--- libc/sysdeps/unix/sysv/linux/i386/dl-librecon.h.jj	2002-12-10 11:30:53.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/i386/dl-librecon.h	2003-11-21 18:00:42.000000000 +0100
@@ -1,5 +1,5 @@
 /* Optional code to distinguish library flavours.
-   Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -48,8 +48,7 @@
   while (0)
 
 /* Recognizing extra environment variables.  */
-#undef EXTRA_LD_ENVVARS
-#define EXTRA_LD_ENVVARS EXTRA_LD_ENVVARS_LINUX \
+#define EXTRA_LD_ENVVARS \
   case 15:								      \
     if (memcmp (envline, "LIBRARY_VERSION", 15) == 0)			      \
       GL(dl_correct_cache_id) = envline[16] == '5' ? 2 : 3;		      \

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]