about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2015-04-01 20:27:29 -0400
committerRich Felker <dalias@aerifal.cx>2015-04-01 20:27:29 -0400
commit5d1c8c995647914c8682498f613672b6b935ca15 (patch)
tree7466d95e5fde8e52a630b5c875aeff63faca2933 /src
parentfd427c4eaeed4d1099acc7b6188e41c6cfa5bca5 (diff)
downloadmusl-5d1c8c995647914c8682498f613672b6b935ca15.tar.gz
musl-5d1c8c995647914c8682498f613672b6b935ca15.tar.xz
musl-5d1c8c995647914c8682498f613672b6b935ca15.zip
harden dynamic linker library path search
transient errors during the path search should not allow the search to
continue and possibly open the wrong file. this patch eliminates most
conditions where that could happen, but there is still a possibility
that $ORIGIN-based rpath processing will have an allocation failure,
causing the search to skip such a path. fixing this is left as a
separate task.

a small bug where overly-long path components caused an infinite loop
rather than being skipped/ignored is also fixed.
Diffstat (limited to 'src')
-rw-r--r--src/ldso/dynlink.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index b0d5ff46..0eb763e7 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -576,9 +576,20 @@ static int path_open(const char *name, const char *s, char *buf, size_t buf_size
 		s += strspn(s, ":\n");
 		l = strcspn(s, ":\n");
 		if (l-1 >= INT_MAX) return -1;
-		if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) >= buf_size)
-			continue;
-		if ((fd = open(buf, O_RDONLY|O_CLOEXEC))>=0) return fd;
+		if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) {
+			if ((fd = open(buf, O_RDONLY|O_CLOEXEC))>=0) return fd;
+			switch (errno) {
+			case ENOENT:
+			case ENOTDIR:
+			case EACCES:
+			case ENAMETOOLONG:
+				break;
+			default:
+				/* Any negative value but -1 will inhibit
+				 * futher path search. */
+				return -2;
+			}
+		}
 		s += l;
 	}
 }
@@ -724,10 +735,10 @@ 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 < 0 && p; p=p->needed_by)
+		for (p=needed_by; fd == -1 && p; p=p->needed_by)
 			if (!fixup_rpath(p, buf, sizeof buf))
 				fd = path_open(name, p->rpath, buf, sizeof buf);
-		if (fd < 0) {
+		if (fd == -1) {
 			if (!sys_path) {
 				char *prefix = 0;
 				size_t prefix_len;