summary refs log tree commit diff
path: root/elf/dl-load.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1997-01-21 06:10:42 +0000
committerUlrich Drepper <drepper@redhat.com>1997-01-21 06:10:42 +0000
commitfd26970f3324277683be531ad2c31f42e19e4b48 (patch)
tree5d9802aa7e77cc5c0f4b87ac661fe264a93bbe2e /elf/dl-load.c
parentf9c53d1159ff05ac533d3351c70df1ea32c2119d (diff)
downloadglibc-fd26970f3324277683be531ad2c31f42e19e4b48.tar.gz
glibc-fd26970f3324277683be531ad2c31f42e19e4b48.tar.xz
glibc-fd26970f3324277683be531ad2c31f42e19e4b48.zip
update from main archive 970120 cvs/libc-970121
Tue Jan 21 04:05:20 1997  Ulrich Drepper  <drepper@cygnus.com>

	* version.h (VERSION): Bump to 1.101.

	Implement -d and -r option to `ldd' to check relocations.
	* elf/dl-error.c: Add another method to intercept errors.
	(_dl_receive_error): New function.  Install user defined handler.
	(receiver): New variable.  Contains pointer to user provided handler.
	(_dl_signal_error): If user provided handler is installed call this.
	* elf/dl-load.c (_dl_map_object): When shared object is not found in
	trace mode initialize a few more fields so that lookup can actually
	happen but always fails.
	* elf/ldd.sh.in: Rewrite argument handling.  Recognize new arguments
	to trigger reloation test.  Return with appropriate error code if
	a file wasn't found.  Print warning if object is not executable.
	* elf/ldd.bash.in: Likewise.
	* elf/link.h (receiver_fct): New type.  Used in _dl_receive_error.
	(_dl_sysdep_error): New prototype.
	(_dl_receive_error): New prototype.
	(_dl_signal_error): Remove  __attribute__ ((__noreturn__)).
	* elf/rtld.c (dl_main): Rewrite argument handling.  More than
	one argument allowed.  Recognize --data-relocs and --function-relocs
	arguments.
	Don't determine `lazy' mode from LD_BIND_NOW environment variable
	when in trace mode.
	If in trace mode and either --data-relocs or --function-relocs is
	given perform relocation.  Report errors using print_unresolved
	function.
	(print_unresolved): New function.  Print information about missing
	symbol on stderr.
	* sysdeps/generic/dl-sysdep.c (_dl_sysdep_error): New function.
	Like _dl_sysdep_message but print to stderr.
	* sysdeps/mach/hurd/dl-sysdep.c: Likewise.

	* sysdeps/generic/sockaddrcom.h: Add definition of sa_family_t.
	Reported by Andreas Schwab.
	(__SOCKADDR_COMMON): Use sa_family_t for family member.
	* sysdeps/unix/bsd/bsd4.4/sockaddrcom.h: Likewise.

	Linux/Sparc support by Miguel de Icaza.
	* sysdeps/sparc/fpu_control.h: New file.
	* sysdeps/unix/sysv/linux/sparc/__sigtrampoline.S: New file.
	* sysdeps/unix/sysv/linux/sparc/brk.c: New file.
	* sysdeps/unix/sysv/linux/sparc/profil-counter.h: New file.
	* sysdeps/unix/sysv/linux/sparc/sigaction.c: New file.
	* sysdeps/unix/sysv/linux/sparc/socket.S: New file.
	* sysdeps/unix/sysv/linux/sparc/syscall.S: New file.
	* sysdeps/unix/sysv/linux/sparc/sysdep.h: New file.
	* sysdeps/unix/sysv/linux/sparc/Dist: New file.
	* sysdeps/unix/sysv/linux/sparc/Makefile: New file.

	* sysdeps/unix/sysv/linux/net/if_arp.h: Don't use kernel header.
	Provide own definition based on 4.4BSD and Linux.
	* sysdeps/unix/sysv/linux/net/ppp_defs.h: Define __u32 before
	including <linux/ppp_defs.h>.
	* sysdeps/unix/sysv/linux/sys/msq_buf.h (struct msqid_ds): Don't
	use __pid_t since the kernel might have a different size.
	* sysdeps/unix/sysv/linux/sys/shm_buf.h (struct shmid_ds): Likewise.
	Reported by Andreas Schwab.

	* time/asctime.c: Update copyright.
	* time/dysize.c: Likewise.
	* time/gmtime.c: Likewise.
	* time/timegm.c: Likewise.
	* time/offtime.c: Likewise.  De-ANSI-declfy.

	* time/tzset.c (__tzset_internal): When TZ envvar does not name a
	DST timezone don't default to offset -1.

	* sysdeps/unix/sysv/linux/net/route.h: Don't use kernel header.
	Reported by a sun <asun@zoology.washington.edu>.

	* resolv/Makefile: Correct spelling: subdirs-dirs -> subdir-dirs.

	* sysdeps/stub/sysv_signal.c: New file.  Stub implementation.

	* Makefile (distribute): Add mcheck.h.

	* nis/Makefile (distribute): Add nss-nis.h.

	* libio/Makefile (routines): Change vdprintf to iovdprintf to prevent
	dist problem.

	* nss/Makefile (distribute): Add digits_dots.c.

	* sysdeps/unix/sysv/linux/Dist: Add kernel_sigaction.h.
	* sysdeps/unix/sysv/linux/alpha/Dist: Add sys/procfs.h.
	* sysdeps/unix/sysv/linux/sparc/Dist: Add clone.S.
	* new-malloc/Makefile (distribute): Add mcheck-init.c and mcheck.h.

Mon Jan 20 17:54:28 1997  Sven Verdoolaege  <skimo@breughel.ufsia.ac.be>

	* manual/filesys.texi: Fix little problem (reentrant->readdir).

Fri Jan 17 19:07:07 1997  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* configure.in [$elf=yes]: Check for support of .previous and
	.popsection in the assembler.
	* config.h.in: Add HAVE_ASM_PREVIOUS_DIRECTIVE and
	HAVE_ASM_POPSECTION_DIRECTIVE.
	* libc-symbols.h (__make_section_unallocated) [HAVE_ELF]: Define
	appropriate if either .previous or .popsection is supported.
	(libc_warning) [HAVE_ELF]: Use it here.

Sat Jan 18 22:15:26 1997  Richard Henderson  <rth@tamu.edu>

	* Makeconfig (CFLAGS-.so): Add -fno-common to prevent odd sorts of
	errors that can occur when linking libc.so.

Mon Jan 20 05:20:49 1997  Ulrich Drepper  <drepper@cygnus.com>

	* elf/dl-load.c (open_path): When running setuid don't try
	a directory if it is not given with the full name.

	* elf/Makefile (before-compile): New variable.  Mention trusted-dirs.h.
	(trusted-dirs.h): Construct file from $(default-rpath) and
	$(user-defined-trusted-dirs) variables.
	* elf/dl-load.c (_dl_map_object): Pass additional argument to open_path
	which is NULL except for the LD_LIBRARY_PATH pass in which case it
	is a pointer to the list of directories from the trusted-dirs.h
	file.
	(open_path): Accept additional argument with list of trusted dirs.
	When running setuid and a list of trusted dirs is given only use
	those which are mentioned in the list.

	* elf/rtld.c (dl_main): Don't reject whole LD_LIBRARY_PATH when
	running setuid.  Instead accept entries which do not contain a '/'.

	* Makeconfig: Correct comment about +(default_cflags).

Mon Jan 20 05:11:14 1997  Hrvoje Niksic  <hniksic@srce.hr>

	* time/strptime.c (recursive): Use && not || to test for valid
	argument.

Mon Jan 20 05:06:50 1997  Ulrich Drepper  <drepper@cygnus.com>

	* elf/ldd.sh.in: Exit with value 1 if an error occured.
	* elf/ldd.bash.in: Likewise.

	* elf/rtld.c (dl_main): Do not always ignore LD_PRELOAD when the
	binary runs setuid.  It is save to use those entries which do not
	contain a '/'.  This is compatible with Solaris-2.
Diffstat (limited to 'elf/dl-load.c')
-rw-r--r--elf/dl-load.c70
1 files changed, 57 insertions, 13 deletions
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 7dc6d91a02..6a3d919976 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1,5 +1,5 @@
 /* _dl_map_object -- Map in a shared object's segments from the file.
-   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997 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
@@ -409,7 +409,8 @@ _dl_map_object_from_fd (char *name, int fd, char *realname,
 static int
 open_path (const char *name, size_t namelen,
 	   const char *dirpath,
-	   char **realname)
+	   char **realname,
+	   const char *trusted_dirs[])
 {
   char *buf;
   const char *p;
@@ -426,13 +427,42 @@ open_path (const char *name, size_t namelen,
   do
     {
       size_t buflen;
+      size_t this_len;
 
       dirpath = p;
       p = strpbrk (dirpath, ":;");
       if (p == NULL)
 	p = strchr (dirpath, '\0');
 
-      if (p == dirpath)
+      this_len = p - dirpath;
+
+      /* When we run a setuid program we do not accept any directory.  */
+      if (__libc_enable_secure)
+	{
+	  /* All trusted directory must be complete name.  */
+	  if (dirpath[0] != '/')
+	    continue;
+
+	  /* If we got a list of trusted directories only accept one
+	     of these.  */
+	  if (trusted_dirs != NULL)
+	    {
+	      const char **trust = trusted_dirs;
+
+	      while (*trust !=  NULL)
+		if (memcmp (dirpath, *trust, this_len) == 0
+		    && (*trust)[this_len] == '\0')
+		  break;
+		else
+		  ++trust;
+
+	      /* If directory is not trusted, ignore this directory.  */
+	      if (*trust == NULL)
+		continue;
+	    }
+	}
+
+      if (this_len == 0)
 	{
 	  /* Two adjacent colons, or a colon at the beginning or the end of
 	     the path means to search the current directory.  */
@@ -442,10 +472,10 @@ open_path (const char *name, size_t namelen,
       else
 	{
 	  /* Construct the pathname to try.  */
-	  (void) memcpy (buf, dirpath, p - dirpath);
-	  buf[p - dirpath] = '/';
-	  (void) memcpy (&buf[(p - dirpath) + 1], name, namelen);
-	  buflen = p - dirpath + 1 + namelen;
+	  (void) memcpy (buf, dirpath, this_len);
+	  buf[this_len] = '/';
+	  (void) memcpy (&buf[this_len + 1], name, namelen);
+	  buflen = this_len + 1 + namelen;
 	}
 
       fd = __open (buf, O_RDONLY);
@@ -508,9 +538,9 @@ _dl_map_object (struct link_map *loader, const char *name, int type,
 
       size_t namelen = strlen (name) + 1;
 
-      inline void trypath (const char *dirpath)
+      inline void trypath (const char *dirpath, const char *trusted[])
 	{
-	  fd = open_path (name, namelen, dirpath, &realname);
+	  fd = open_path (name, namelen, dirpath, &realname, trusted);
 	}
 
       fd = -1;
@@ -521,16 +551,24 @@ _dl_map_object (struct link_map *loader, const char *name, int type,
 	if (l && l->l_info[DT_RPATH])
 	  trypath ((const char *) (l->l_addr +
 				   l->l_info[DT_STRTAB]->d_un.d_ptr +
-				   l->l_info[DT_RPATH]->d_un.d_val));
+				   l->l_info[DT_RPATH]->d_un.d_val), NULL);
       /* If dynamically linked, try the DT_RPATH of the executable itself.  */
       l = _dl_loaded;
       if (fd == -1 && l && l->l_type != lt_loaded && l->l_info[DT_RPATH])
 	trypath ((const char *) (l->l_addr +
 				 l->l_info[DT_STRTAB]->d_un.d_ptr +
-				 l->l_info[DT_RPATH]->d_un.d_val));
+				 l->l_info[DT_RPATH]->d_un.d_val), NULL);
       /* Try an environment variable (unless setuid).  */
       if (fd == -1 && ! __libc_enable_secure)
-	trypath (getenv ("LD_LIBRARY_PATH"));
+	{
+	  static const char *trusted_dirs[] =
+	  {
+#include "trusted-dirs.h"
+	    NULL
+	  };
+
+	  trypath (getenv ("LD_LIBRARY_PATH"), trusted_dirs);
+	}
       if (fd == -1)
 	{
 	  /* Check the list of libraries in the file /etc/ld.so.cache,
@@ -555,7 +593,7 @@ _dl_map_object (struct link_map *loader, const char *name, int type,
       if (fd == -1)
 	{
 	  extern const char *_dl_rpath;	/* Set in rtld.c. */
-	  trypath (_dl_rpath);
+	  trypath (_dl_rpath, NULL);
 	}
     }
   else
@@ -590,6 +628,7 @@ _dl_map_object (struct link_map *loader, const char *name, int type,
 	     are only interested in the list of libraries this isn't
 	     so severe.  Fake an entry with all the information we
 	     have (in fact only the name).  */
+	  static const ElfW(Symndx) dummy_bucket = STN_UNDEF;
 
 	  /* Enter the new object in the list of loaded objects.  */
 	  if ((name_copy = local_strdup (name)) == NULL
@@ -599,6 +638,11 @@ _dl_map_object (struct link_map *loader, const char *name, int type,
 	  /* We use an opencount of 0 as a sign for the faked entry.  */
 	  l->l_opencount = 0;
 	  l->l_reserved = 0;
+	  l->l_buckets = &dummy_bucket;
+	  l->l_nbuckets = 1;
+	  l->l_relocated = 1;
+
+	  return l;
 	}
       else
 	_dl_signal_error (errno, name, "cannot open shared object file");