size_t i;
ssize_t l = read(fd, buf, sizeof buf);
- if (l<sizeof *eh) return 0;
+ if (l<(int)sizeof *eh) return 0;
eh = buf;
+ if (eh->e_type != ET_DYN && eh->e_type != ET_EXEC) {
+ errno = ENOEXEC;
+ return 0;
+ }
phsize = eh->e_phentsize * eh->e_phnum;
if (phsize + sizeof *eh > l) return 0;
if (eh->e_phoff + phsize > l) {
* amount of virtual address space to map over later. */
map = mmap((void *)addr_min, map_len, prot, MAP_PRIVATE, fd, off_start);
if (map==MAP_FAILED) return 0;
+ /* If the loaded file is not relocatable and the requested address is
+ * not available, then the load operation must fail. */
+ if (eh->e_type != ET_DYN && addr_min && map!=(void *)addr_min) {
+ errno = EBUSY;
+ goto error;
+ }
base = map - addr_min;
dso->phdr = 0;
dso->phnum = 0;
struct stat st;
size_t alloc_size;
int n_th = 0;
+ int is_self = 0;
/* Catch and block attempts to reload the implementation itself */
if (name[0]=='l' && name[1]=='i' && name[2]=='b') {
ldso->base);
}
}
- if (!ldso->prev) {
- tail->next = ldso;
- ldso->prev = tail;
- tail = ldso->next ? ldso->next : ldso;
- }
- return ldso;
+ is_self = 1;
}
}
}
+ if (!strcmp(name, ldso->name)) is_self = 1;
+ if (is_self) {
+ if (!ldso->prev) {
+ tail->next = ldso;
+ ldso->prev = tail;
+ tail = ldso->next ? ldso->next : ldso;
+ }
+ return ldso;
+ }
if (strchr(name, '/')) {
pathname = name;
fd = open(name, O_RDONLY|O_CLOEXEC);
while (n--) ((void (*)(void))*--fn)();
}
#ifndef NO_LEGACY_INITFINI
- if (dyn[0] & (1<<DT_FINI))
+ if ((dyn[0] & (1<<DT_FINI)) && dyn[DT_FINI])
((void (*)(void))(p->base + dyn[DT_FINI]))();
#endif
}
fini_head = p;
}
#ifndef NO_LEGACY_INITFINI
- if (dyn[0] & (1<<DT_INIT))
+ if ((dyn[0] & (1<<DT_INIT)) && dyn[DT_INIT])
((void (*)(void))(p->base + dyn[DT_INIT]))();
#endif
if (dyn[0] & (1<<DT_INIT_ARRAY)) {
lib->phdr = (void *)(aux[AT_BASE]+ehdr->e_phoff);
find_map_range(lib->phdr, ehdr->e_phnum, ehdr->e_phentsize, lib);
lib->dynv = (void *)(lib->base + find_dyn(lib->phdr,
- ehdr->e_phnum, ehdr->e_phentsize));
+ ehdr->e_phnum, ehdr->e_phentsize));
decode_dyn(lib);
if (aux[AT_PHDR]) {