Beispiel #1
0
/* This function's behavior must exactly match that
 * in uClibc/ldso/util/ldd.c */
static struct elf_resolve *
search_for_named_library(const char *name, unsigned int rflags, const char *path_list,
	struct dyn_elf **rpnt, const char* origin)
{
	char *mylibname;
	struct elf_resolve *tpnt;
	const char *p, *pn;
	int plen;

	if (path_list==NULL)
		return NULL;

	/* another bit of local storage */
	mylibname = alloca(2050);

	/* Unlike ldd.c, don't bother to eliminate double //s */

	/* Replace colons with zeros in path_list */
	/* : at the beginning or end of path maps to CWD */
	/* :: anywhere maps CWD */
	/* "" maps to CWD */
	for (p = path_list; p != NULL; p = pn) {
		pn = _dl_strchr(p + 1, ':');
		if (pn != NULL) {
			plen = pn - p;
			pn++;
		} else
			plen = _dl_strlen(p);

		if (plen >= 7 && _dl_memcmp(p, "$ORIGIN", 7) == 0) {
			int olen;
			/* $ORIGIN is not expanded for SUID/GUID programs
			   (except if it is $ORIGIN alone) */
			if ((rflags & __RTLD_SECURE) && plen != 7)
				continue;
			if (origin == NULL)
				continue;
			for (olen = _dl_strlen(origin) - 1; olen >= 0 && origin[olen] != '/'; olen--)
				;
			if (olen <= 0)
				continue;
			_dl_memcpy(&mylibname[0], origin, olen);
			_dl_memcpy(&mylibname[olen], p + 7, plen - 7);
			mylibname[olen + plen - 7] = 0;
		} else if (plen != 0) {
			_dl_memcpy(mylibname, p, plen);
			mylibname[plen] = 0;
		} else {
			_dl_strcpy(mylibname, ".");
		}
		_dl_strcat(mylibname, "/");
		_dl_strcat(mylibname, name);
#ifdef __LDSO_SAFE_RUNPATH__
		if (*mylibname == '/')
#endif
		if ((tpnt = _dl_load_elf_shared_library(rflags, rpnt, mylibname)) != NULL)
			return tpnt;
	}
	return NULL;
}
Beispiel #2
0
/* This function's behavior must exactly match that
 * in uClibc/ldso/util/ldd.c */
static struct elf_resolve *
search_for_named_library(const char *name, unsigned rflags, const char *path_list,
	struct dyn_elf **rpnt)
{
	char *path, *path_n, *mylibname;
	struct elf_resolve *tpnt;
	int done;

	if (path_list==NULL)
		return NULL;

	/* We need a writable copy of this string, but we don't
	 * need this allocated permanently since we don't want
	 * to leak memory, so use alloca to put path on the stack */
	done = _dl_strlen(path_list);
	path = alloca(done + 1);

	/* another bit of local storage */
	mylibname = alloca(2050);

	_dl_memcpy(path, path_list, done+1);

	/* Unlike ldd.c, don't bother to eliminate double //s */

	/* Replace colons with zeros in path_list */
	/* : at the beginning or end of path maps to CWD */
	/* :: anywhere maps CWD */
	/* "" maps to CWD */
	done = 0;
	path_n = path;
	do {
		if (*path == 0) {
			*path = ':';
			done = 1;
		}
		if (*path == ':') {
			*path = 0;
			if (*path_n)
				_dl_strcpy(mylibname, path_n);
			else
				_dl_strcpy(mylibname, "."); /* Assume current dir if empty path */
			_dl_strcat(mylibname, "/");
			_dl_strcat(mylibname, name);
#ifdef __LDSO_SAFE_RUNPATH__
			if (*mylibname == '/')
#endif
				if ((tpnt = _dl_load_elf_shared_library(rflags, rpnt, mylibname)) != NULL)
					return tpnt;
			path_n = path+1;
		}
		path++;
	} while (!done);
	return NULL;
}
Beispiel #3
0
struct elf_resolve *_dl_load_shared_library(unsigned int rflags, struct dyn_elf **rpnt,
	struct elf_resolve *tpnt, char *full_libname, int attribute_unused trace_loaded_objects)
{
	char *pnt;
	struct elf_resolve *tpnt1;
	char *libname;

	_dl_internal_error_number = 0;
	libname = 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)
		goto goof;

	/* Skip over any initial initial './' and '/' stuff to
	 * get the short form libname with no path garbage */
	pnt = _dl_strrchr(libname, '/');
	if (pnt) {
		libname = pnt + 1;
	}

	_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
	   /usr/i486-sysv4/lib for /usr/lib in library names. */

	if (libname != full_libname) {
		_dl_if_debug_dprint("\ttrying file='%s'\n", full_libname);
		tpnt1 = _dl_load_elf_shared_library(rflags, rpnt, full_libname);
		if (tpnt1) {
			return tpnt1;
		}
	}

	/*
	 * The ABI specifies that RPATH is searched before LD_LIBRARY_PATH or
	 * the default path of /usr/lib.  Check in rpath directories.
	 */
#ifdef __LDSO_RUNPATH__
	pnt = (tpnt ? (char *) tpnt->dynamic_info[DT_RPATH] : NULL);
	if (pnt) {
		pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
		_dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt);
		if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt,
						      tpnt->libname)) != NULL)
			return tpnt1;

	}
#endif

#ifdef __LDSO_LD_LIBRARY_PATH__
	/* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
	if (_dl_library_path) {
		_dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path);
		if ((tpnt1 = search_for_named_library(libname, rflags, _dl_library_path, rpnt, NULL)) != NULL)
		{
			return tpnt1;
		}
	}
#endif
	/*
	 * The ABI specifies that RUNPATH is searched after LD_LIBRARY_PATH.
	 */
#ifdef __LDSO_RUNPATH__
	pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL);
	if (pnt) {
		pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
		_dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt);
		if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt, NULL)) != NULL)
			return tpnt1;
	}
#ifdef __LDSO_RUNPATH_OF_EXECUTABLE__
        /*
         * Try the DT_RPATH of the executable itself.
         */
        pnt = (char *) _dl_loaded_modules->dynamic_info[DT_RPATH];
        if (pnt) {
                pnt += (unsigned long) _dl_loaded_modules->dynamic_info[DT_STRTAB];
                _dl_if_debug_dprint("\tsearching exe's RPATH='%s'\n", pnt);
                if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt, NULL)) != NULL)
                        return tpnt1;
        }
#endif
#endif

	/*
	 * Where should the cache be searched?  There is no such concept in the
	 * ABI, so we have some flexibility here.  For now, search it before
	 * the hard coded paths that follow (i.e before /lib and /usr/lib).
	 */
#ifdef __LDSO_CACHE_SUPPORT__
	if (_dl_cache_addr != NULL && _dl_cache_addr != MAP_FAILED) {
		int i;
		header_t *header = (header_t *) _dl_cache_addr;
		libentry_t *libent = (libentry_t *) & header[1];
		char *strs = (char *) &libent[header->nlibs];

		_dl_if_debug_dprint("\tsearching cache='%s'\n", LDSO_CACHE);
		for (i = 0; i < header->nlibs; i++) {
			if ((libent[i].flags == LIB_ELF
			     || libent[i].flags == LIB_ELF_LIBC0
			     ||	libent[i].flags == LIB_ELF_LIBC5)
			 && _dl_strcmp(libname, strs + libent[i].sooffset) == 0
			 && (tpnt1 = _dl_load_elf_shared_library(rflags, rpnt, strs + libent[i].liboffset))
			) {
				return tpnt1;
			}
		}
	}
#endif

#ifdef LDSO_MULTILIB_DIR
	/* If multilib directory is selected, search it before falling back to
	   standard lib directories. */
	_dl_if_debug_dprint("\tsearching multilib lib path list\n");
	tpnt1 = search_for_named_library(libname, rflags,
					UCLIBC_RUNTIME_PREFIX LDSO_MULTILIB_DIR ":"
					UCLIBC_RUNTIME_PREFIX "usr/" LDSO_MULTILIB_DIR,
					rpnt, NULL);
	if (tpnt1 != NULL)
		return tpnt1;
#endif

#if defined SHARED && defined __LDSO_SEARCH_INTERP_PATH__
	/* Look for libraries wherever the shared library loader
	 * was installed */
	_dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath);
	tpnt1 = search_for_named_library(libname, rflags, _dl_ldsopath, rpnt, NULL);
	if (tpnt1 != NULL)
		return tpnt1;
#endif

	/* Lastly, search the standard list of paths for the library.
	   This list must exactly match the list in uClibc/ldso/util/ldd.c */
	_dl_if_debug_dprint("\tsearching full lib path list\n");
	tpnt1 = search_for_named_library(libname, rflags,
					UCLIBC_RUNTIME_PREFIX "lib:"
					UCLIBC_RUNTIME_PREFIX "usr/lib"
#ifndef __LDSO_CACHE_SUPPORT__
					":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib"
#endif
					, rpnt, NULL);
	if (tpnt1 != NULL)
		return tpnt1;

#ifdef __LDSO_RUNPATH_OF_EXECUTABLE__
	/* Very last resort, try the executable's DT_RUNPATH and DT_RPATH */
	/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#shobj_dependencies
	 * The set of directories specified by a given DT_RUNPATH entry is
	 * used to find only the immediate dependencies of the executable or
	 * shared object containing the DT_RUNPATH entry. That is, it is
	 * used only for those dependencies contained in the DT_NEEDED
	 * entries of the dynamic structure containing the DT_RUNPATH entry,
	 * itself. One object's DT_RUNPATH entry does not affect the search
	 * for any other object's dependencies.
	 *
	 * glibc (around 2.19) violates this and the usual suspects are
	 * abusing this bug^Wrelaxed, user-friendly behaviour.
	 */

	pnt = (char *) _dl_loaded_modules->dynamic_info[DT_RUNPATH];
	if (pnt) {
		pnt += (unsigned long) _dl_loaded_modules->dynamic_info[DT_STRTAB];
		_dl_if_debug_dprint("\tsearching exe's RUNPATH='%s'\n", pnt);
		if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt, NULL)) != NULL)
			return tpnt1;
	}
	pnt = (char *) _dl_loaded_modules->dynamic_info[DT_RPATH];
	if (pnt) {
		pnt += (unsigned long) _dl_loaded_modules->dynamic_info[DT_STRTAB];
		_dl_if_debug_dprint("\tsearching exe's RPATH='%s'\n", pnt);
		if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt, NULL)) != NULL)
			return tpnt1;
	}
#endif


goof:
	/* Well, we shot our wad on that one.  All we can do now is punt */
	if (_dl_internal_error_number)
		_dl_error_number = _dl_internal_error_number;
	else
		_dl_error_number = LD_ERROR_NOFILE;
	_dl_if_debug_dprint("Bummer: could not find '%s'!\n", libname);
	return NULL;
}
Beispiel #4
0
/* This function's behavior must exactly match that
 * in uClibc/ldso/util/ldd.c */
static struct elf_resolve *
search_for_named_library(const char *name, int secure, const char *path_list,
	struct dyn_elf **rpnt)
{
	char *path, *path_n, *mylibname;
	struct elf_resolve *tpnt;
	int done;

	if (path_list==NULL)
		return NULL;

	/* We need a writable copy of this string, but we don't
	 * need this allocated permanently since we don't want
	 * to leak memory, so use alloca to put path on the stack */
	done = _dl_strlen(path_list);
	path = alloca(done + 1);

	/* another bit of local storage */
	mylibname = alloca(2050);

	/* gcc inlines alloca using a single instruction adjusting
	 * the stack pointer and no stack overflow check and thus
	 * no NULL error return.  No point leaving in dead code... */
#if 0
	if (!path || !mylibname) {
		_dl_dprintf(2, "Out of memory!\n");
		_dl_exit(0);
	}
#endif

	_dl_memcpy(path, path_list, done+1);

	/* Unlike ldd.c, don't bother to eliminate double //s */

	/* Replace colons with zeros in path_list */
	/* : at the beginning or end of path maps to CWD */
	/* :: anywhere maps CWD */
	/* "" maps to CWD */ 
	done = 0;
	path_n = path;
	do {
		if (*path == 0) {
			*path = ':';
			done = 1;
		}
		if (*path == ':') {
			*path = 0;
			if (*path_n)
				_dl_strcpy(mylibname, path_n);
			else
				_dl_strcpy(mylibname, "."); /* Assume current dir if empty path */
			_dl_strcat(mylibname, "/");
			_dl_strcat(mylibname, name);
			if ((tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname)) != NULL)
				return tpnt;
			path_n = path+1;
		}
		path++;
	} while (!done);
	return NULL;
}
Beispiel #5
0
struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
	struct elf_resolve *tpnt, char *full_libname, int attribute_unused trace_loaded_objects)
{
	char *pnt;
	struct elf_resolve *tpnt1;
	char *libname;

	_dl_internal_error_number = 0;
	libname = 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)
		goto goof;

	/* Skip over any initial initial './' and '/' stuff to
	 * get the short form libname with no path garbage */
	pnt = _dl_strrchr(libname, '/');
	if (pnt) {
		libname = pnt + 1;
	}

	_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
	   /usr/i486-sysv4/lib for /usr/lib in library names. */

	if (libname != full_libname) {
		_dl_if_debug_dprint("\ttrying file='%s'\n", full_libname);
		tpnt1 = _dl_load_elf_shared_library(secure, rpnt, full_libname);
		if (tpnt1) {
			return tpnt1;
		}
	}

	/*
	 * The ABI specifies that RPATH is searched before LD_LIBRARY_PATH or
	 * the default path of /usr/lib.  Check in rpath directories.
	 */
#ifdef __LDSO_RUNPATH__
	pnt = (tpnt ? (char *) tpnt->dynamic_info[DT_RPATH] : NULL);
	if (pnt) {
		pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
		_dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt);
		if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)
			return tpnt1;
	}
#endif

	/* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
	if (_dl_library_path) {
		_dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path);
		if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL)
		{
			return tpnt1;
		}
	}

	/*
	 * The ABI specifies that RUNPATH is searched after LD_LIBRARY_PATH.
	 */
#ifdef __LDSO_RUNPATH__
	pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL);
	if (pnt) {
		pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
		_dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt);
		if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)
			return tpnt1;
	}
#endif

	/*
	 * Where should the cache be searched?  There is no such concept in the
	 * ABI, so we have some flexibility here.  For now, search it before
	 * the hard coded paths that follow (i.e before /lib and /usr/lib).
	 */
#ifdef __LDSO_CACHE_SUPPORT__
	if (_dl_cache_addr != NULL && _dl_cache_addr != MAP_FAILED) {
		int i;
		header_t *header = (header_t *) _dl_cache_addr;
		libentry_t *libent = (libentry_t *) & header[1];
		char *strs = (char *) &libent[header->nlibs];

		_dl_if_debug_dprint("\tsearching cache='%s'\n", LDSO_CACHE);
		for (i = 0; i < header->nlibs; i++) {
			if ((libent[i].flags == LIB_ELF
			     || libent[i].flags == LIB_ELF_LIBC0
			     ||	libent[i].flags == LIB_ELF_LIBC5)
			 && _dl_strcmp(libname, strs + libent[i].sooffset) == 0
			 && (tpnt1 = _dl_load_elf_shared_library(secure, rpnt, strs + libent[i].liboffset))
			) {
				return tpnt1;
			}
		}
	}
#endif

	/* Look for libraries wherever the shared library loader
	 * was installed */
	_dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath);
	tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt);
	if (tpnt1 != NULL)
		return tpnt1;

	/* Lastly, search the standard list of paths for the library.
	   This list must exactly match the list in uClibc/ldso/util/ldd.c */
	_dl_if_debug_dprint("\tsearching full lib path list\n");
	tpnt1 = search_for_named_library(libname, secure,
					UCLIBC_RUNTIME_PREFIX "lib:"
					UCLIBC_RUNTIME_PREFIX "usr/lib"
#ifndef __LDSO_CACHE_SUPPORT__
					":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib"
#endif
					, rpnt);
	if (tpnt1 != NULL)
		return tpnt1;

goof:
	/* Well, we shot our wad on that one.  All we can do now is punt */
	if (_dl_internal_error_number)
		_dl_error_number = _dl_internal_error_number;
	else
		_dl_error_number = LD_ERROR_NOFILE;
	_dl_if_debug_dprint("Bummer: could not find '%s'!\n", libname);
	return NULL;
}