add some sanity checks in dynamic loader code

reject elf files which are not ET_EXEC/ET_DYN type as bad exec format,
and reject ET_EXEC files when they cannot be loaded at the correct
address, since they are not relocatable at runtime. the main practical
benefit of this is to make dlopen of the main program fail rather than
producing an unsafe-to-use handle.
This commit is contained in:
Rich Felker 2013-07-31 14:42:08 -04:00
parent c4f49a6a72
commit 339516addb
1 changed files with 10 additions and 0 deletions

View File

@ -320,6 +320,10 @@ static void *map_library(int fd, struct dso *dso)
ssize_t l = read(fd, buf, sizeof buf); ssize_t l = read(fd, buf, sizeof buf);
if (l<(int)sizeof *eh) return 0; if (l<(int)sizeof *eh) return 0;
eh = buf; eh = buf;
if (eh->e_type != ET_DYN && eh->e_type != ET_EXEC) {
errno = ENOEXEC;
return 0;
}
phsize = eh->e_phentsize * eh->e_phnum; phsize = eh->e_phentsize * eh->e_phnum;
if (phsize + sizeof *eh > l) return 0; if (phsize + sizeof *eh > l) return 0;
if (eh->e_phoff + phsize > l) { if (eh->e_phoff + phsize > l) {
@ -362,6 +366,12 @@ static void *map_library(int fd, struct dso *dso)
* amount of virtual address space to map over later. */ * amount of virtual address space to map over later. */
map = mmap((void *)addr_min, map_len, prot, MAP_PRIVATE, fd, off_start); map = mmap((void *)addr_min, map_len, prot, MAP_PRIVATE, fd, off_start);
if (map==MAP_FAILED) return 0; 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; base = map - addr_min;
dso->phdr = 0; dso->phdr = 0;
dso->phnum = 0; dso->phnum = 0;