From 24acea547572659fd2041803882411b68ff0d6eb Mon Sep 17 00:00:00 2001
From: Joakim Tjernlund <joakim.tjernlund@transmode.se>
Date: Sat, 17 Sep 2005 17:06:59 +0000
Subject: Fix bug 430 and reduce ldso size with 1KB :). Not sure if I need to
 use fstat64, but I am sure someone will tell me.

---
 ldso/include/dl-hash.h    |   3 ++
 ldso/include/dl-syscall.h |   7 ++-
 ldso/ldso/dl-elf.c        | 133 +++++++++-------------------------------------
 3 files changed, 34 insertions(+), 109 deletions(-)

(limited to 'ldso')

diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h
index af6c2b93f..00b9c87f6 100644
--- a/ldso/include/dl-hash.h
+++ b/ldso/include/dl-hash.h
@@ -49,6 +49,9 @@ struct elf_resolve{
   ElfW(Addr) relro_addr;
   size_t relro_size;
 
+  dev_t st_dev;      /* device */
+  ino_t st_ino;      /* inode */
+
 #ifdef __powerpc__
   /* this is used to store the address of relocation data words, so
    * we don't have to calculate it every time, which requires a divide */
diff --git a/ldso/include/dl-syscall.h b/ldso/include/dl-syscall.h
index 3f20229cd..a1a2859c4 100644
--- a/ldso/include/dl-syscall.h
+++ b/ldso/include/dl-syscall.h
@@ -11,7 +11,9 @@
 #define kernel_stat stat
 #include <bits/kernel_stat.h>
 #include <bits/kernel_types.h>
-
+#define _SYSCALL_H
+#include <bits/sysnum.h>
+#undef _SYSCALL_H
 
 /* _dl_open() parameters */
 #define O_RDONLY        0x0000
@@ -82,6 +84,9 @@ static inline _syscall3(int, _dl_mprotect, const void *, addr, unsigned long, le
 #define __NR__dl_stat __NR_stat
 static inline _syscall2(int, _dl_stat, const char *, file_name, struct stat *, buf);
 
+#define __NR__dl_fstat __NR_fstat
+static inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf);
+
 #define __NR__dl_munmap __NR_munmap
 static inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length);
 
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index 14a10bc1f..28b3094d1 100644
--- a/ldso/ldso/dl-elf.c
+++ b/ldso/ldso/dl-elf.c
@@ -180,71 +180,6 @@ search_for_named_library(const char *name, int secure, const char *path_list,
 	return NULL;
 }
 
-/* Check if the named library is already loaded... */
-struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname,
-		int trace_loaded_objects)
-{
-	const char *pnt, *pnt1;
-	struct elf_resolve *tpnt1;
-	const char *libname, *libname2;
-	static const char libc[] = "libc.so.";
-	static const char aborted_wrong_lib[] = "%s: aborted attempt to load %s!\n";
-
-	pnt = libname = full_libname;
-
-	_dl_if_debug_dprint("Checking if '%s' is already loaded\n", full_libname);
-	/* quick hack to ensure mylibname buffer doesn't overflow.  don't
-	   allow full_libname or any directory to be longer than 1024. */
-	if (_dl_strlen(full_libname) > 1024)
-		return NULL;
-
-	/* Skip over any initial initial './' and '/' stuff to
-	 * get the short form libname with no path garbage */
-	pnt1 = _dl_strrchr(pnt, '/');
-	if (pnt1) {
-		libname = pnt1 + 1;
-	}
-
-	/* Make sure they are not trying to load the wrong C library!
-	 * This sometimes happens esp with shared libraries when the
-	 * library path is somehow wrong! */
-#define isdigit(c)  (c >= '0' && c <= '9')
-	if ((_dl_strncmp(libname, libc, 8) == 0) &&  _dl_strlen(libname) >=8 &&
-			isdigit(libname[8]))
-	{
-		/* Abort attempts to load glibc, libc5, etc */
-		if ( libname[8]!='0') {
-			if (!trace_loaded_objects) {
-				_dl_dprintf(2, aborted_wrong_lib, libname, _dl_progname);
-				_dl_exit(1);
-			}
-			return NULL;
-		}
-	}
-
-	/* Critical step!  Weed out duplicates early to avoid
-	 * function aliasing, which wastes memory, and causes
-	 * really bad things to happen with weaks and globals. */
-	for (tpnt1 = _dl_loaded_modules; tpnt1; tpnt1 = tpnt1->next) {
-
-		/* Skip over any initial initial './' and '/' stuff to
-		 * get the short form libname with no path garbage */
-		libname2 = tpnt1->libname;
-		pnt1 = _dl_strrchr(libname2, '/');
-		if (pnt1) {
-			libname2 = pnt1 + 1;
-		}
-
-		if (_dl_strcmp(libname2, libname) == 0) {
-			/* Well, that was certainly easy */
-			return tpnt1;
-		}
-	}
-
-	return NULL;
-}
-
-
 /* Used to return error codes back to dlopen et. al.  */
 unsigned long _dl_error_number;
 unsigned long _dl_internal_error_number;
@@ -271,14 +206,6 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 		libname = pnt + 1;
 	}
 
-	/* Critical step!  Weed out duplicates early to avoid
-	 * function aliasing, which wastes memory, and causes
-	 * really bad things to happen with weaks and globals. */
-	if ((tpnt1=_dl_check_if_named_library_is_loaded(libname, trace_loaded_objects))!=NULL) {
-		tpnt1->usage_count++;
-		return tpnt1;
-	}
-
 	_dl_if_debug_dprint("\tfind library='%s'; searching\n", libname);
 	/* If the filename has any '/', try it straight and leave it at that.
 	   For IBCS2 compatibility under linux, we substitute the string
@@ -290,7 +217,6 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 		if (tpnt1) {
 			return tpnt1;
 		}
-		//goto goof;
 	}
 
 	/*
@@ -411,48 +337,37 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	int i, flags, piclib, infile;
 	ElfW(Addr) relro_addr = 0;
 	size_t relro_size = 0;
-
-	/* If this file is already loaded, skip this step */
-	tpnt = _dl_check_hashed_files(libname);
-	if (tpnt) {
-		if (*rpnt) {
-			(*rpnt)->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
-			_dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf));
-			(*rpnt)->next->prev = (*rpnt);
-			*rpnt = (*rpnt)->next;
-			(*rpnt)->dyn = tpnt;
-			tpnt->symbol_scope = _dl_symbol_tables;
-		}
-		tpnt->usage_count++;
-		tpnt->libtype = elf_lib;
-		_dl_if_debug_dprint("file='%s';  already loaded\n", libname);
-		return tpnt;
-	}
-
-	/* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD),
-	   we don't load the library if it isn't setuid. */
-
-	if (secure) {
-		struct stat st;
-
-		if (_dl_stat(libname, &st) || !(st.st_mode & S_ISUID))
-			return NULL;
-	}
+	struct stat st;
 
 	libaddr = 0;
 	infile = _dl_open(libname, O_RDONLY, 0);
 	if (infile < 0) {
-#if 0
-		/*
-		 * NO!  When we open shared libraries we may search several paths.
-		 * it is inappropriate to generate an error here.
-		 */
-		_dl_dprintf(2, "%s: can't open '%s'\n", _dl_progname, libname);
-#endif
 		_dl_internal_error_number = LD_ERROR_NOFILE;
 		return NULL;
 	}
 
+	if (_dl_fstat(infile, &st) < 0) {
+		_dl_internal_error_number = LD_ERROR_NOFILE;
+		_dl_close(infile);
+		return NULL;
+	}
+	/* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD),
+	   we don't load the library if it isn't setuid. */
+	if (secure)
+		if (!(st.st_mode & S_ISUID)) {
+			_dl_close(infile);
+			return NULL;
+		}
+
+	/* Check if file is already loaded */
+	for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+		if(tpnt->st_dev == st.st_dev && tpnt->st_ino == st.st_ino) {
+			/* Already loaded */
+			tpnt->usage_count++;
+			_dl_close(infile);
+			return tpnt;
+		}
+	}
 	header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
 			MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 	if (_dl_mmap_check_error(header)) {
@@ -665,6 +580,8 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 			dynamic_addr, 0);
 	tpnt->relro_addr = relro_addr;
 	tpnt->relro_size = relro_size;
+	tpnt->st_dev = st.st_dev;
+	tpnt->st_ino = st.st_ino;
 	tpnt->ppnt = (ElfW(Phdr) *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff);
 	tpnt->n_phent = epnt->e_phnum;
 
-- 
cgit v1.2.3