mirror of
git://git.musl-libc.org/musl
synced 2025-03-08 04:37:31 +00:00
add rpath $ORIGIN processing to dynamic linker
This commit is contained in:
parent
709355e1f6
commit
a897a20a57
@ -72,8 +72,9 @@ struct dso {
|
||||
signed char global;
|
||||
char relocated;
|
||||
char constructed;
|
||||
char kernel_mapped;
|
||||
struct dso **deps, *needed_by;
|
||||
char *rpath;
|
||||
char *rpath_orig, *rpath;
|
||||
void *tls_image;
|
||||
size_t tls_len, tls_size, tls_align, tls_id, tls_offset;
|
||||
void **new_dtv;
|
||||
@ -448,6 +449,58 @@ static int path_open(const char *name, const char *s, char *buf, size_t buf_size
|
||||
}
|
||||
}
|
||||
|
||||
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 (!strchr(p->rpath_orig, '$')) {
|
||||
p->rpath = p->rpath_orig;
|
||||
return 0;
|
||||
}
|
||||
n = 0;
|
||||
s = p->rpath_orig;
|
||||
while ((t=strstr(s, "$ORIGIN")) || (t=strstr(s, "${ORIGIN}"))) {
|
||||
s = t+1;
|
||||
n++;
|
||||
}
|
||||
if (n > SSIZE_MAX/PATH_MAX) return -1;
|
||||
|
||||
if (p->kernel_mapped) {
|
||||
/* $ORIGIN searches cannot be performed for the main program
|
||||
* when it is suid/sgid/AT_SECURE. This is because the
|
||||
* pathname is under the control of the caller of execve.
|
||||
* For libraries, however, $ORIGIN can be processed safely
|
||||
* since the library's pathname came from a trusted source
|
||||
* (either system paths or a call to dlopen). */
|
||||
if (libc.secure)
|
||||
return -1;
|
||||
if (readlink("/proc/self/exe", buf, buf_size) >= buf_size)
|
||||
return -1;
|
||||
origin = buf;
|
||||
} else {
|
||||
origin = p->name;
|
||||
}
|
||||
t = strrchr(origin, '/');
|
||||
l = t ? t-origin : 0;
|
||||
p->rpath = malloc(strlen(p->rpath_orig) + n*l + 1);
|
||||
if (!p->rpath) return -1;
|
||||
|
||||
d = p->rpath;
|
||||
s = p->rpath_orig;
|
||||
while ((t=strstr(s, "$ORIGIN")) || (t=strstr(s, "${ORIGIN}"))) {
|
||||
memcpy(d, s, t-s);
|
||||
d += t-s;
|
||||
memcpy(d, origin, l);
|
||||
d += l;
|
||||
s = t + 7 + 2*(t[1]=='{');
|
||||
}
|
||||
strcpy(d, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void decode_dyn(struct dso *p)
|
||||
{
|
||||
size_t dyn[DYN_CNT] = {0};
|
||||
@ -457,7 +510,7 @@ static void decode_dyn(struct dso *p)
|
||||
if (dyn[0]&(1<<DT_HASH))
|
||||
p->hashtab = (void *)(p->base + dyn[DT_HASH]);
|
||||
if (dyn[0]&(1<<DT_RPATH))
|
||||
p->rpath = (void *)(p->strings + dyn[DT_RPATH]);
|
||||
p->rpath_orig = (void *)(p->strings + dyn[DT_RPATH]);
|
||||
if (search_vec(p->dynv, dyn, DT_GNU_HASH))
|
||||
p->ghashtab = (void *)(p->base + *dyn);
|
||||
if (search_vec(p->dynv, dyn, DT_VERSYM))
|
||||
@ -525,7 +578,7 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
|
||||
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)
|
||||
if (p->rpath)
|
||||
if (!fixup_rpath(p, buf, sizeof buf))
|
||||
fd = path_open(name, p->rpath, buf, sizeof buf);
|
||||
if (fd < 0) {
|
||||
if (!sys_path) {
|
||||
@ -917,6 +970,7 @@ void *__dynlink(int argc, char **argv)
|
||||
|| aux[AT_GID]!=aux[AT_EGID] || aux[AT_SECURE]) {
|
||||
env_path = 0;
|
||||
env_preload = 0;
|
||||
libc.secure = 1;
|
||||
}
|
||||
|
||||
/* If the dynamic linker was invoked as a program itself, AT_BASE
|
||||
@ -933,6 +987,7 @@ void *__dynlink(int argc, char **argv)
|
||||
lib->base = (void *)aux[AT_BASE];
|
||||
lib->name = lib->shortname = "libc.so";
|
||||
lib->global = 1;
|
||||
lib->kernel_mapped = 1;
|
||||
ehdr = (void *)lib->base;
|
||||
lib->phnum = ehdr->e_phnum;
|
||||
lib->phdr = (void *)(aux[AT_BASE]+ehdr->e_phoff);
|
||||
@ -962,6 +1017,7 @@ void *__dynlink(int argc, char **argv)
|
||||
if (app->tls_size) app->tls_image = (char *)app->base + tls_image;
|
||||
if (interp_off) lib->name = (char *)app->base + interp_off;
|
||||
app->name = argv[0];
|
||||
app->kernel_mapped = 1;
|
||||
app->dynv = (void *)(app->base + find_dyn(
|
||||
(void *)aux[AT_PHDR], aux[AT_PHNUM], aux[AT_PHENT]));
|
||||
find_map_range((void *)aux[AT_PHDR],
|
||||
|
Loading…
Reference in New Issue
Block a user