about summary refs log tree commit diff
path: root/src/ldso
diff options
context:
space:
mode:
Diffstat (limited to 'src/ldso')
-rw-r--r--src/ldso/dynlink.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index 0eb763e7..4a371839 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -599,8 +599,7 @@ static int fixup_rpath(struct dso *p, char *buf, size_t buf_size)
 	size_t n, l;
 	const char *s, *t, *origin;
 	char *d;
-	if (p->rpath) return 0;
-	if (!p->rpath_orig) return -1;
+	if (p->rpath || !p->rpath_orig) return 0;
 	if (!strchr(p->rpath_orig, '$')) {
 		p->rpath = p->rpath_orig;
 		return 0;
@@ -609,11 +608,11 @@ static int fixup_rpath(struct dso *p, char *buf, size_t buf_size)
 	s = p->rpath_orig;
 	while ((t=strchr(s, '$'))) {
 		if (strncmp(t, "$ORIGIN", 7) && strncmp(t, "${ORIGIN}", 9))
-			return -1;
+			return 0;
 		s = t+1;
 		n++;
 	}
-	if (n > SSIZE_MAX/PATH_MAX) return -1;
+	if (n > SSIZE_MAX/PATH_MAX) return 0;
 
 	if (p->kernel_mapped) {
 		/* $ORIGIN searches cannot be performed for the main program
@@ -623,10 +622,18 @@ static int fixup_rpath(struct dso *p, char *buf, size_t buf_size)
 		 * since the library's pathname came from a trusted source
 		 * (either system paths or a call to dlopen). */
 		if (libc.secure)
-			return -1;
+			return 0;
 		l = readlink("/proc/self/exe", buf, buf_size);
-		if (l >= buf_size)
+		if (l == -1) switch (errno) {
+		case ENOENT:
+		case ENOTDIR:
+		case EACCES:
+			break;
+		default:
 			return -1;
+		}
+		if (l >= buf_size)
+			return 0;
 		buf[l] = 0;
 		origin = buf;
 	} else {
@@ -735,9 +742,12 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
 		if (strlen(name) > NAME_MAX) return 0;
 		fd = -1;
 		if (env_path) fd = path_open(name, env_path, buf, sizeof buf);
-		for (p=needed_by; fd == -1 && p; p=p->needed_by)
-			if (!fixup_rpath(p, buf, sizeof buf))
+		for (p=needed_by; fd == -1 && p; p=p->needed_by) {
+			if (fixup_rpath(p, buf, sizeof buf) < 0)
+				fd = -2; /* Inhibit further search. */
+			if (p->rpath)
 				fd = path_open(name, p->rpath, buf, sizeof buf);
+		}
 		if (fd == -1) {
 			if (!sys_path) {
 				char *prefix = 0;