|
|
@ -48,7 +48,7 @@ struct dso |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
static struct dso *head, *tail, *libc; |
|
|
static struct dso *head, *tail, *libc; |
|
|
static int trust_env; |
|
|
static char *env_path, *sys_path; |
|
|
|
|
|
|
|
|
#define AUX_CNT 15 |
|
|
#define AUX_CNT 15 |
|
|
#define DYN_CNT 34 |
|
|
#define DYN_CNT 34 |
|
|
@ -205,6 +205,20 @@ static void *map_library(int fd, size_t *lenp, unsigned char **basep, size_t *dy |
|
|
return map; |
|
|
return map; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int path_open(const char *name, const char *search) |
|
|
|
|
|
{ |
|
|
|
|
|
char buf[2*NAME_MAX+2]; |
|
|
|
|
|
const char *s, *z; |
|
|
|
|
|
int l, fd; |
|
|
|
|
|
for (s=search; *s; s+=l+!!z) { |
|
|
|
|
|
z = strchr(s, ':'); |
|
|
|
|
|
l = z ? z-s : strlen(s); |
|
|
|
|
|
snprintf(buf, sizeof buf, "%.*s/%s", l, s, name); |
|
|
|
|
|
if ((fd = open(buf, O_RDONLY))>=0) return fd; |
|
|
|
|
|
} |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
static struct dso *load_library(const char *name) |
|
|
static struct dso *load_library(const char *name) |
|
|
{ |
|
|
{ |
|
|
unsigned char *base, *map; |
|
|
unsigned char *base, *map; |
|
|
@ -242,14 +256,20 @@ static struct dso *load_library(const char *name) |
|
|
if (name[0] == '/') { |
|
|
if (name[0] == '/') { |
|
|
fd = open(name, O_RDONLY); |
|
|
fd = open(name, O_RDONLY); |
|
|
} else { |
|
|
} else { |
|
|
static const char path[] = "/lib/\0/usr/local/lib/\0/usr/lib/\0"; |
|
|
|
|
|
const char *s; |
|
|
|
|
|
char buf[NAME_MAX+32]; |
|
|
|
|
|
if (strlen(name) > NAME_MAX || strchr(name, '/')) return 0; |
|
|
if (strlen(name) > NAME_MAX || strchr(name, '/')) return 0; |
|
|
for (s=path; *s; s+=strlen(s)+1) { |
|
|
fd = -1; |
|
|
strcpy(buf, s); |
|
|
if (env_path) fd = path_open(name, env_path); |
|
|
strcat(buf, name); |
|
|
if (fd < 0) { |
|
|
if ((fd = open(buf, O_RDONLY))>=0) break; |
|
|
if (!sys_path) { |
|
|
|
|
|
FILE *f = fopen(ETC_LDSO_PATH, "r"); |
|
|
|
|
|
if (f) { |
|
|
|
|
|
if (getline(&sys_path, (size_t[1]){0}, f) > 0) |
|
|
|
|
|
sys_path[strlen(sys_path)-1]=0; |
|
|
|
|
|
fclose(f); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (sys_path) fd = path_open(name, sys_path); |
|
|
|
|
|
else fd = path_open(name, "/lib:/usr/local/lib:/usr/lib"); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
if (fd < 0) return 0; |
|
|
if (fd < 0) return 0; |
|
|
@ -342,11 +362,19 @@ void *__dynlink(int argc, char **argv, size_t *got) |
|
|
struct dso lib, app; |
|
|
struct dso lib, app; |
|
|
|
|
|
|
|
|
/* Find aux vector just past environ[] */ |
|
|
/* Find aux vector just past environ[] */ |
|
|
for (i=argc+1; argv[i]; i++); |
|
|
for (i=argc+1; argv[i]; i++) |
|
|
|
|
|
if (!memcmp(argv[i], "LD_LIBRARY_PATH=", 16)) |
|
|
|
|
|
env_path = argv[i]+16; |
|
|
auxv = (void *)(argv+i+1); |
|
|
auxv = (void *)(argv+i+1); |
|
|
|
|
|
|
|
|
decode_vec(auxv, aux, AUX_CNT); |
|
|
decode_vec(auxv, aux, AUX_CNT); |
|
|
|
|
|
|
|
|
|
|
|
/* Only trust user/env if kernel says we're not suid/sgid */ |
|
|
|
|
|
if ((aux[0]&0x7800)!=0x7800 || aux[AT_UID]!=aux[AT_EUID] |
|
|
|
|
|
|| aux[AT_GID]!=aux[AT_EGID]) { |
|
|
|
|
|
env_path = 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/* Relocate ldso's DYNAMIC pointer and load vector */ |
|
|
/* Relocate ldso's DYNAMIC pointer and load vector */ |
|
|
decode_vec((void *)(got[0] += aux[AT_BASE]), lib_dyn, DYN_CNT); |
|
|
decode_vec((void *)(got[0] += aux[AT_BASE]), lib_dyn, DYN_CNT); |
|
|
|
|
|
|
|
|
@ -385,11 +413,6 @@ void *__dynlink(int argc, char **argv, size_t *got) |
|
|
|
|
|
|
|
|
/* At this point the standard library is fully functional */ |
|
|
/* At this point the standard library is fully functional */ |
|
|
|
|
|
|
|
|
/* Only trust user/env if kernel says we're not suid/sgid */ |
|
|
|
|
|
trust_env = (aux[0]&0x7800)==0x7800 |
|
|
|
|
|
&& aux[AT_UID]==aux[AT_EUID] |
|
|
|
|
|
&& aux[AT_GID]==aux[AT_EGID]; |
|
|
|
|
|
|
|
|
|
|
|
head = tail = &app; |
|
|
head = tail = &app; |
|
|
libc = &lib; |
|
|
libc = &lib; |
|
|
app.next = 0; |
|
|
app.next = 0; |
|
|
@ -398,6 +421,7 @@ void *__dynlink(int argc, char **argv, size_t *got) |
|
|
reloc_all(head); |
|
|
reloc_all(head); |
|
|
|
|
|
|
|
|
free_all(head); |
|
|
free_all(head); |
|
|
|
|
|
free(sys_path); |
|
|
|
|
|
|
|
|
errno = 0; |
|
|
errno = 0; |
|
|
return (void *)aux[AT_ENTRY]; |
|
|
return (void *)aux[AT_ENTRY]; |
|
|
|