Add LD_LIBRARY_PATH support to bionic's linker
This commit is contained in:
parent
0353195f34
commit
bc3a5c26f1
1 changed files with 52 additions and 4 deletions
|
@ -53,6 +53,10 @@
|
|||
|
||||
#define SO_MAX 96
|
||||
|
||||
/* Assume average path length of 64 and max 8 paths */
|
||||
#define LDPATH_BUFSIZE 512
|
||||
#define LDPATH_MAX 8
|
||||
|
||||
/* >>> IMPORTANT NOTE - READ ME BEFORE MODIFYING <<<
|
||||
*
|
||||
* Do NOT use malloc() and friends or pthread_*() code here.
|
||||
|
@ -66,7 +70,6 @@
|
|||
* - should we do anything special for STB_WEAK symbols?
|
||||
* - are we doing everything we should for ARM_COPY relocations?
|
||||
* - cleaner error reporting
|
||||
* - configuration for paths (LD_LIBRARY_PATH?)
|
||||
* - after linking, set as much stuff as possible to READONLY
|
||||
* and NOEXEC
|
||||
* - linker hardcodes PAGE_SIZE and PAGE_MASK because the kernel
|
||||
|
@ -89,6 +92,9 @@ static soinfo *freelist = NULL;
|
|||
static soinfo *solist = &libdl_info;
|
||||
static soinfo *sonext = &libdl_info;
|
||||
|
||||
static char ldpaths_buf[LDPATH_BUFSIZE];
|
||||
static const char *ldpaths[LDPATH_MAX + 1];
|
||||
|
||||
int debug_verbosity;
|
||||
static int pid;
|
||||
|
||||
|
@ -503,13 +509,12 @@ static int _open_lib(const char *name)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* TODO: Need to add support for initializing the so search path with
|
||||
* LD_LIBRARY_PATH env variable for non-setuid programs. */
|
||||
static int open_library(const char *name)
|
||||
{
|
||||
int fd;
|
||||
char buf[512];
|
||||
const char **path;
|
||||
int n;
|
||||
|
||||
TRACE("[ %5d opening %s ]\n", pid, name);
|
||||
|
||||
|
@ -519,8 +524,21 @@ static int open_library(const char *name)
|
|||
if ((name[0] == '/') && ((fd = _open_lib(name)) >= 0))
|
||||
return fd;
|
||||
|
||||
for (path = ldpaths; *path; path++) {
|
||||
n = snprintf(buf, sizeof(buf), "%s/%s", *path, name);
|
||||
if (n < 0 || n >= (int)sizeof(buf)) {
|
||||
WARN("Ignoring very long library path: %s/%s\n", *path, name);
|
||||
continue;
|
||||
}
|
||||
if ((fd = _open_lib(buf)) >= 0)
|
||||
return fd;
|
||||
}
|
||||
for (path = sopaths; *path; path++) {
|
||||
snprintf(buf, sizeof(buf), "%s/%s", *path, name);
|
||||
n = snprintf(buf, sizeof(buf), "%s/%s", *path, name);
|
||||
if (n < 0 || n >= (int)sizeof(buf)) {
|
||||
WARN("Ignoring very long library path: %s/%s\n", *path, name);
|
||||
continue;
|
||||
}
|
||||
if ((fd = _open_lib(buf)) >= 0)
|
||||
return fd;
|
||||
}
|
||||
|
@ -1683,6 +1701,29 @@ fail:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void parse_library_path(char *path, char *delim)
|
||||
{
|
||||
size_t len;
|
||||
char *ldpaths_bufp = ldpaths_buf;
|
||||
int i = 0;
|
||||
|
||||
len = strlcpy(ldpaths_buf, path, sizeof(ldpaths_buf));
|
||||
|
||||
while (i < LDPATH_MAX && (ldpaths[i] = strsep(&ldpaths_bufp, delim))) {
|
||||
if (*ldpaths[i] != '\0')
|
||||
++i;
|
||||
}
|
||||
|
||||
/* Forget the last path if we had to truncate; this occurs if the 2nd to
|
||||
* last char isn't '\0' (i.e. not originally a delim). */
|
||||
if (i > 0 && len >= sizeof(ldpaths_buf) &&
|
||||
ldpaths_buf[sizeof(ldpaths_buf) - 2] != '\0') {
|
||||
ldpaths[i - 1] = NULL;
|
||||
} else {
|
||||
ldpaths[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return 0;
|
||||
|
@ -1701,6 +1742,7 @@ unsigned __linker_init(unsigned **elfdata)
|
|||
unsigned *vecs = (unsigned*) (argv + argc + 1);
|
||||
soinfo *si;
|
||||
struct link_map * map;
|
||||
char *ldpath_env = NULL;
|
||||
|
||||
pid = getpid();
|
||||
|
||||
|
@ -1718,6 +1760,8 @@ unsigned __linker_init(unsigned **elfdata)
|
|||
while(vecs[0] != 0) {
|
||||
if(!strncmp((char*) vecs[0], "DEBUG=", 6)) {
|
||||
debug_verbosity = atoi(((char*) vecs[0]) + 6);
|
||||
} else if(!strncmp((char*) vecs[0], "LD_LIBRARY_PATH=", 16)) {
|
||||
ldpath_env = (char*) vecs[0] + 16;
|
||||
}
|
||||
vecs++;
|
||||
}
|
||||
|
@ -1777,6 +1821,10 @@ unsigned __linker_init(unsigned **elfdata)
|
|||
si->wrprotect_start = 0xffffffff;
|
||||
si->wrprotect_end = 0;
|
||||
|
||||
/* Use LD_LIBRARY_PATH if we aren't setuid/setgid */
|
||||
if (ldpath_env && getuid() == geteuid() && getgid() == getegid())
|
||||
parse_library_path(ldpath_env, ":");
|
||||
|
||||
if(link_image(si, 0)) {
|
||||
char errmsg[] = "CANNOT LINK EXECUTABLE\n";
|
||||
write(2, __linker_dl_err_buf, strlen(__linker_dl_err_buf));
|
||||
|
|
Loading…
Reference in a new issue