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
/*
 * Extract a trace specification field, and setup the tracespec struct
 * accordingly.
 */
const char *
_dl_trace_parse_spec(const char *var, struct tracespec *spec)
{
	const char *start, *end;

	if (*var == '!') {
		spec->inverse = 1;
		var++;
	}

	start = var;
	end = _dl_strchr(start, ':');
	if (end == NULL)
		end = start + _dl_strlen(start);

	if (end != start) {
		spec->spec = _dl_malloc(1 + end - start);
		if (spec->spec == NULL)
			_dl_exit(8);

		_dl_bcopy(start, spec->spec, end - start);
		spec->spec[end - start] = '\0';
	}

	if (*end == ':')
		end++;

	return end;
}
Beispiel #3
0
/*
 * Check if a given name matches a trace specification list.
 */
static int
_dl_trace_match(const char *name, struct tracespec *spec, int allow_so)
{
	const char *list, *end, *next;
	size_t span;
	int match;

	/* no spec means trace everything */
	if (spec->spec == NULL)
		return 1;

	match = 0;
	list = spec->spec;
	end = list + _dl_strlen(list);

	while (*list != '\0') {
		next = _dl_strchr(list, ',');
		if (next == NULL)
			next = end;

		span = next - list;
		if (span != 0 && *(next - 1) == '*')
			span--;

		if (span != 0 && _dl_strncmp(name, list, span) == 0) {
			/*
			 * If the object name matches the specification
			 * fragment so far, it's a match if:
			 *   + the specification ends in a star (wildcard
			 *     match)
			 *   + there are no remaining chars in both the
			 *     object name and the specification (exact
			 *     match)
			 *   + the specification ends (no star) and the
			 *     object name continues with ".so" (radix
			 *     match) and `allow_so' is nonzero.
			 */
			if (list[span] == '*' ||
			    name[span] == '\0' ||
			    (allow_so &&
			    _dl_strncmp(name + span, ".so", 3) == 0)) {
				match = 1;
				break;
			}
		}

		while (*next == ',')
			next++;
		list = next;
	}

	return spec->inverse ? !match : match;
}
Beispiel #4
0
void
_dl_trace_object_setup(elf_object_t *object)
{
	const char *basename, *slash;

	object->traced = 0;

	if (_dl_traceplt) {
		basename = object->load_name;
		while (*basename == '/') {
			basename++;
			slash = _dl_strchr(basename, '/');
			if (slash == NULL)
				break;
			basename = slash;
		}
		if (_dl_trace_match(basename, &_dl_tracelib, 1))
			object->traced = 1;
	}
}
Beispiel #5
0
/*
 * char *dl_realpath(const char *path, char resolved[PATH_MAX]);
 *
 * Find the real name of path, by removing all ".", ".." and symlink
 * components.  Returns (resolved) on success, or (NULL) on failure,
 * in which case the path which caused trouble is left in (resolved).
 */
char *
_dl_realpath(const char *path, char *resolved)
{
	struct stat sb;
	const char *p, *s;
	char *q;
	size_t left_len, resolved_len;
	unsigned symlinks;
	int slen, mem_allocated, ret;
	char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];

	if (path[0] == '\0') {
		return (NULL);
	}

	if (resolved == NULL) {
		resolved = _dl_malloc(PATH_MAX);
		if (resolved == NULL)
			return (NULL);
		mem_allocated = 1;
	} else
		mem_allocated = 0;

	symlinks = 0;
	if (path[0] == '/') {
		resolved[0] = '/';
		resolved[1] = '\0';
		if (path[1] == '\0')
			return (resolved);
		resolved_len = 1;
		left_len = _dl_strlcpy(left, path + 1, sizeof(left));
	} else {
		if (_dl_getcwd(resolved, PATH_MAX) <= 0) {
			if (mem_allocated)
				_dl_free(resolved);
			else
				_dl_strlcpy(resolved, ".", PATH_MAX);
			return (NULL);
		}
		resolved_len = _dl_strlen(resolved);
		left_len = _dl_strlcpy(left, path, sizeof(left));
	}
	if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
		goto err;
	}

	/*
	 * Iterate over path components in `left'.
	 */
	while (left_len != 0) {
		/*
		 * Extract the next path component and adjust `left'
		 * and its length.
		 */
		p = _dl_strchr(left, '/');
		s = p ? p : left + left_len;
		if (s - left >= sizeof(next_token)) {
			goto err;
		}
		_dl_bcopy(left, next_token, s - left);
		next_token[s - left] = '\0';
		left_len -= s - left;
		if (p != NULL)
			_dl_bcopy(s + 1, left, left_len + 1);
		if (resolved[resolved_len - 1] != '/') {
			if (resolved_len + 1 >= PATH_MAX) {
				goto err;
			}
			resolved[resolved_len++] = '/';
			resolved[resolved_len] = '\0';
		}
		if (next_token[0] == '\0')
			continue;
		else if (_dl_strcmp(next_token, ".") == 0)
			continue;
		else if (_dl_strcmp(next_token, "..") == 0) {
			/*
			 * Strip the last path component except when we have
			 * single "/"
			 */
			if (resolved_len > 1) {
				resolved[resolved_len - 1] = '\0';
				q = _dl_strrchr(resolved, '/') + 1;
				*q = '\0';
				resolved_len = q - resolved;
			}
			continue;
		}

		/*
		 * Append the next path component and lstat() it. If
		 * lstat() fails we still can return successfully if
		 * there are no more path components left.
		 */
		resolved_len = _dl_strlcat(resolved, next_token, PATH_MAX);
		if (resolved_len >= PATH_MAX) {
			goto err;
		}
		if ((ret = _dl_lstat(resolved, &sb)) != 0) {
			if (ret == ENOENT && p == NULL) {
				return (resolved);
			}
			goto err;
		}
		if (S_ISLNK(sb.st_mode)) {
			if (symlinks++ > SYMLOOP_MAX) {
				goto err;
			}
			slen = _dl_readlink(resolved, symlink, sizeof(symlink) - 1);
			if (slen < 0)
				goto err;
			symlink[slen] = '\0';
			if (symlink[0] == '/') {
				resolved[1] = 0;
				resolved_len = 1;
			} else if (resolved_len > 1) {
				/* Strip the last path component. */
				resolved[resolved_len - 1] = '\0';
				q = _dl_strrchr(resolved, '/') + 1;
				*q = '\0';
				resolved_len = q - resolved;
			}

			/*
			 * If there are any path components left, then
			 * append them to symlink. The result is placed
			 * in `left'.
			 */
			if (p != NULL) {
				if (symlink[slen - 1] != '/') {
					if (slen + 1 >= sizeof(symlink)) {
						goto err;
					}
					symlink[slen] = '/';
					symlink[slen + 1] = 0;
				}
				left_len = _dl_strlcat(symlink, left, sizeof(symlink));
				if (left_len >= sizeof(left)) {
					goto err;
				}
			}
			left_len = _dl_strlcpy(left, symlink, sizeof(left));
		}
	}

	/*
	 * Remove trailing slash except when the resolved pathname
	 * is a single "/".
	 */
	if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
		resolved[resolved_len - 1] = '\0';
	return (resolved);

err:
	if (mem_allocated)
		_dl_free(resolved);
	return (NULL);
}