aboutsummaryrefslogtreecommitdiffstats
path: root/main/libc0.9.32/0008-ldso-limited-support-for-ORIGIN-in-rpath.patch
blob: 58386eb89697f64adbec38b57f596aeb7449b076 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
From 4eb3c29b8ee0e77f3b8b98e697a6ce0b5571a0f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
Date: Fri, 18 Mar 2011 10:53:56 +0200
Subject: [PATCH 8/8] ldso: limited support for $ORIGIN in rpath
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Handle it if it's in the beginning of the rpath entry as it
should be.

Posted to uclibc ml:
http://old.nabble.com/-PATCH-1-3--ldso%3A-limited-support-for-$ORIGIN-in-rpath-td31181219.html

Signed-off-by: Timo Teräs <timo.teras@iki.fi>
Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>

Conflicts:

	ldso/ldso/dl-elf.c
	ldso/ldso/ldso.c
---
 ldso/ldso/dl-elf.c |   81 ++++++++++++++++++++++++++++++---------------------
 ldso/ldso/ldso.c   |   18 +++++++++--
 2 files changed, 63 insertions(+), 36 deletions(-)

diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index b9de199..547d9e0 100644
--- a/ldso/ldso/dl-elf.c
+++ b/ldso/ldso/dl-elf.c
@@ -132,57 +132,71 @@ _dl_protect_relro (struct elf_resolve *l)
 /* 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)
+search_for_named_library_with_origin(const char *name, int secure,
+	const char *path_list, struct dyn_elf **rpnt, const char *origin)
 {
-	char *path, *path_n, *mylibname;
+	char *mylibname;
+	const char *p, *pn;
 	struct elf_resolve *tpnt;
-	int done;
+	int plen;
 
 	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);
-			if ((tpnt = _dl_load_elf_shared_library(rflags, rpnt, mylibname)) != NULL)
-				return tpnt;
-			path_n = path+1;
+	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;
+			if (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, ".");
 		}
-		path++;
-	} while (!done);
+		_dl_strcat(mylibname, "/");
+		_dl_strcat(mylibname, name);
+
+		tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname);
+		if (tpnt != NULL)
+			return tpnt;
+	}
+
 	return NULL;
 }
 
+static struct elf_resolve *
+search_for_named_library(const char *name, int secure, const char *path_list,
+	struct dyn_elf **rpnt)
+{
+	return search_for_named_library_with_origin(name, secure, path_list, rpnt, NULL);
+}
+
 /* Used to return error codes back to dlopen et. al.  */
 unsigned long _dl_error_number;
 unsigned long _dl_internal_error_number;
@@ -231,7 +245,8 @@ struct elf_resolve *_dl_load_shared_library(unsigned rflags, struct dyn_elf **rp
 	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)) != NULL)
+		if ((tpnt1 = search_for_named_library_with_origin(libname, rflags, pnt, rpnt,
+						      tpnt->libname)) != NULL)
 			return tpnt1;
 	}
 #endif
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index 7690036..78dc92d 100644
--- a/ldso/ldso/ldso.c
+++ b/ldso/ldso/ldso.c
@@ -403,6 +403,20 @@ static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list,
 	return p - list;
 }
 
+static void _dl_setup_progname(const char *argv0)
+{
+	char image[PATH_MAX];
+	ssize_t s;
+
+	s = _dl_readlink("/proc/self/exe", image, sizeof(image));
+	if (s > 0 && image[0] == '/') {
+		image[s] = 0;
+		_dl_progname = _dl_strdup(image);
+	} else if (argv0) {
+		_dl_progname = argv0;
+	}
+}
+
 void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 			  ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv
 			  DL_GET_READY_TO_RUN_EXTRA_PARMS)
@@ -454,9 +468,7 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 	 * been fixed up by now.  Still no function calls outside of this
 	 * library, since the dynamic resolver is not yet ready.
 	 */
-	if (argv[0]) {
-		_dl_progname = argv[0];
-	}
+	_dl_setup_progname(argv[0]);
 
 #ifndef __LDSO_STANDALONE_SUPPORT__
 	if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
-- 
1.7.8.4