summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1998-02-17 18:23:42 +0000
committerUlrich Drepper <drepper@redhat.com>1998-02-17 18:23:42 +0000
commitc6222ab921cee390ea3aab57795e028d587b77e2 (patch)
tree1786e626fbd5876fac5496febe5f5c118d4c0ac8
parent71a14d64831fed0b9fd6a0488aff6d6eab89b448 (diff)
downloadglibc-c6222ab921cee390ea3aab57795e028d587b77e2.tar.gz
glibc-c6222ab921cee390ea3aab57795e028d587b77e2.tar.xz
glibc-c6222ab921cee390ea3aab57795e028d587b77e2.zip
Update.
1998-02-17 17:41  Ulrich Drepper  <drepper@cygnus.com>

	* elf/dl-load.c (open_path): Take extra argument PRELOADED.
	If PRELOADED is nonzero check in case of an SUID application
	whether the shared object has the SUID bit set.
	Fix some other problems with handling shared objects in system
	specific directories.
	(_dl_map_object): Also take extra parameter and pass it to open_path.
	* elf/link.h (_dl_map_object): Correct prototype and comment.
	* elf/rtld.c (dl_main): Call _dl_map_object correctly.
	* elf/dl-open.c (_dl_open): Likewise.
	* elf/dl-deps.c (openaux, _dl_map_object_deps): Likewise.

	* sysdeps/libm-ieee754/s_modfl.c: Handle numbers > 1.0 correctly.

	* math/libm-test.c (modf_test): Add test for 1.5.
-rw-r--r--ChangeLog17
-rw-r--r--elf/dl-deps.c8
-rw-r--r--elf/dl-load.c61
-rw-r--r--elf/dl-open.c2
-rw-r--r--elf/link.h8
-rw-r--r--elf/rtld.c12
-rw-r--r--math/libm-test.c4
-rw-r--r--sysdeps/libm-ieee754/s_modfl.c2
8 files changed, 91 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index 805219afbb..fb69047b19 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
+1998-02-17 17:41  Ulrich Drepper  <drepper@cygnus.com>
+
+	* elf/dl-load.c (open_path): Take extra argument PRELOADED.
+	If PRELOADED is nonzero check in case of an SUID application
+	whether the shared object has the SUID bit set.
+	Fix some other problems with handling shared objects in system
+	specific directories.
+	(_dl_map_object): Also take extra parameter and pass it to open_path.
+	* elf/link.h (_dl_map_object): Correct prototype and comment.
+	* elf/rtld.c (dl_main): Call _dl_map_object correctly.
+	* elf/dl-open.c (_dl_open): Likewise.
+	* elf/dl-deps.c (openaux, _dl_map_object_deps): Likewise.
+
+	* sysdeps/libm-ieee754/s_modfl.c: Handle numbers > 1.0 correctly.
+
 1998-02-17  Ulrich Drepper  <drepper@cygnus.com>
 
+	* math/libm-test.c (modf_test): Add test for 1.5.
+
 	* sysdeps/generic/bits/select.h (__FD_ISSET): Compare result with
 	0 to get always an int.
 
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 27de231dff..c069fab0c8 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -1,5 +1,5 @@
 /* Load the dependencies of a mapped object.
-   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998 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
@@ -53,7 +53,7 @@ openaux (void *a)
 {
   struct openaux_args *args = (struct openaux_args *) a;
 
-  args->aux = _dl_map_object (args->map, args->strtab + args->d->d_un.d_val,
+  args->aux = _dl_map_object (args->map, args->strtab + args->d->d_un.d_val, 0,
 			      (args->map->l_type == lt_executable
 			       ? lt_library : args->map->l_type),
 			      args->trace_mode);
@@ -160,7 +160,7 @@ _dl_map_object_deps (struct link_map *map,
 	      {
 		/* Map in the needed object.  */
 		struct link_map *dep
-		  = _dl_map_object (l, strtab + d->d_un.d_val,
+		  = _dl_map_object (l, strtab + d->d_un.d_val, 0,
 				    l->l_type == lt_executable ? lt_library :
 				    l->l_type, trace_mode);
 		/* Allocate new entry.  */
@@ -216,7 +216,7 @@ _dl_map_object_deps (struct link_map *map,
 		  }
 		else
 		  /* For filter objects the dependency must be available.  */
-		  args.aux = _dl_map_object (l, strtab + d->d_un.d_val,
+		  args.aux = _dl_map_object (l, strtab + d->d_un.d_val, 0,
 					     (l->l_type == lt_executable
 					      ? lt_library : l->l_type),
 					     trace_mode);
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 96c1eb6bc6..cc94d7b510 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -793,7 +793,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname,
    with the malloc'd full directory name.  */
 
 static int
-open_path (const char *name, size_t namelen,
+open_path (const char *name, size_t namelen, int preloaded,
 	   struct r_search_path_elem **dirs,
 	   char **realname)
 {
@@ -839,9 +839,31 @@ open_path (const char *name, size_t namelen,
 		else
 		  this_dir->machdirstatus = existing;
 	      }
+	  if (fd != -1 && preloaded && __libc_enable_secure)
+	    {
+	      /* This is an extra security effort to make sure nobody can
+		 preload broken shared objects which are in the trusted
+		 directories and so exploit the bugs.  */
+	      struct stat st;
+
+	      if (__fxstat (_STAT_VER, fd, &st) != 0
+		  || (st.st_mode & S_ISUID) == 0)
+		{
+		  /* The shared object cannot be tested for being SUID
+		     or this bit is not set.  In this case we must not
+		     use this object.  */
+		  __close (fd);
+		  fd = -1;
+		  /* We simply ignore the file, signal this by setting
+		     the error value which would have been set by `open'.  */
+		  errno = ENOENT;
+		}
+	    }
 	}
+      else
+	errno = ENOENT;
 
-      if (fd == -1 && this_dir->dirstatus != nonexisting)
+      if (fd == -1 && errno == ENOENT && this_dir->dirstatus != nonexisting)
 	{
 	  /* Construct the pathname to try.  */
 	  buflen = ((char *) __mempcpy (__mempcpy (buf, this_dir->dirname,
@@ -871,12 +893,32 @@ open_path (const char *name, size_t namelen,
 		  else
 		    this_dir->dirstatus = existing;
 		}
+	  if (fd != -1 && preloaded && __libc_enable_secure)
+	    {
+	      /* This is an extra security effort to make sure nobody can
+		 preload broken shared objects which are in the trusted
+		 directories and so exploit the bugs.  */
+	      struct stat st;
+
+	      if (__fxstat (_STAT_VER, fd, &st) != 0
+		  || (st.st_mode & S_ISUID) == 0)
+		{
+		  /* The shared object cannot be tested for being SUID
+		     or this bit is not set.  In this case we must not
+		     use this object.  */
+		  __close (fd);
+		  fd = -1;
+		  /* We simply ignore the file, signal this by setting
+		     the error value which would have been set by `open'.  */
+		  errno = ENOENT;
+		}
+	    }
 	}
 
       if (fd != -1)
 	{
 	  *realname = malloc (buflen);
-	  if (*realname)
+	  if (*realname != NULL)
 	    {
 	      memcpy (*realname, buf, buflen);
 	      return fd;
@@ -901,8 +943,8 @@ open_path (const char *name, size_t namelen,
 /* Map in the shared object file NAME.  */
 
 struct link_map *
-_dl_map_object (struct link_map *loader, const char *name, int type,
-		int trace_mode)
+_dl_map_object (struct link_map *loader, const char *name, int preloaded,
+		int type, int trace_mode)
 {
   int fd;
   char *realname;
@@ -963,7 +1005,8 @@ _dl_map_object (struct link_map *loader, const char *name, int type,
 	      }
 
 	    if (l->l_rpath_dirs != (struct r_search_path_elem **) -1l)
-	      fd = open_path (name, namelen, l->l_rpath_dirs, &realname);
+	      fd = open_path (name, namelen, preloaded, l->l_rpath_dirs,
+			      &realname);
 	  }
 
       /* If dynamically linked, try the DT_RPATH of the executable itself
@@ -971,12 +1014,12 @@ _dl_map_object (struct link_map *loader, const char *name, int type,
       l = _dl_loaded;
       if (fd == -1 && l && l->l_type != lt_loaded
 	  && l->l_rpath_dirs != (struct r_search_path_elem **) -1l)
-	fd = open_path (name, namelen, l->l_rpath_dirs, &realname);
+	fd = open_path (name, namelen, preloaded, l->l_rpath_dirs, &realname);
 
       /* This is used if a static binary uses dynamic loading and there
 	 is a LD_LIBRARY_PATH given.  */
       if (fd == -1 && fake_path_list != NULL)
-	fd = open_path (name, namelen, fake_path_list, &realname);
+	fd = open_path (name, namelen, preloaded, fake_path_list, &realname);
 
       if (fd == -1)
 	{
@@ -1001,7 +1044,7 @@ _dl_map_object (struct link_map *loader, const char *name, int type,
 
       /* Finally, try the default path.  */
       if (fd == -1)
-	fd = open_path (name, namelen, rtld_search_dirs, &realname);
+	fd = open_path (name, namelen, preloaded, rtld_search_dirs, &realname);
     }
   else
     {
diff --git a/elf/dl-open.c b/elf/dl-open.c
index d095f5e65d..c97321edf0 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -61,7 +61,7 @@ _dl_open (const char *file, int mode)
   __libc_lock_lock (_dl_load_lock);
 
   /* Load the named object.  */
-  new = _dl_map_object (NULL, file, lt_loaded, 0);
+  new = _dl_map_object (NULL, file, 0, lt_loaded, 0);
   if (new->l_searchlist)
     {
       /* It was already open.  */
diff --git a/elf/link.h b/elf/link.h
index 7f2dc674db..67701a13b7 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -296,10 +296,12 @@ extern int _dlerror_run (void (*operate) (void *), void *args);
 
 /* Open the shared object NAME and map in its segments.
    LOADER's DT_RPATH is used in searching for NAME.
-   If the object is already opened, returns its existing map.  */
+   If the object is already opened, returns its existing map.
+   For preloaded shared objects PRELOADED is set to a non-zero
+   value to allow additional security checks.  */
 extern struct link_map *_dl_map_object (struct link_map *loader,
-					const char *name, int type,
-					int trace_mode);
+					const char *name, int preloaded,
+					int type, int trace_mode);
 
 /* Call _dl_map_object on the dependencies of MAP, and set up
    MAP->l_searchlist.  PRELOADS points to a vector of NPRELOADS previously
diff --git a/elf/rtld.c b/elf/rtld.c
index 9529b9c14e..2ca1692584 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -187,7 +187,7 @@ static void
 map_doit (void *a)
 {
   struct map_args *args = (struct map_args *)a;
-  args->main_map = _dl_map_object (NULL, args->str, lt_library, 0);
+  args->main_map = _dl_map_object (NULL, args->str, 0, lt_library, 0);
 }
 
 static void
@@ -394,7 +394,7 @@ of this helper program; chances are you did not intend to run this program.\n",
 	    }
 	}
       else
-	main_map = _dl_map_object (NULL, _dl_argv[0], lt_library, 0);
+	main_map = _dl_map_object (NULL, _dl_argv[0], 0, lt_library, 0);
 
       phdr = main_map->l_phdr;
       phent = main_map->l_phnum;
@@ -509,7 +509,8 @@ of this helper program; chances are you did not intend to run this program.\n",
       while ((p = strsep (&list, " :")) != NULL)
 	if (! __libc_enable_secure || strchr (p, '/') == NULL)
 	  {
-	    struct link_map *new_map = _dl_map_object (NULL, p, lt_library, 0);
+	    struct link_map *new_map = _dl_map_object (NULL, p, 1,
+						       lt_library, 0);
 	    if (new_map->l_opencount == 1)
 	      /* It is no duplicate.  */
 	      ++npreloads;
@@ -569,7 +570,7 @@ of this helper program; chances are you did not intend to run this program.\n",
 	  runp = file + strspn (file, ": \t\n");
 	  while ((p = strsep (&runp, ": \t\n")) != NULL)
 	    {
-	      struct link_map *new_map = _dl_map_object (NULL, p,
+	      struct link_map *new_map = _dl_map_object (NULL, p, 1,
 							 lt_library, 0);
 	      if (new_map->l_opencount == 1)
 		/* It is no duplicate.  */
@@ -583,7 +584,8 @@ of this helper program; chances are you did not intend to run this program.\n",
       if (problem != NULL)
 	{
 	  char *p = strndupa (problem, file_size - (problem - file));
-	  struct link_map *new_map = _dl_map_object (NULL, p, lt_library, 0);
+	  struct link_map *new_map = _dl_map_object (NULL, p, 1,
+						     lt_library, 0);
 	  if (new_map->l_opencount == 1)
 	    /* It is no duplicate.  */
 	    ++npreloads;
diff --git a/math/libm-test.c b/math/libm-test.c
index 8fa473eaf5..ea5716ff81 100644
--- a/math/libm-test.c
+++ b/math/libm-test.c
@@ -1703,6 +1703,10 @@ modf_test (void)
   check ("modf (-0, &x) returns -0", result, minus_zero);
   check ("modf (-0, &x) sets x to -0", intpart, minus_zero);
 
+  result = FUNC(modf) (1.5, &intpart);
+  check ("modf (1.5, &x) returns 0.5", result, 0.5);
+  check ("modf (1.5, &x) sets x to 1", intpart, 1);
+
   result = FUNC(modf) (2.5, &intpart);
   check ("modf (2.5, &x) returns 0.5", result, 0.5);
   check ("modf (2.5, &x) sets x to 2", intpart, 2);
diff --git a/sysdeps/libm-ieee754/s_modfl.c b/sysdeps/libm-ieee754/s_modfl.c
index 5f2b4b5e2c..ad16ef65ec 100644
--- a/sysdeps/libm-ieee754/s_modfl.c
+++ b/sysdeps/libm-ieee754/s_modfl.c
@@ -71,7 +71,7 @@ static long double one = 1.0;
 	    SET_LDOUBLE_WORDS(x,se&0x8000,0,0);	/* return +-0 */
 	    return x;
 	} else {			/* fraction part in low x */
-	    i = ((u_int32_t)(0x7fffffff))>>(j0-32);
+	    i = ((u_int32_t)(0xffffffff))>>(j0-32);
 	    if((i1&i)==0) { 		/* x is integral */
 		*iptr = x;
 		INSERT_WORDS(x,se&0x8000,0);	/* return +-0 */