Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <n1FH_ABRqLH5azVtlHjGr7zNxzSeSSkTseltE1X-55Zjb5Lv2j_ABU33FGvFLFDc6qK1osA8YMzog5D2gs6qmgCL2d8WePdhY3yYQiZevtE=@harmenstoppels.nl>
Date: Sun, 20 Mar 2022 14:19:23 +0000
From: Harmen Stoppels <me@...menstoppels.nl>
To: "musl@...ts.openwall.com" <musl@...ts.openwall.com>
Subject: [PATCH] dynlink.c: locate ld-musl-<arch>.path better.

Fixes an issue where the dynamic loader can't locate the
`ld-musl-<arch>.path` file when the interpreter is not a normalized
path. The following works after this commit:

```
./path/to/ld-musl-<arch>.so.1 ./exe
/absolute/path/to////ld-musl-<arch>.so.1 ./exe
/absolute/path/to/./ld-musl-<arch>.so.1 ./exe
```

The `ld-musl-<arch>.path` file is now located by simply appending
`/../etc/ld-musl-<arch>.path` to the directory name of `ldso.name`, or
falls back to `/etc/ld-musl-<arch>.path` when no directory separator is
found in `ldso.name`.

This means that there's currently one limitation where

```
PATH="/absolute/path/to/loader/dir:$PATH" ld-musl-<arch.so.1> ./exe
```

still fails to locate `ld-musl-<arch>.path` relative to the dynamic
loader's path.
---
 ldso/dynlink.c | 29 +++++++++++------------------
 1 file changed, 11 insertions(+), 18 deletions(-)

diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 5b9c8be4..5a508ddf 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -1061,25 +1061,18 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
 		}
 		if (fd == -1) {
 			if (!sys_path) {
-				char *prefix = 0;
-				size_t prefix_len;
-				if (ldso.name[0]=='/') {
-					char *s, *t, *z;
-					for (s=t=z=ldso.name; *s; s++)
-						if (*s=='/') z=t, t=s;
-					prefix_len = z-ldso.name;
-					if (prefix_len < PATH_MAX)
-						prefix = ldso.name;
+				/* etc_ldso_path is <dir of ld.so>/../etc/ld-musl-<arch>.path when
+				 * we have a path for ld.so, otherwise fall back to
+				 * /etc/ld-musl-<arch>.path. */
+				char suffix[] = "/etc/ld-musl-" LDSO_ARCH ".path";
+				char *ldso_dir = strrchr(ldso.name, '/');
+				size_t prefix_len = ldso_dir ? ldso_dir - ldso.name + 3 : 0;
+				char etc_ldso_path[prefix_len + sizeof suffix];
+				if (ldso_dir) {
+					memcpy(etc_ldso_path, ldso.name, prefix_len - 2);
+					memcpy(etc_ldso_path + prefix_len - 2, "..", 2);
 				}
-				if (!prefix) {
-					prefix = "";
-					prefix_len = 0;
-				}
-				char etc_ldso_path[prefix_len + 1
-					+ sizeof "/etc/ld-musl-" LDSO_ARCH ".path"];
-				snprintf(etc_ldso_path, sizeof etc_ldso_path,
-					"%.*s/etc/ld-musl-" LDSO_ARCH ".path",
-					(int)prefix_len, prefix);
+				memcpy(etc_ldso_path + prefix_len, suffix, sizeof suffix);
 				fd = open(etc_ldso_path, O_RDONLY|O_CLOEXEC);
 				if (fd>=0) {
 					size_t n = 0;
--
2.25.1


Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.